Beispiel #1
0
        /// <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();
            }
        }
Beispiel #2
0
        /// <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);
                }
            }
        }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
 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;
         }
     }
 }
Beispiel #5
0
        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();
        }
Beispiel #6
0
        /// <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));
        }
Beispiel #7
0
        /// <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);
            }
        }
Beispiel #8
0
 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);
     }
 }
Beispiel #9
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();
            }
        }
Beispiel #10
0
        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);
                    }
                }
            }
        }
Beispiel #11
0
        /// <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;
        }
Beispiel #12
0
        /// <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));
            }
        }
Beispiel #13
0
        /// <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();
            }
        }
Beispiel #14
0
        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();
        }
Beispiel #15
0
        /// <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);
                    }
                }
            }
        }