/// <summary> /// Parse a single available types section. For composite R2R images this method is called multiple times /// as available types are stored separately for each component assembly of the composite R2R executable. /// </summary> /// <param name="availableTypesSection"></param> private void ParseAvailableTypesSection(ReadyToRunSection availableTypesSection, MetadataReader metadataReader) { int availableTypesOffset = GetOffset(availableTypesSection.RelativeVirtualAddress); NativeParser parser = new NativeParser(Image, (uint)availableTypesOffset); NativeHashtable availableTypes = new NativeHashtable(Image, parser, (uint)(availableTypesOffset + availableTypesSection.Size)); NativeHashtable.AllEntriesEnumerator allEntriesEnum = availableTypes.EnumerateAllEntries(); NativeParser curParser = allEntriesEnum.GetNext(); while (!curParser.IsNull()) { uint rid = curParser.GetUnsigned(); bool isExportedType = (rid & 1) != 0; rid = rid >> 1; if (isExportedType) { ExportedTypeHandle exportedTypeHandle = MetadataTokens.ExportedTypeHandle((int)rid); string exportedTypeName = GetExportedTypeFullName(metadataReader, exportedTypeHandle); _availableTypes.Add("exported " + exportedTypeName); } else { TypeDefinitionHandle typeDefHandle = MetadataTokens.TypeDefinitionHandle((int)rid); string typeDefName = MetadataNameFormatter.FormatHandle(metadataReader, typeDefHandle); _availableTypes.Add(typeDefName); } curParser = allEntriesEnum.GetNext(); } }
/// <summary> /// Read the EH clause from a given file offset in the PE image. /// </summary> /// <param name="reader">R2R image reader<param> /// <param name="offset">Offset of the EH clause in the image</param> public EHClause(R2RReader reader, int offset) { Flags = (CorExceptionFlag)BitConverter.ToUInt32(reader.Image, offset + 0 * sizeof(uint)); TryOffset = BitConverter.ToUInt32(reader.Image, offset + 1 * sizeof(uint)); TryEnd = BitConverter.ToUInt32(reader.Image, offset + 2 * sizeof(uint)); HandlerOffset = BitConverter.ToUInt32(reader.Image, offset + 3 * sizeof(uint)); HandlerEnd = BitConverter.ToUInt32(reader.Image, offset + 4 * sizeof(uint)); ClassTokenOrFilterOffset = BitConverter.ToUInt32(reader.Image, offset + 5 * sizeof(uint)); if ((Flags & CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_KIND_MASK) == CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_NONE) { ClassName = MetadataNameFormatter.FormatHandle(reader.MetadataReader, MetadataTokens.Handle((int)ClassTokenOrFilterOffset)); } }
/// <summary> /// Read the EH clause from a given file offset in the PE image. /// </summary> /// <param name="reader">R2R image reader<param> /// <param name="offset">Offset of the EH clause in the image</param> public EHClause(ReadyToRunReader reader, int offset) { Flags = (CorExceptionFlag)BitConverter.ToUInt32(reader.Image, offset + 0 * sizeof(uint)); TryOffset = BitConverter.ToUInt32(reader.Image, offset + 1 * sizeof(uint)); TryEnd = BitConverter.ToUInt32(reader.Image, offset + 2 * sizeof(uint)); HandlerOffset = BitConverter.ToUInt32(reader.Image, offset + 3 * sizeof(uint)); HandlerEnd = BitConverter.ToUInt32(reader.Image, offset + 4 * sizeof(uint)); ClassTokenOrFilterOffset = BitConverter.ToUInt32(reader.Image, offset + 5 * sizeof(uint)); if ((Flags & CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_KIND_MASK) == CorExceptionFlag.COR_ILEXCEPTION_CLAUSE_NONE) { if (reader.Composite) { // TODO: EH clauses in composite mode ClassName = "TODO-composite module in EH clause"; } else { ClassName = MetadataNameFormatter.FormatHandle(reader.GetGlobalMetadata()?.MetadataReader, MetadataTokens.Handle((int)ClassTokenOrFilterOffset)); } } }
/// <summary> /// Iterates through a native hashtable to get all RIDs /// </summary> private void ParseAvailableTypes() { if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES)) { return; } R2RSection availableTypesSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES]; int availableTypesOffset = GetOffset(availableTypesSection.RelativeVirtualAddress); NativeParser parser = new NativeParser(Image, (uint)availableTypesOffset); NativeHashtable availableTypes = new NativeHashtable(Image, parser, (uint)(availableTypesOffset + availableTypesSection.Size)); NativeHashtable.AllEntriesEnumerator allEntriesEnum = availableTypes.EnumerateAllEntries(); NativeParser curParser = allEntriesEnum.GetNext(); while (!curParser.IsNull()) { uint rid = curParser.GetUnsigned(); bool isExportedType = (rid & 1) != 0; rid = rid >> 1; if (isExportedType) { ExportedTypeHandle exportedTypeHandle = MetadataTokens.ExportedTypeHandle((int)rid); string exportedTypeName = GetExportedTypeFullName(MetadataReader, exportedTypeHandle); AvailableTypes.Add("exported " + exportedTypeName); } else { TypeDefinitionHandle typeDefHandle = MetadataTokens.TypeDefinitionHandle((int)rid); string typeDefName = MetadataNameFormatter.FormatHandle(MetadataReader, typeDefHandle); AvailableTypes.Add(typeDefName); } curParser = allEntriesEnum.GetNext(); } }
/// <summary> /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/zap/zapimport.cpp">ZapImportSectionsTable::Save</a> /// </summary> private void EnsureImportSections() { if (_importSections != null) { return; } _importSections = new List <ReadyToRunImportSection>(); _importCellNames = new Dictionary <int, string>(); _importSignatures = new Dictionary <int, ReadyToRunSignature>(); if (!ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.ImportSections, out ReadyToRunSection importSectionsSection)) { return; } int offset = GetOffset(importSectionsSection.RelativeVirtualAddress); int endOffset = offset + importSectionsSection.Size; while (offset < endOffset) { int rva = NativeReader.ReadInt32(Image, ref offset); int sectionOffset = GetOffset(rva); int startOffset = sectionOffset; int size = NativeReader.ReadInt32(Image, ref offset); CorCompileImportFlags flags = (CorCompileImportFlags)NativeReader.ReadUInt16(Image, ref offset); byte type = NativeReader.ReadByte(Image, ref offset); byte entrySize = NativeReader.ReadByte(Image, ref offset); if (entrySize == 0) { switch (Machine) { case Machine.I386: case Machine.ArmThumb2: entrySize = 4; break; case Machine.Amd64: case Machine.Arm64: entrySize = 8; break; default: throw new NotImplementedException(Machine.ToString()); } } int entryCount = 0; if (entrySize != 0) { entryCount = size / entrySize; } int signatureRVA = NativeReader.ReadInt32(Image, ref offset); int signatureOffset = 0; if (signatureRVA != 0) { signatureOffset = GetOffset(signatureRVA); } List <ReadyToRunImportSection.ImportSectionEntry> entries = new List <ReadyToRunImportSection.ImportSectionEntry>(); for (int i = 0; i < entryCount; i++) { int entryOffset = sectionOffset - startOffset; long section = NativeReader.ReadInt64(Image, ref sectionOffset); uint sigRva = NativeReader.ReadUInt32(Image, ref signatureOffset); int sigOffset = GetOffset((int)sigRva); ReadyToRunSignature signature; string cellName = MetadataNameFormatter.FormatSignature(_assemblyResolver, this, sigOffset, out signature); entries.Add(new ReadyToRunImportSection.ImportSectionEntry(entries.Count, entryOffset, entryOffset + rva, section, sigRva, cellName)); _importCellNames.Add(rva + entrySize * i, cellName); _importSignatures.Add(rva + entrySize * i, signature); } int auxDataRVA = NativeReader.ReadInt32(Image, ref offset); int auxDataOffset = 0; if (auxDataRVA != 0) { auxDataOffset = GetOffset(auxDataRVA); } _importSections.Add(new ReadyToRunImportSection(_importSections.Count, this, rva, size, flags, type, entrySize, signatureRVA, entries, auxDataRVA, auxDataOffset, Machine, ReadyToRunHeader.MajorVersion)); } }
/// <summary> /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/zap/zapimport.cpp">ZapImportSectionsTable::Save</a> /// </summary> private void ParseImportSections() { if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS)) { return; } R2RSection importSectionsSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS]; int offset = GetOffset(importSectionsSection.RelativeVirtualAddress); int endOffset = offset + importSectionsSection.Size; while (offset < endOffset) { int rva = NativeReader.ReadInt32(Image, ref offset); int sectionOffset = GetOffset(rva); int startOffset = sectionOffset; int size = NativeReader.ReadInt32(Image, ref offset); CorCompileImportFlags flags = (CorCompileImportFlags)NativeReader.ReadUInt16(Image, ref offset); byte type = NativeReader.ReadByte(Image, ref offset); byte entrySize = NativeReader.ReadByte(Image, ref offset); if (entrySize == 0) { switch (Machine) { case Machine.I386: case Machine.ArmThumb2: entrySize = 4; break; case Machine.Amd64: case Machine.Arm64: entrySize = 8; break; default: throw new NotImplementedException(Machine.ToString()); } } int entryCount = 0; if (entrySize != 0) { entryCount = size / entrySize; } int signatureRVA = NativeReader.ReadInt32(Image, ref offset); int signatureOffset = 0; if (signatureRVA != 0) { signatureOffset = GetOffset(signatureRVA); } List <R2RImportSection.ImportSectionEntry> entries = new List <R2RImportSection.ImportSectionEntry>(); for (int i = 0; i < entryCount; i++) { int entryOffset = sectionOffset - startOffset; long section = NativeReader.ReadInt64(Image, ref sectionOffset); uint sigRva = NativeReader.ReadUInt32(Image, ref signatureOffset); int sigOffset = GetOffset((int)sigRva); string cellName = MetadataNameFormatter.FormatSignature(_assemblyResolver, this, sigOffset); entries.Add(new R2RImportSection.ImportSectionEntry(entries.Count, entryOffset, entryOffset + rva, section, sigRva, cellName)); ImportCellNames.Add(rva + entrySize * i, cellName); } int auxDataRVA = NativeReader.ReadInt32(Image, ref offset); int auxDataOffset = 0; if (auxDataRVA != 0) { auxDataOffset = GetOffset(auxDataRVA); } ImportSections.Add(new R2RImportSection(ImportSections.Count, this, rva, size, flags, type, entrySize, signatureRVA, entries, auxDataRVA, auxDataOffset, Machine, R2RHeader.MajorVersion)); } }
/// <summary> /// Extracts the method signature from the metadata by rid /// </summary> public ReadyToRunMethod( ReadyToRunReader readyToRunReader, IAssemblyMetadata componentReader, EntityHandle methodHandle, int entryPointId, string owningType, string constrainedType, string[] instanceArgs, int?fixupOffset) { _readyToRunReader = readyToRunReader; _fixupOffset = fixupOffset; MethodHandle = methodHandle; EntryPointRuntimeFunctionId = entryPointId; ComponentReader = componentReader; EntityHandle owningTypeHandle; GenericParameterHandleCollection genericParams = default(GenericParameterHandleCollection); DisassemblingGenericContext genericContext = new DisassemblingGenericContext(typeParameters: Array.Empty <string>(), methodParameters: instanceArgs); DisassemblingTypeProvider typeProvider = new DisassemblingTypeProvider(); // get the method signature from the method handle switch (MethodHandle.Kind) { case HandleKind.MethodDefinition: { MethodDefinition methodDef = ComponentReader.MetadataReader.GetMethodDefinition((MethodDefinitionHandle)MethodHandle); if (methodDef.RelativeVirtualAddress != 0) { MethodBodyBlock mbb = ComponentReader.ImageReader.GetMethodBody(methodDef.RelativeVirtualAddress); if (!mbb.LocalSignature.IsNil) { StandaloneSignature ss = ComponentReader.MetadataReader.GetStandaloneSignature(mbb.LocalSignature); LocalSignature = ss.DecodeLocalSignature(typeProvider, genericContext); } } Name = ComponentReader.MetadataReader.GetString(methodDef.Name); Signature = methodDef.DecodeSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = methodDef.GetDeclaringType(); genericParams = methodDef.GetGenericParameters(); } break; case HandleKind.MemberReference: { MemberReference memberRef = ComponentReader.MetadataReader.GetMemberReference((MemberReferenceHandle)MethodHandle); Name = ComponentReader.MetadataReader.GetString(memberRef.Name); Signature = memberRef.DecodeMethodSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = memberRef.Parent; } break; default: throw new NotImplementedException(); } if (owningType != null) { DeclaringType = owningType; } else { DeclaringType = MetadataNameFormatter.FormatHandle(ComponentReader.MetadataReader, owningTypeHandle); } StringBuilder sb = new StringBuilder(); sb.Append(Signature.ReturnType); sb.Append(" "); sb.Append(DeclaringType); sb.Append("."); sb.Append(Name); if (Signature.GenericParameterCount != 0) { sb.Append("<"); for (int i = 0; i < Signature.GenericParameterCount; i++) { if (i > 0) { sb.Append(", "); } if (instanceArgs != null && instanceArgs.Length > i) { sb.Append(instanceArgs[i]); } else { sb.Append("!"); sb.Append(i); } } sb.Append(">"); } sb.Append("("); for (int i = 0; i < Signature.ParameterTypes.Length; i++) { if (i > 0) { sb.Append(", "); } sb.AppendFormat($"{Signature.ParameterTypes[i]}"); } sb.Append(")"); SignatureString = sb.ToString(); }
public PgoInfoKey(IAssemblyMetadata componentReader, string owningType, EntityHandle methodHandle, string[] instanceArgs) { ComponentReader = componentReader; EntityHandle owningTypeHandle; DisassemblingGenericContext genericContext = new DisassemblingGenericContext(typeParameters: Array.Empty <string>(), methodParameters: instanceArgs); DisassemblingTypeProvider typeProvider = new DisassemblingTypeProvider(); MethodHandle = methodHandle; // get the method signature from the method handle switch (MethodHandle.Kind) { case HandleKind.MethodDefinition: { MethodDefinition methodDef = componentReader.MetadataReader.GetMethodDefinition((MethodDefinitionHandle)MethodHandle); Name = componentReader.MetadataReader.GetString(methodDef.Name); Signature = methodDef.DecodeSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = methodDef.GetDeclaringType(); } break; case HandleKind.MemberReference: { MemberReference memberRef = componentReader.MetadataReader.GetMemberReference((MemberReferenceHandle)MethodHandle); Name = componentReader.MetadataReader.GetString(memberRef.Name); Signature = memberRef.DecodeMethodSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = memberRef.Parent; } break; default: throw new NotImplementedException(); } if (owningType != null) { DeclaringType = owningType; } else { DeclaringType = MetadataNameFormatter.FormatHandle(componentReader.MetadataReader, owningTypeHandle); } StringBuilder sb = new StringBuilder(); sb.Append(Signature.ReturnType); sb.Append(" "); sb.Append(DeclaringType); sb.Append("."); sb.Append(Name); if (Signature.GenericParameterCount != 0) { sb.Append("<"); for (int i = 0; i < Signature.GenericParameterCount; i++) { if (i > 0) { sb.Append(", "); } if (instanceArgs != null && instanceArgs.Length > i) { sb.Append(instanceArgs[i]); } else { sb.Append("!"); sb.Append(i); } } sb.Append(">"); } sb.Append("("); for (int i = 0; i < Signature.ParameterTypes.Length; i++) { if (i > 0) { sb.Append(", "); } sb.AppendFormat($"{Signature.ParameterTypes[i]}"); } sb.Append(")"); SignatureString = sb.ToString(); }
public virtual string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind = 0) { return(MetadataNameFormatter.FormatHandle(reader, handle)); }
public virtual string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind = 0) { return(MetadataNameFormatter.FormatHandle(reader, handle)); }
public string GetTypeFromHandle(MetadataReader reader, DisassemblingGenericContext genericContext, EntityHandle handle) { return(MetadataNameFormatter.FormatHandle(reader, handle)); }
public override string GetTypeFromSpecification(MetadataReader reader, DisassemblingGenericContext genericContext, TypeSpecificationHandle handle, byte rawTypeKind) { return(MetadataNameFormatter.FormatHandle(reader, handle)); }
/// <summary> /// Extracts the method signature from the metadata by rid /// </summary> public R2RMethod( int index, MetadataReader metadataReader, EntityHandle methodHandle, int entryPointId, string owningType, string constrainedType, string[] instanceArgs, FixupCell[] fixups) { Index = index; MethodHandle = methodHandle; EntryPointRuntimeFunctionId = entryPointId; MetadataReader = metadataReader; RuntimeFunctions = new List <RuntimeFunction>(); EntityHandle owningTypeHandle; GenericParameterHandleCollection genericParams = default(GenericParameterHandleCollection); DisassemblingGenericContext genericContext = new DisassemblingGenericContext(typeParameters: Array.Empty <string>(), methodParameters: instanceArgs); DisassemblingTypeProvider typeProvider = new DisassemblingTypeProvider(); // get the method signature from the method handle switch (MethodHandle.Kind) { case HandleKind.MethodDefinition: { MethodDefinition methodDef = MetadataReader.GetMethodDefinition((MethodDefinitionHandle)MethodHandle); Name = MetadataReader.GetString(methodDef.Name); Signature = methodDef.DecodeSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = methodDef.GetDeclaringType(); genericParams = methodDef.GetGenericParameters(); } break; case HandleKind.MemberReference: { MemberReference memberRef = MetadataReader.GetMemberReference((MemberReferenceHandle)MethodHandle); Name = MetadataReader.GetString(memberRef.Name); Signature = memberRef.DecodeMethodSignature <string, DisassemblingGenericContext>(typeProvider, genericContext); owningTypeHandle = memberRef.Parent; } break; default: throw new NotImplementedException(); } if (owningType != null) { DeclaringType = owningType; } else { DeclaringType = MetadataNameFormatter.FormatHandle(MetadataReader, owningTypeHandle); } Fixups = fixups; StringBuilder sb = new StringBuilder(); sb.Append(Signature.ReturnType); sb.Append(" "); sb.Append(DeclaringType); sb.Append("."); sb.Append(Name); if (Signature.GenericParameterCount != 0) { sb.Append("<"); for (int i = 0; i < Signature.GenericParameterCount; i++) { if (i > 0) { sb.Append(", "); } if (instanceArgs != null && instanceArgs.Length > i) { sb.Append(instanceArgs[i]); } else { sb.Append("!"); sb.Append(i); } } sb.Append(">"); } sb.Append("("); for (int i = 0; i < Signature.ParameterTypes.Length; i++) { if (i > 0) { sb.Append(", "); } sb.AppendFormat($"{Signature.ParameterTypes[i]}"); } sb.Append(")"); SignatureString = sb.ToString(); }