/// <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> /// Parse a single method def entrypoint section. For composite R2R images, this method is called multiple times /// are method entrypoints are stored separately for each component assembly of the composite R2R executable. /// </summary> /// <param name="section">Method entrypoint section to parse</param> /// <param name="metadataReader">ECMA metadata reader representing this method entrypoint section</param> /// <param name="isEntryPoint">Set to true for each runtime function index representing a method entrypoint</param> private void ParseMethodDefEntrypointsSection(ReadyToRunSection section, MetadataReader metadataReader, bool[] isEntryPoint) { int methodDefEntryPointsOffset = GetOffset(section.RelativeVirtualAddress); NativeArray methodEntryPoints = new NativeArray(Image, (uint)methodDefEntryPointsOffset); uint nMethodEntryPoints = methodEntryPoints.GetCount(); for (uint rid = 1; rid <= nMethodEntryPoints; rid++) { int offset = 0; if (methodEntryPoints.TryGetAt(Image, rid - 1, ref offset)) { EntityHandle methodHandle = MetadataTokens.MethodDefinitionHandle((int)rid); int runtimeFunctionId; int? fixupOffset; GetRuntimeFunctionIndexFromOffset(offset, out runtimeFunctionId, out fixupOffset); ReadyToRunMethod method = new ReadyToRunMethod(this, _methods.Count, metadataReader, methodHandle, runtimeFunctionId, owningType: null, constrainedType: null, instanceArgs: null, fixupOffset: fixupOffset); if (method.EntryPointRuntimeFunctionId < 0 || method.EntryPointRuntimeFunctionId >= isEntryPoint.Length) { throw new BadImageFormatException("EntryPointRuntimeFunctionId out of bounds"); } isEntryPoint[method.EntryPointRuntimeFunctionId] = true; if (!_methods.TryGetValue(section, out List <ReadyToRunMethod> sectionMethods)) { sectionMethods = new List <ReadyToRunMethod>(); _methods.Add(section, sectionMethods); } sectionMethods.Add(method); } } }
private void EnsureRuntimeFunctionToDebugInfo() { if (_runtimeFunctionToDebugInfo != null) { return; } _runtimeFunctionToDebugInfo = new Dictionary <int, DebugInfo>(); if (!ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_DEBUG_INFO)) { return; } ReadyToRunSection debugInfoSection = ReadyToRunHeader.Sections[ReadyToRunSection.SectionType.READYTORUN_SECTION_DEBUG_INFO]; int debugInfoSectionOffset = GetOffset(debugInfoSection.RelativeVirtualAddress); NativeArray debugInfoArray = new NativeArray(Image, (uint)debugInfoSectionOffset); for (uint i = 0; i < debugInfoArray.GetCount(); ++i) { int offset = 0; if (!debugInfoArray.TryGetAt(Image, i, ref offset)) { continue; } var debugInfo = new DebugInfo(this, offset); _runtimeFunctionToDebugInfo.Add((int)i, debugInfo); } }
private unsafe void EnsureExceptionInfo() { if (_runtimeFunctionToEHInfo != null) { return; } _runtimeFunctionToEHInfo = new Dictionary <int, EHInfo>(); if (ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO)) { ReadyToRunSection exceptionInfoSection = ReadyToRunHeader.Sections[ReadyToRunSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO]; int offset = GetOffset(exceptionInfoSection.RelativeVirtualAddress); int length = exceptionInfoSection.Size; int methodRva = BitConverter.ToInt32(Image, offset); int ehInfoRva = BitConverter.ToInt32(Image, offset + sizeof(uint)); while ((length -= 2 * sizeof(uint)) >= 8) { offset += 2 * sizeof(uint); int nextMethodRva = BitConverter.ToInt32(Image, offset); int nextEhInfoRva = BitConverter.ToInt32(Image, offset + sizeof(uint)); _runtimeFunctionToEHInfo.Add(methodRva, new EHInfo(this, ehInfoRva, methodRva, GetOffset(ehInfoRva), (nextEhInfoRva - ehInfoRva) / EHClause.Length)); methodRva = nextMethodRva; ehInfoRva = nextEhInfoRva; } } }
private unsafe void Initialize() { _assemblyCache = new Dictionary <int, MetadataReader>(); if (MetadataReader == null) { byte[] image = File.ReadAllBytes(Filename); Image = image; PEReader = new PEReader(Unsafe.As <byte[], ImmutableArray <byte> >(ref image)); if (!PEReader.HasMetadata) { throw new Exception($"ECMA metadata not found in file '{Filename}'"); } MetadataReader = PEReader.GetMetadataReader(); } else { ImmutableArray <byte> content = PEReader.GetEntireImage().GetContent(); Image = Unsafe.As <ImmutableArray <byte>, byte[]>(ref content); } if ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) == 0) { throw new BadImageFormatException("The file is not a ReadyToRun image"); } // This is a work in progress toward lazy initialization. // Ideally, here should be the end of the Initialize() method ImportSections = new List <ReadyToRunImportSection>(); ImportCellNames = new Dictionary <int, string>(); ParseImportSections(); Methods = new List <ReadyToRunMethod>(); InstanceMethods = new List <InstanceMethod>(); if (ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS)) { int runtimeFunctionSize = CalculateRuntimeFunctionSize(); ReadyToRunSection runtimeFunctionSection = ReadyToRunHeader.Sections[ReadyToRunSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS]; uint nRuntimeFunctions = (uint)(runtimeFunctionSection.Size / runtimeFunctionSize); int runtimeFunctionOffset = GetOffset(runtimeFunctionSection.RelativeVirtualAddress); bool[] isEntryPoint = new bool[nRuntimeFunctions]; // initialize R2RMethods ParseMethodDefEntrypoints(isEntryPoint); ParseInstanceMethodEntrypoints(isEntryPoint); ParseRuntimeFunctions(isEntryPoint, runtimeFunctionOffset, runtimeFunctionSize); } AvailableTypes = new List <string>(); ParseAvailableTypes(); CompilerIdentifier = ParseCompilerIdentifier(); }
/// <summary> /// Converts the bytes in the compiler identifier section to characters in a string /// </summary> private string ParseCompilerIdentifier() { if (!ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER)) { return(""); } ReadyToRunSection compilerIdentifierSection = ReadyToRunHeader.Sections[ReadyToRunSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER]; byte[] identifier = new byte[compilerIdentifierSection.Size - 1]; int identifierOffset = GetOffset(compilerIdentifierSection.RelativeVirtualAddress); Array.Copy(Image, identifierOffset, identifier, 0, compilerIdentifierSection.Size - 1); return(Encoding.UTF8.GetString(identifier)); }
/// <summary> /// Parse core header fields common to global R2R file header and per assembly headers in composite R2R images. /// </summary> /// <param name="image">PE image</param> /// <param name="curOffset">Index in the image byte array to the start of the ReadyToRun core header</param> public void ParseCoreHeader(byte[] image, ref int curOffset) { Flags = NativeReader.ReadUInt32(image, ref curOffset); int nSections = NativeReader.ReadInt32(image, ref curOffset); Sections = new Dictionary <ReadyToRunSectionType, ReadyToRunSection>(); for (int i = 0; i < nSections; i++) { int type = NativeReader.ReadInt32(image, ref curOffset); var sectionType = (ReadyToRunSectionType)type; if (!Enum.IsDefined(typeof(ReadyToRunSectionType), type)) { Console.WriteLine("Warning: Invalid ReadyToRun section type"); } int sectionStartRva = NativeReader.ReadInt32(image, ref curOffset); int sectionLength = NativeReader.ReadInt32(image, ref curOffset); Sections[sectionType] = new ReadyToRunSection(sectionType, sectionStartRva, sectionLength); } }
public int GetAssemblyIndex(ReadyToRunSection section) { EnsureHeader(); if (_composite) { for (int assemblyIndex = 0; assemblyIndex < _readyToRunAssemblyHeaders.Count; assemblyIndex++) { ReadyToRunSection toMatch; if (_readyToRunAssemblyHeaders[assemblyIndex].Sections.TryGetValue(section.Type, out toMatch) && section.RelativeVirtualAddress == toMatch.RelativeVirtualAddress) { return(assemblyIndex); } } return(-1); } else { return(0); } }
/// <summary> /// Iterates through a native hashtable to get all RIDs /// </summary> private void ParseAvailableTypes() { if (!ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES)) { return; } ReadyToRunSection availableTypesSection = ReadyToRunHeader.Sections[ReadyToRunSection.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(); } }
private unsafe void EnsureManifestReferences() { if (_manifestReferences != null) { return; } _manifestReferences = new List <AssemblyReferenceHandle>(); if (ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_MANIFEST_METADATA)) { ReadyToRunSection manifestMetadata = ReadyToRunHeader.Sections[ReadyToRunSection.SectionType.READYTORUN_SECTION_MANIFEST_METADATA]; fixed(byte *image = Image) { _manifestReader = new MetadataReader(image + GetOffset(manifestMetadata.RelativeVirtualAddress), manifestMetadata.Size); int assemblyRefCount = _manifestReader.GetTableRowCount(TableIndex.AssemblyRef); for (int assemblyRefIndex = 1; assemblyRefIndex <= assemblyRefCount; assemblyRefIndex++) { AssemblyReferenceHandle asmRefHandle = MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex); _manifestReferences.Add(asmRefHandle); } } } }
/// <summary> /// Initializes the fields of the R2RHeader /// </summary> /// <param name="image">PE image</param> /// <param name="rva">Relative virtual address of the ReadyToRun header</param> /// <param name="curOffset">Index in the image byte array to the start of the ReadyToRun header</param> /// <exception cref="BadImageFormatException">The signature must be 0x00525452</exception> public ReadyToRunHeader(byte[] image, int rva, int curOffset) { RelativeVirtualAddress = rva; int startOffset = curOffset; byte[] signature = new byte[sizeof(uint) - 1]; // -1 removes the null character at the end of the cstring Array.Copy(image, curOffset, signature, 0, sizeof(uint) - 1); SignatureString = Encoding.UTF8.GetString(signature); Signature = NativeReader.ReadUInt32(image, ref curOffset); if (Signature != READYTORUN_SIGNATURE) { throw new System.BadImageFormatException("Incorrect R2R header signature: " + SignatureString); } MajorVersion = NativeReader.ReadUInt16(image, ref curOffset); MinorVersion = NativeReader.ReadUInt16(image, ref curOffset); Flags = NativeReader.ReadUInt32(image, ref curOffset); int nSections = NativeReader.ReadInt32(image, ref curOffset); Sections = new Dictionary <ReadyToRunSection.SectionType, ReadyToRunSection>(); for (int i = 0; i < nSections; i++) { int type = NativeReader.ReadInt32(image, ref curOffset); var sectionType = (ReadyToRunSection.SectionType)type; if (!Enum.IsDefined(typeof(ReadyToRunSection.SectionType), type)) { // TODO (refactoring) - what should we do? // R2RDump.WriteWarning("Invalid ReadyToRun section type"); } Sections[sectionType] = new ReadyToRunSection(sectionType, NativeReader.ReadInt32(image, ref curOffset), NativeReader.ReadInt32(image, ref curOffset)); } Size = curOffset - startOffset; }
/// <summary> /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/zap/zapimport.cpp">ZapImportSectionsTable::Save</a> /// </summary> private void ParseImportSections() { if (!ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS)) { return; } ReadyToRunSection importSectionsSection = ReadyToRunHeader.Sections[ReadyToRunSection.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 <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); string cellName = MetadataNameFormatter.FormatSignature(_assemblyResolver, this, sigOffset); entries.Add(new ReadyToRunImportSection.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 ReadyToRunImportSection(ImportSections.Count, this, rva, size, flags, type, entrySize, signatureRVA, entries, auxDataRVA, auxDataOffset, Machine, ReadyToRunHeader.MajorVersion)); } }
/// <summary> /// Initialize generic method instances with argument types and runtime function indices from InstanceMethodEntrypoints /// </summary> private void ParseInstanceMethodEntrypoints(bool[] isEntryPoint) { if (!ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS)) { return; } ReadyToRunSection instMethodEntryPointSection = ReadyToRunHeader.Sections[ReadyToRunSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS]; int instMethodEntryPointsOffset = GetOffset(instMethodEntryPointSection.RelativeVirtualAddress); NativeParser parser = new NativeParser(Image, (uint)instMethodEntryPointsOffset); NativeHashtable instMethodEntryPoints = new NativeHashtable(Image, parser, (uint)(instMethodEntryPointsOffset + instMethodEntryPointSection.Size)); NativeHashtable.AllEntriesEnumerator allEntriesEnum = instMethodEntryPoints.EnumerateAllEntries(); NativeParser curParser = allEntriesEnum.GetNext(); while (!curParser.IsNull()) { SignatureDecoder decoder = new SignatureDecoder(_assemblyResolver, this, (int)curParser.Offset); MetadataReader mdReader = MetadataReader; string owningType = null; uint methodFlags = decoder.ReadUInt(); if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType) != 0) { mdReader = decoder.GetMetadataReaderFromModuleOverride(); owningType = decoder.ReadTypeSignatureNoEmit(); } if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_SlotInsteadOfToken) != 0) { throw new NotImplementedException(); } EntityHandle methodHandle; int rid = (int)decoder.ReadUInt(); if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_MemberRefToken) != 0) { methodHandle = MetadataTokens.MemberReferenceHandle(rid); } else { methodHandle = MetadataTokens.MethodDefinitionHandle(rid); } string[] methodTypeArgs = null; if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_MethodInstantiation) != 0) { uint typeArgCount = decoder.ReadUInt(); methodTypeArgs = new string[typeArgCount]; for (int typeArgIndex = 0; typeArgIndex < typeArgCount; typeArgIndex++) { methodTypeArgs[typeArgIndex] = decoder.ReadTypeSignatureNoEmit(); } } string constrainedType = null; if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_Constrained) != 0) { constrainedType = decoder.ReadTypeSignatureNoEmit(); } int runtimeFunctionId; FixupCell[] fixups; GetRuntimeFunctionIndexFromOffset((int)decoder.Offset, out runtimeFunctionId, out fixups); ReadyToRunMethod method = new ReadyToRunMethod( R2RMethods.Count, mdReader == null ? MetadataReader : mdReader, methodHandle, runtimeFunctionId, owningType, constrainedType, methodTypeArgs, fixups); if (method.EntryPointRuntimeFunctionId >= 0 && method.EntryPointRuntimeFunctionId < isEntryPoint.Length) { isEntryPoint[method.EntryPointRuntimeFunctionId] = true; } R2RMethods.Add(method); InstanceMethods.Add(new InstanceMethod(curParser.LowHashcode, method)); curParser = allEntriesEnum.GetNext(); } }
private unsafe void Initialize() { _assemblyCache = new Dictionary <int, MetadataReader>(); this._manifestReferences = new List <AssemblyReferenceHandle>(); if (MetadataReader == null) { byte[] image = File.ReadAllBytes(Filename); Image = image; PEReader = new PEReader(Unsafe.As <byte[], ImmutableArray <byte> >(ref image)); if (!PEReader.HasMetadata) { throw new Exception($"ECMA metadata not found in file '{Filename}'"); } MetadataReader = PEReader.GetMetadataReader(); } else { ImmutableArray <byte> content = PEReader.GetEntireImage().GetContent(); Image = Unsafe.As <ImmutableArray <byte>, byte[]>(ref content); } if ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) == 0) { throw new BadImageFormatException("The file is not a ReadyToRun image"); } // This is a work in progress toward lazy initialization. // Ideally, here should be the end of the Initialize() method EnsureHeader(); EnsureRuntimeFunctionToDebugInfo(); if (ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_MANIFEST_METADATA)) { ReadyToRunSection manifestMetadata = ReadyToRunHeader.Sections[ReadyToRunSection.SectionType.READYTORUN_SECTION_MANIFEST_METADATA]; fixed(byte *image = Image) { _manifestReader = new MetadataReader(image + GetOffset(manifestMetadata.RelativeVirtualAddress), manifestMetadata.Size); int assemblyRefCount = _manifestReader.GetTableRowCount(TableIndex.AssemblyRef); for (int assemblyRefIndex = 1; assemblyRefIndex <= assemblyRefCount; assemblyRefIndex++) { AssemblyReferenceHandle asmRefHandle = MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex); _manifestReferences.Add(asmRefHandle); } } } if (ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO)) { ReadyToRunSection exceptionInfoSection = ReadyToRunHeader.Sections[ReadyToRunSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO]; EHLookupTable = new EHLookupTable(Image, GetOffset(exceptionInfoSection.RelativeVirtualAddress), exceptionInfoSection.Size); } ImportSections = new List <ReadyToRunImportSection>(); ImportCellNames = new Dictionary <int, string>(); ParseImportSections(); R2RMethods = new List <ReadyToRunMethod>(); InstanceMethods = new List <InstanceMethod>(); if (ReadyToRunHeader.Sections.ContainsKey(ReadyToRunSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS)) { int runtimeFunctionSize = CalculateRuntimeFunctionSize(); ReadyToRunSection runtimeFunctionSection = ReadyToRunHeader.Sections[ReadyToRunSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS]; uint nRuntimeFunctions = (uint)(runtimeFunctionSection.Size / runtimeFunctionSize); int runtimeFunctionOffset = GetOffset(runtimeFunctionSection.RelativeVirtualAddress); bool[] isEntryPoint = new bool[nRuntimeFunctions]; // initialize R2RMethods ParseMethodDefEntrypoints(isEntryPoint); ParseInstanceMethodEntrypoints(isEntryPoint); ParseRuntimeFunctions(isEntryPoint, runtimeFunctionOffset, runtimeFunctionSize); } AvailableTypes = new List <string>(); ParseAvailableTypes(); CompilerIdentifier = ParseCompilerIdentifier(); }
/// <summary> /// Parse a single method def entrypoint section. For composite R2R images, this method is called multiple times /// are method entrypoints are stored separately for each component assembly of the composite R2R executable. /// </summary> /// <param name="section">Method entrypoint section to parse</param> /// <param name="metadataReader">ECMA metadata reader representing this method entrypoint section</param> /// <param name="isEntryPoint">Set to true for each runtime function index representing a method entrypoint</param> private void ParseMethodDefEntrypointsSectionCustom <TType, TMethod, TGenericContext>(IR2RSignatureTypeProvider <TType, TMethod, TGenericContext> provider, Dictionary <TMethod, ReadyToRunMethod> foundMethods, ReadyToRunSection section, IAssemblyMetadata metadataReader) { int methodDefEntryPointsOffset = GetOffset(section.RelativeVirtualAddress); NativeArray methodEntryPoints = new NativeArray(Image, (uint)methodDefEntryPointsOffset); uint nMethodEntryPoints = methodEntryPoints.GetCount(); for (uint rid = 1; rid <= nMethodEntryPoints; rid++) { int offset = 0; if (methodEntryPoints.TryGetAt(Image, rid - 1, ref offset)) { EntityHandle methodHandle = MetadataTokens.MethodDefinitionHandle((int)rid); int runtimeFunctionId; int? fixupOffset; GetRuntimeFunctionIndexFromOffset(offset, out runtimeFunctionId, out fixupOffset); ReadyToRunMethod r2rMethod = _runtimeFunctionToMethod[runtimeFunctionId]; var customMethod = provider.GetMethodFromMethodDef(metadataReader.MetadataReader, MetadataTokens.MethodDefinitionHandle((int)rid), default(TType)); if (!Object.ReferenceEquals(customMethod, null) && !foundMethods.ContainsKey(customMethod)) { foundMethods.Add(customMethod, r2rMethod); } } } }