예제 #1
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 R2RHeader(byte[] image, uint rva, int curOffset)
        {
            RelativeVirtualAddress = rva;
            Offset = curOffset;

            byte[] signature = new byte[sizeof(uint)];
            Array.Copy(image, curOffset, signature, 0, sizeof(uint));
            SignatureString = System.Text.Encoding.UTF8.GetString(signature);
            Signature       = (uint)GetField(image, ref curOffset, sizeof(uint));
            if (Signature != READYTORUN_SIGNATURE)
            {
                throw new System.BadImageFormatException("Incorrect R2R header signature");
            }

            MajorVersion     = (ushort)GetField(image, ref curOffset, sizeof(ushort));
            MinorVersion     = (ushort)GetField(image, ref curOffset, sizeof(ushort));
            Flags            = (uint)GetField(image, ref curOffset, sizeof(uint));
            NumberOfSections = (uint)GetField(image, ref curOffset, sizeof(uint));

            Sections = new R2RSection[NumberOfSections];
            for (int i = 0; i < NumberOfSections; i++)
            {
                Sections[i] = new R2RSection((int)GetField(image, ref curOffset, sizeof(int)),
                                             (uint)GetField(image, ref curOffset, sizeof(uint)),
                                             (uint)GetField(image, ref curOffset, sizeof(uint)));
            }

            Size = curOffset - Offset;
        }
예제 #2
0
        private void ParseAvailableTypes()
        {
            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);

            NativeHashtable.AllEntriesEnumerator allEntriesEnum = availableTypes.EnumerateAllEntries();
            NativeParser curParser = allEntriesEnum.GetNext();

            while (!curParser.IsNull())
            {
                uint rid = curParser.GetUnsigned();
                rid = rid >> 1;
                TypeDefinitionHandle typeDefHandle = MetadataTokens.TypeDefinitionHandle((int)rid);

                TypeDefinition typeDef = _mdReader.GetTypeDefinition(typeDefHandle);
                string         name    = _mdReader.GetString(typeDef.Name);
                if (!typeDef.Namespace.IsNil)
                {
                    name = _mdReader.GetString(typeDef.Namespace) + "." + name;
                }
                AvailableTypes.Add(name);
                curParser = allEntriesEnum.GetNext();
            }
        }
예제 #3
0
        /// <summary>
        /// Initializes the fields of the R2RHeader and R2RMethods
        /// </summary>
        /// <param name="filename">PE image</param>
        /// <exception cref="BadImageFormatException">The Cor header flag must be ILLibrary</exception>
        public unsafe R2RReader(string filename)
        {
            Filename = filename;
            Image    = File.ReadAllBytes(filename);

            fixed(byte *p = Image)
            {
                IntPtr ptr = (IntPtr)p;

                _peReader = new PEReader(p, Image.Length);

                IsR2R = (_peReader.PEHeaders.CorHeader.Flags == CorFlags.ILLibrary);
                if (!IsR2R)
                {
                    throw new BadImageFormatException("The file is not a ReadyToRun image");
                }

                Machine   = _peReader.PEHeaders.CoffHeader.Machine;
                ImageBase = _peReader.PEHeaders.PEHeader.ImageBase;

                // initialize R2RHeader
                DirectoryEntry r2rHeaderDirectory = _peReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
                int            r2rHeaderOffset    = GetOffset(r2rHeaderDirectory.RelativeVirtualAddress);

                R2RHeader = new R2RHeader(Image, r2rHeaderDirectory.RelativeVirtualAddress, r2rHeaderOffset);
                if (r2rHeaderDirectory.Size != R2RHeader.Size)
                {
                    throw new BadImageFormatException("The calculated size of the R2RHeader doesn't match the size saved in the ManagedNativeHeaderDirectory");
                }

                if (_peReader.HasMetadata)
                {
                    _mdReader = _peReader.GetMetadataReader();

                    R2RMethods = new List <R2RMethod>();
                    if (R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS))
                    {
                        int        runtimeFunctionSize    = CalculateRuntimeFunctionSize();
                        R2RSection runtimeFunctionSection = R2RHeader.Sections[R2RSection.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();

                    CompileIdentifier = ParseCompilerIdentifier();

                    ImportSections = new List <R2RImportSection>();
                    ParseImportSections();
                }
            }
        }
예제 #4
0
파일: XmlDumper.cs 프로젝트: htyu/coreclr
        internal override void DumpSectionContents(R2RSection section, XmlNode parentNode)
        {
            XmlNode contentsNode = XmlDocument.CreateNode("element", "Contents", "");

            parentNode.AppendChild(contentsNode);

            switch (section.Type)
            {
            case R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES:
                int availableTypesId = 0;
                foreach (string name in _r2r.AvailableTypes)
                {
                    AddXMLNode("AvailableType", name, contentsNode, $"{availableTypesId++}");
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS:
                int rtfOffset    = _r2r.GetOffset(section.RelativeVirtualAddress);
                int rtfEndOffset = rtfOffset + section.Size;
                int rtfIndex     = 0;
                while (rtfOffset < rtfEndOffset)
                {
                    uint rva = NativeReader.ReadUInt32(_r2r.Image, ref rtfOffset);
                    AddXMLNode($"id{rtfIndex}", $"0x{rva:X8}", contentsNode, $"{rtfIndex}");
                    rtfIndex++;
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER:
                AddXMLNode("CompilerIdentifier", _r2r.CompilerIdentifier, contentsNode);
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS:
                foreach (R2RImportSection importSection in _r2r.ImportSections)
                {
                    Serialize(importSection, contentsNode);
                    if (_raw && importSection.Entries.Count != 0)
                    {
                        if (importSection.SectionRVA != 0)
                        {
                            DumpBytes(importSection.SectionRVA, (uint)importSection.SectionSize, contentsNode, "SectionBytes");
                        }
                        if (importSection.SignatureRVA != 0)
                        {
                            DumpBytes(importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int), contentsNode, "SignatureBytes");
                        }
                        if (importSection.AuxiliaryDataRVA != 0)
                        {
                            DumpBytes(importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryData.Size, contentsNode, "AuxiliaryDataBytes");
                        }
                    }
                    foreach (R2RImportSection.ImportSectionEntry entry in importSection.Entries)
                    {
                        Serialize(entry, contentsNode);
                    }
                }
                break;
            }
        }
예제 #5
0
파일: R2RDump.cs 프로젝트: zdrsh/coreclr
        /// <summary>
        /// Returns true if the name or value of the ReadyToRunSectionType of <param>section</param> matches <param>query</param>
        /// </summary>
        /// <remarks>Case-insensitive</remarks>
        private bool Match(R2RSection section, string query)
        {
            int    queryInt;
            bool   isNum    = ArgStringToInt(query, out queryInt);
            string typeName = Enum.GetName(typeof(R2RSection.SectionType), section.Type);

            return((isNum && (int)section.Type == queryInt) || typeName.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0);
        }
예제 #6
0
 public static void WriteTo(this R2RSection theThis, TextWriter writer, DumpOptions options)
 {
     writer.WriteLine($"Type:  {Enum.GetName(typeof(R2RSection.SectionType), theThis.Type)} ({theThis.Type:D})");
     if (!options.Naked)
     {
         writer.WriteLine($"RelativeVirtualAddress: 0x{theThis.RelativeVirtualAddress:X8}");
     }
     writer.WriteLine($"Size: {theThis.Size} bytes");
 }
예제 #7
0
 /// <summary>
 /// Dumps one R2RSection
 /// </summary>
 private void DumpSection(R2RReader r2r, R2RSection section)
 {
     WriteSubDivider();
     _writer.WriteLine(section.ToString());
     if (_raw)
     {
         DumpBytes(r2r, section.RelativeVirtualAddress, (uint)section.Size);
     }
 }
예제 #8
0
        private string ParseCompilerIdentifier()
        {
            R2RSection compilerIdentifierSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER];

            byte[] identifier       = new byte[compilerIdentifierSection.Size];
            int    identifierOffset = GetOffset(compilerIdentifierSection.RelativeVirtualAddress);

            Array.Copy(Image, identifierOffset, identifier, 0, compilerIdentifierSection.Size);
            return(Encoding.UTF8.GetString(identifier));
        }
예제 #9
0
        /// <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;
            }

            HashSet <uint> added = new HashSet <uint>();

            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();
                rid = rid >> 1;
                if (added.Contains(rid))
                {
                    continue;
                }

                TypeDefinitionHandle typeDefHandle    = MetadataTokens.TypeDefinitionHandle((int)rid);
                string             typeDefName        = MetadataNameFormatter.FormatHandle(MetadataReader, typeDefHandle);
                ExportedTypeHandle exportedTypeHandle = MetadataTokens.ExportedTypeHandle((int)rid);
                string             exportedTypeName   = GetExportedTypeFullName(MetadataReader, exportedTypeHandle);
                if (typeDefName == null && exportedTypeName == null)
                {
                    R2RDump.WriteWarning($"AvailableType with rid {rid} is not a TypeDef or ExportedType");
                }
                if (typeDefName != null)
                {
                    AvailableTypes.Add(typeDefName);
                    added.Add(rid);
                }
                if (exportedTypeName != null)
                {
                    AvailableTypes.Add("exported " + exportedTypeName);
                    added.Add(rid);
                }

                curParser = allEntriesEnum.GetNext();
            }
        }
예제 #10
0
        /// <summary>
        /// Dumps one R2RSection
        /// </summary>
        internal override void DumpSection(R2RSection section, XmlNode parentNode)
        {
            XmlNode sectionNode = _xmlDocument.CreateNode("element", "Section", "");

            parentNode.AppendChild(sectionNode);
            Serialize(section, sectionNode);

            if (_raw)
            {
                DumpBytes(section.RelativeVirtualAddress, (uint)section.Size, sectionNode);
            }
            if (_sectionContents)
            {
                DumpSectionContents(section, sectionNode);
            }
        }
예제 #11
0
        /// <summary>
        /// Dumps one R2RSection
        /// </summary>
        internal override void DumpSection(R2RSection section, XmlNode parentNode = null)
        {
            WriteSubDivider();
            _writer.WriteLine(section.ToString());

            if (_raw)
            {
                DumpBytes(section.RelativeVirtualAddress, (uint)section.Size);
                SkipLine();
            }
            if (_sectionContents)
            {
                DumpSectionContents(section);
                SkipLine();
            }
        }
예제 #12
0
        /// <summary>
        /// Dumps one R2RSection
        /// </summary>
        internal override void DumpSection(R2RSection section, XmlNode parentNode = null)
        {
            WriteSubDivider();
            section.WriteTo(_writer, _options);

            if (_options.Raw)
            {
                DumpBytes(section.RelativeVirtualAddress, (uint)section.Size);
                SkipLine();
            }
            if (_options.SectionContents)
            {
                DumpSectionContents(section, parentNode);
                SkipLine();
            }
        }
예제 #13
0
        /// <summary>
        /// Initialize generic method instances with argument types and runtime function indices from InstanceMethodEntrypoints
        /// </summary>
        private void ParseInstanceMethodEntrypoints(bool[] isEntryPoint)
        {
            if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS))
            {
                return;
            }
            R2RSection      instMethodEntryPointSection = R2RHeader.Sections[R2RSection.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())
            {
                uint methodFlags = curParser.GetCompressedData();
                uint rid         = curParser.GetCompressedData();
                if ((methodFlags & (byte)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_MethodInstantiation) != 0)
                {
                    uint             nArgs  = curParser.GetCompressedData();
                    CorElementType[] args   = new CorElementType[nArgs];
                    uint[]           tokens = new uint[nArgs];
                    for (int i = 0; i < nArgs; i++)
                    {
                        args[i] = (CorElementType)curParser.GetByte();
                        if (args[i] == CorElementType.ELEMENT_TYPE_VALUETYPE)
                        {
                            tokens[i] = curParser.GetCompressedData();
                            tokens[i] = (tokens[i] >> 2);
                        }
                    }

                    int         runtimeFunctionId;
                    FixupCell[] fixups;
                    GetRuntimeFunctionIndexFromOffset((int)curParser.Offset, out runtimeFunctionId, out fixups);
                    R2RMethod method = new R2RMethod(R2RMethods.Count, MetadataReader, rid, runtimeFunctionId, args, tokens, fixups);
                    if (method.EntryPointRuntimeFunctionId >= 0 && method.EntryPointRuntimeFunctionId < isEntryPoint.Length)
                    {
                        isEntryPoint[method.EntryPointRuntimeFunctionId] = true;
                    }
                    R2RMethods.Add(method);
                }
                curParser = allEntriesEnum.GetNext();
            }
        }
예제 #14
0
        /// <summary>
        /// Dumps one R2RSection
        /// </summary>
        internal override void DumpSection(R2RSection section, XmlNode parentNode)
        {
            XmlNode sectionNode = XmlDocument.CreateNode("element", "Section", "");

            AddXMLAttribute(sectionNode, "Index", $"{section.Type}");

            parentNode.AppendChild(sectionNode);
            Serialize(section, sectionNode);

            if (_options.Raw)
            {
                DumpBytes(section.RelativeVirtualAddress, (uint)section.Size, sectionNode);
            }
            if (_options.SectionContents)
            {
                DumpSectionContents(section, sectionNode);
            }
        }
예제 #15
0
        /// <summary>
        /// Initialize generic method instances with argument types and runtime function indices from InstanceMethodEntrypoints
        /// </summary>
        private void ParseInstanceMethodEntrypoints(bool[] isEntryPoint)
        {
            if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS))
            {
                return;
            }
            R2RSection      instMethodEntryPointSection = R2RHeader.Sections[R2RSection.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())
            {
                uint methodFlags = curParser.GetCompressedData();
                uint rid         = curParser.GetCompressedData();
                if ((methodFlags & (byte)R2RMethod.EncodeMethodSigFlags.ENCODE_METHOD_SIG_MethodInstantiation) != 0)
                {
                    uint nArgs = curParser.GetCompressedData();
                    R2RMethod.GenericElementTypes[] args = new R2RMethod.GenericElementTypes[nArgs];
                    uint[] tokens = new uint[nArgs];
                    for (int i = 0; i < nArgs; i++)
                    {
                        args[i] = (R2RMethod.GenericElementTypes)curParser.GetByte();
                        if (args[i] == R2RMethod.GenericElementTypes.ValueType)
                        {
                            tokens[i] = curParser.GetCompressedData();
                            tokens[i] = (tokens[i] >> 2);
                        }
                    }

                    int       id     = GetEntryPointIdFromOffset((int)curParser.Offset);
                    R2RMethod method = new R2RMethod(_mdReader, rid, id, args, tokens);
                    if (method.EntryPointRuntimeFunctionId >= 0 && method.EntryPointRuntimeFunctionId < isEntryPoint.Length)
                    {
                        isEntryPoint[method.EntryPointRuntimeFunctionId] = true;
                    }
                    R2RMethods.Add(method);
                }
                curParser = allEntriesEnum.GetNext();
            }
        }
예제 #16
0
        private void ParseAvailableTypes()
        {
            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();
                rid = rid >> 1;
                TypeDefinitionHandle typeDefHandle = MetadataTokens.TypeDefinitionHandle((int)rid);
                AvailableTypes.Add(GetTypeDefFullName(_mdReader, typeDefHandle));
                curParser = allEntriesEnum.GetNext();
            }
        }
예제 #17
0
        /// <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();
            }
        }
예제 #18
0
        private void ParseDebugInfo()
        {
            if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_DEBUG_INFO))
            {
                return;
            }

            R2RSection debugInfoSection       = R2RHeader.Sections[R2RSection.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(Image, offset, Machine);
                _runtimeFunctionToDebugInfo.Add((int)i, debugInfo);
            }
        }
예제 #19
0
파일: R2RHeader.cs 프로젝트: v-zhpa/coreclr
        /// <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 R2RHeader(byte[] image, int rva, int curOffset)
        {
            RelativeVirtualAddress = rva;
            int startOffset = curOffset;

            byte[] signature = new byte[sizeof(uint)];
            Array.Copy(image, curOffset, signature, 0, sizeof(uint));
            SignatureString = System.Text.Encoding.UTF8.GetString(signature);
            Signature       = NativeReader.ReadUInt32(image, ref curOffset);
            if (Signature != READYTORUN_SIGNATURE)
            {
                throw new System.BadImageFormatException("Incorrect R2R header signature");
            }

            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 <R2RSection.SectionType, R2RSection>();

            for (int i = 0; i < nSections; i++)
            {
                int type        = NativeReader.ReadInt32(image, ref curOffset);
                var sectionType = (R2RSection.SectionType)type;
                if (!Enum.IsDefined(typeof(R2RSection.SectionType), type))
                {
                    R2RDump.OutputWarning("Invalid ReadyToRun section type");
                }
                Sections[sectionType] = new R2RSection(sectionType,
                                                       NativeReader.ReadInt32(image, ref curOffset),
                                                       NativeReader.ReadInt32(image, ref curOffset));
            }

            Size = curOffset - startOffset;
        }
예제 #20
0
파일: R2RReader.cs 프로젝트: v-zhpa/coreclr
        /// <summary>
        /// Initializes the fields of the R2RHeader
        /// </summary>
        /// <param name="filename">PE image</param>
        /// <exception cref="BadImageFormatException">The Cor header flag must be ILLibrary</exception>
        public unsafe R2RReader(string filename)
        {
            Filename = filename;
            _image   = File.ReadAllBytes(filename);

            fixed(byte *p = _image)
            {
                IntPtr ptr = (IntPtr)p;

                peReader = new PEReader(p, _image.Length);

                IsR2R = (peReader.PEHeaders.CorHeader.Flags == CorFlags.ILLibrary);
                if (!IsR2R)
                {
                    throw new BadImageFormatException("The file is not a ReadyToRun image");
                }

                Machine   = peReader.PEHeaders.CoffHeader.Machine;
                ImageBase = peReader.PEHeaders.PEHeader.ImageBase;

                // initialize R2RHeader
                DirectoryEntry r2rHeaderDirectory = peReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
                int            r2rHeaderOffset    = GetOffset(r2rHeaderDirectory.RelativeVirtualAddress);

                R2RHeader = new R2RHeader(_image, r2rHeaderDirectory.RelativeVirtualAddress, r2rHeaderOffset);
                if (r2rHeaderDirectory.Size != R2RHeader.Size)
                {
                    throw new BadImageFormatException("The calculated size of the R2RHeader doesn't match the size saved in the ManagedNativeHeaderDirectory");
                }

                // initialize R2RMethods
                if (peReader.HasMetadata)
                {
                    MetadataReader mdReader = peReader.GetMetadataReader();

                    int runtimeFunctionSize = 2;
                    if (Machine == Machine.Amd64)
                    {
                        runtimeFunctionSize = 3;
                    }
                    runtimeFunctionSize *= sizeof(int);
                    R2RSection runtimeFunctionSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS];
                    uint       nRuntimeFunctions      = (uint)(runtimeFunctionSection.Size / runtimeFunctionSize);
                    int        runtimeFunctionOffset  = GetOffset(runtimeFunctionSection.RelativeVirtualAddress);
                    bool[]     isEntryPoint           = new bool[nRuntimeFunctions];
                    for (int i = 0; i < nRuntimeFunctions; i++)
                    {
                        isEntryPoint[i] = false;
                    }

                    // initialize R2RMethods with method signatures from MethodDefHandle, and runtime function indices from MethodDefEntryPoints
                    int         methodDefEntryPointsRVA    = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS].RelativeVirtualAddress;
                    int         methodDefEntryPointsOffset = GetOffset(methodDefEntryPointsRVA);
                    NativeArray methodEntryPoints          = new NativeArray(_image, (uint)methodDefEntryPointsOffset);
                    uint        nMethodEntryPoints         = methodEntryPoints.GetCount();
                    R2RMethods = new List <R2RMethod>();
                    for (uint rid = 1; rid <= nMethodEntryPoints; rid++)
                    {
                        int offset = 0;
                        if (methodEntryPoints.TryGetAt(_image, rid - 1, ref offset))
                        {
                            R2RMethod method = new R2RMethod(_image, mdReader, rid, GetEntryPointIdFromOffset(offset), null, null);

                            if (method.EntryPointRuntimeFunctionId < 0 || method.EntryPointRuntimeFunctionId >= nRuntimeFunctions)
                            {
                                throw new BadImageFormatException("EntryPointRuntimeFunctionId out of bounds");
                            }
                            isEntryPoint[method.EntryPointRuntimeFunctionId] = true;
                            R2RMethods.Add(method);
                        }
                    }

                    // instance method table
                    R2RSection      instMethodEntryPointSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS];
                    int             instMethodEntryPointsOffset = GetOffset(instMethodEntryPointSection.RelativeVirtualAddress);
                    NativeParser    parser = new NativeParser(_image, (uint)instMethodEntryPointsOffset);
                    NativeHashtable instMethodEntryPoints = new NativeHashtable(_image, parser);
                    NativeHashtable.AllEntriesEnumerator allEntriesEnum = instMethodEntryPoints.EnumerateAllEntries();
                    NativeParser curParser = allEntriesEnum.GetNext();
                    while (!curParser.IsNull())
                    {
                        byte methodFlags = curParser.GetByte();
                        byte rid         = curParser.GetByte();
                        if ((methodFlags & (byte)R2RMethod.EncodeMethodSigFlags.ENCODE_METHOD_SIG_MethodInstantiation) != 0)
                        {
                            byte nArgs = curParser.GetByte();
                            R2RMethod.GenericElementTypes[] args = new R2RMethod.GenericElementTypes[nArgs];
                            uint[] tokens = new uint[nArgs];
                            for (int i = 0; i < nArgs; i++)
                            {
                                args[i] = (R2RMethod.GenericElementTypes)curParser.GetByte();
                                if (args[i] == R2RMethod.GenericElementTypes.ValueType)
                                {
                                    tokens[i] = curParser.GetByte();
                                    tokens[i] = (tokens[i] >> 2);
                                }
                            }

                            uint id = curParser.GetUnsigned();
                            id = id >> 1;
                            R2RMethod method = new R2RMethod(_image, mdReader, rid, (int)id, args, tokens);
                            if (method.EntryPointRuntimeFunctionId >= 0 && method.EntryPointRuntimeFunctionId < nRuntimeFunctions)
                            {
                                isEntryPoint[method.EntryPointRuntimeFunctionId] = true;
                            }
                            R2RMethods.Add(method);
                        }
                        curParser = allEntriesEnum.GetNext();
                    }

                    // get the RVAs of the runtime functions for each method
                    int curOffset = 0;
                    foreach (R2RMethod method in R2RMethods)
                    {
                        int runtimeFunctionId = method.EntryPointRuntimeFunctionId;
                        if (runtimeFunctionId == -1)
                        {
                            continue;
                        }
                        curOffset = runtimeFunctionOffset + runtimeFunctionId * runtimeFunctionSize;
                        do
                        {
                            int startRva = NativeReader.ReadInt32(_image, ref curOffset);
                            int endRva   = -1;
                            if (Machine == Machine.Amd64)
                            {
                                endRva = NativeReader.ReadInt32(_image, ref curOffset);
                            }
                            int unwindRva = NativeReader.ReadInt32(_image, ref curOffset);

                            method.RuntimeFunctions.Add(new RuntimeFunction(runtimeFunctionId, startRva, endRva, unwindRva));
                            runtimeFunctionId++;
                        }while (runtimeFunctionId < nRuntimeFunctions && !isEntryPoint[runtimeFunctionId]);
                    }
                }
            }
        }
예제 #21
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 (!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.IA64:
                    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(this, sigOffset);
                    entries.Add(new R2RImportSection.ImportSectionEntry(entries.Count, entryOffset, 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, Image, rva, size, flags, type, entrySize, signatureRVA, entries, auxDataRVA, auxDataOffset, Machine, R2RHeader.MajorVersion));
            }
        }
예제 #22
0
        /// <summary>
        /// Initializes the fields of the R2RHeader and R2RMethods
        /// </summary>
        /// <param name="filename">PE image</param>
        /// <exception cref="BadImageFormatException">The Cor header flag must be ILLibrary</exception>
        public unsafe R2RReader(string filename)
        {
            Filename = filename;
            Image    = File.ReadAllBytes(filename);

            fixed(byte *p = Image)
            {
                IntPtr ptr = (IntPtr)p;

                PEReader = new PEReader(p, Image.Length);

                IsR2R = ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) != 0);
                if (!IsR2R)
                {
                    throw new BadImageFormatException("The file is not a ReadyToRun image");
                }

                uint machine = (uint)PEReader.PEHeaders.CoffHeader.Machine;

                OS = OperatingSystem.Unknown;
                foreach (OperatingSystem os in Enum.GetValues(typeof(OperatingSystem)))
                {
                    Machine = (Machine)(machine ^ (uint)os);
                    if (Enum.IsDefined(typeof(Machine), Machine))
                    {
                        OS = os;
                        break;
                    }
                }
                if (OS == OperatingSystem.Unknown)
                {
                    throw new BadImageFormatException($"Invalid Machine: {machine}");
                }
                ImageBase = PEReader.PEHeaders.PEHeader.ImageBase;

                // initialize R2RHeader
                DirectoryEntry r2rHeaderDirectory = PEReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
                int            r2rHeaderOffset    = GetOffset(r2rHeaderDirectory.RelativeVirtualAddress);

                R2RHeader = new R2RHeader(Image, r2rHeaderDirectory.RelativeVirtualAddress, r2rHeaderOffset);
                if (r2rHeaderDirectory.Size != R2RHeader.Size)
                {
                    throw new BadImageFormatException("The calculated size of the R2RHeader doesn't match the size saved in the ManagedNativeHeaderDirectory");
                }

                if (PEReader.HasMetadata)
                {
                    MetadataReader = PEReader.GetMetadataReader();

                    ParseDebugInfo();

                    if (R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO))
                    {
                        R2RSection exceptionInfoSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO];
                        EHLookupTable = new EHLookupTable(Image, GetOffset(exceptionInfoSection.RelativeVirtualAddress), exceptionInfoSection.Size);
                    }

                    R2RMethods = new List <R2RMethod>();
                    if (R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS))
                    {
                        int        runtimeFunctionSize    = CalculateRuntimeFunctionSize();
                        R2RSection runtimeFunctionSection = R2RHeader.Sections[R2RSection.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();

                    ImportSections  = new List <R2RImportSection>();
                    ImportCellNames = new Dictionary <int, string>();
                    ParseImportSections();
                }
            }
        }
예제 #23
0
        internal override void DumpSectionContents(R2RSection section, XmlNode parentNode = null)
        {
            switch (section.Type)
            {
            case R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES:
                if (!_options.Naked)
                {
                    uint            availableTypesSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress);
                    NativeParser    availableTypesParser        = new NativeParser(_r2r.Image, availableTypesSectionOffset);
                    NativeHashtable availableTypes = new NativeHashtable(_r2r.Image, availableTypesParser, (uint)(availableTypesSectionOffset + section.Size));
                    _writer.WriteLine(availableTypes.ToString());
                }

                foreach (string name in _r2r.AvailableTypes)
                {
                    _writer.WriteLine(name);
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS:
                if (!_options.Naked)
                {
                    NativeArray methodEntryPoints = new NativeArray(_r2r.Image, (uint)_r2r.GetOffset(section.RelativeVirtualAddress));
                    _writer.Write(methodEntryPoints.ToString());
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS:
                if (!_options.Naked)
                {
                    uint            instanceSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress);
                    NativeParser    instanceParser        = new NativeParser(_r2r.Image, instanceSectionOffset);
                    NativeHashtable instMethodEntryPoints = new NativeHashtable(_r2r.Image, instanceParser, (uint)(instanceSectionOffset + section.Size));
                    _writer.Write(instMethodEntryPoints.ToString());
                    _writer.WriteLine();
                }
                foreach (InstanceMethod instanceMethod in _r2r.InstanceMethods)
                {
                    _writer.WriteLine($@"0x{instanceMethod.Bucket:X2} -> {instanceMethod.Method.SignatureString}");
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS:
                int rtfOffset    = _r2r.GetOffset(section.RelativeVirtualAddress);
                int rtfEndOffset = rtfOffset + section.Size;
                int rtfIndex     = 0;
                while (rtfOffset < rtfEndOffset)
                {
                    int startRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    int endRva   = -1;
                    if (_r2r.Machine == Machine.Amd64)
                    {
                        endRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    }
                    int unwindRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    _writer.WriteLine($"Index: {rtfIndex}");
                    _writer.WriteLine($"\tStartRva: 0x{startRva:X8}");
                    if (endRva != -1)
                    {
                        _writer.WriteLine($"\tEndRva: 0x{endRva:X8}");
                    }
                    _writer.WriteLine($"\tUnwindRva: 0x{unwindRva:X8}");
                    rtfIndex++;
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER:
                _writer.WriteLine(_r2r.CompilerIdentifier);
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS:
                if (_options.Naked)
                {
                    DumpNakedImportSections();
                }
                else
                {
                    foreach (R2RImportSection importSection in _r2r.ImportSections)
                    {
                        importSection.WriteTo(_writer);
                        if (_options.Raw && importSection.Entries.Count != 0)
                        {
                            if (importSection.SectionRVA != 0)
                            {
                                _writer.WriteLine("Section Bytes:");
                                DumpBytes(importSection.SectionRVA, (uint)importSection.SectionSize);
                            }
                            if (importSection.SignatureRVA != 0)
                            {
                                _writer.WriteLine("Signature Bytes:");
                                DumpBytes(importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int));
                            }
                            if (importSection.AuxiliaryDataRVA != 0 && importSection.AuxiliaryDataSize != 0)
                            {
                                _writer.WriteLine("AuxiliaryData Bytes:");
                                DumpBytes(importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryDataSize);
                            }
                        }
                        foreach (R2RImportSection.ImportSectionEntry entry in importSection.Entries)
                        {
                            entry.WriteTo(_writer, _options);
                            _writer.WriteLine();
                        }
                        _writer.WriteLine();
                    }
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_MANIFEST_METADATA:
                int assemblyRefCount = _r2r.MetadataReader.GetTableRowCount(TableIndex.AssemblyRef);
                _writer.WriteLine($"MSIL AssemblyRef's ({assemblyRefCount} entries):");
                for (int assemblyRefIndex = 1; assemblyRefIndex <= assemblyRefCount; assemblyRefIndex++)
                {
                    AssemblyReference assemblyRef     = _r2r.MetadataReader.GetAssemblyReference(MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex));
                    string            assemblyRefName = _r2r.MetadataReader.GetString(assemblyRef.Name);
                    _writer.WriteLine($"[ID 0x{assemblyRefIndex:X2}]: {assemblyRefName}");
                }

                _writer.WriteLine($"Manifest metadata AssemblyRef's ({_r2r.ManifestReferenceAssemblies.Count} entries):");
                for (int manifestAsmIndex = 0; manifestAsmIndex < _r2r.ManifestReferenceAssemblies.Count; manifestAsmIndex++)
                {
                    _writer.WriteLine($"[ID 0x{manifestAsmIndex + assemblyRefCount + 2:X2}]: {_r2r.ManifestReferenceAssemblies[manifestAsmIndex]}");
                }
                break;
            }
        }
예제 #24
0
        private void DumpSectionContents(R2RReader r2r, R2RSection section)
        {
            switch (section.Type)
            {
            case R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES:
                uint            availableTypesSectionOffset = (uint)r2r.GetOffset(section.RelativeVirtualAddress);
                NativeParser    availableTypesParser        = new NativeParser(r2r.Image, availableTypesSectionOffset);
                NativeHashtable availableTypes = new NativeHashtable(r2r.Image, availableTypesParser, (uint)(availableTypesSectionOffset + section.Size));
                _writer.WriteLine(availableTypes.ToString());

                foreach (string name in r2r.AvailableTypes)
                {
                    _writer.WriteLine(name);
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS:
                NativeArray methodEntryPoints = new NativeArray(r2r.Image, (uint)r2r.GetOffset(section.RelativeVirtualAddress));
                _writer.Write(methodEntryPoints.ToString());
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS:
                uint            instanceSectionOffset = (uint)r2r.GetOffset(section.RelativeVirtualAddress);
                NativeParser    instanceParser        = new NativeParser(r2r.Image, instanceSectionOffset);
                NativeHashtable instMethodEntryPoints = new NativeHashtable(r2r.Image, instanceParser, (uint)(instanceSectionOffset + section.Size));
                _writer.Write(instMethodEntryPoints.ToString());
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS:
                int rtfOffset    = r2r.GetOffset(section.RelativeVirtualAddress);
                int rtfEndOffset = rtfOffset + section.Size;
                int rtfIndex     = 0;
                while (rtfOffset < rtfEndOffset)
                {
                    uint rva = NativeReader.ReadUInt32(r2r.Image, ref rtfOffset);
                    _writer.WriteLine($"{rtfIndex}: 0x{rva:X8}");
                    rtfIndex++;
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER:
                _writer.WriteLine(r2r.CompileIdentifier);
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS:
                foreach (R2RImportSection importSection in r2r.ImportSections)
                {
                    _writer.Write(importSection.ToString());
                    if (_raw && importSection.Entries.Count != 0)
                    {
                        if (importSection.SectionRVA != 0)
                        {
                            _writer.WriteLine("Section Bytes:");
                            DumpBytes(r2r, importSection.SectionRVA, (uint)importSection.SectionSize);
                        }
                        if (importSection.SignatureRVA != 0)
                        {
                            _writer.WriteLine("Signature Bytes:");
                            DumpBytes(r2r, importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int));
                        }
                        if (importSection.AuxiliaryDataRVA != 0)
                        {
                            _writer.WriteLine("AuxiliaryData Bytes:");
                            DumpBytes(r2r, importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryData.Size);
                        }
                    }
                    foreach (R2RImportSection.ImportSectionEntry entry in importSection.Entries)
                    {
                        _writer.WriteLine();
                        _writer.WriteLine(entry.ToString());
                    }
                    _writer.WriteLine();
                }
                break;
            }
        }
예제 #25
0
        /// <summary>
        /// Initializes the fields of the R2RHeader
        /// </summary>
        /// <param name="filename">PE image</param>
        /// <exception cref="BadImageFormatException">The Cor header flag must be ILLibrary</exception>
        public unsafe R2RReader(string filename)
        {
            Filename = filename;
            _image   = File.ReadAllBytes(filename);

            fixed(byte *p = _image)
            {
                IntPtr ptr = (IntPtr)p;

                peReader = new PEReader(p, _image.Length);

                IsR2R = (peReader.PEHeaders.CorHeader.Flags == CorFlags.ILLibrary);
                if (!IsR2R)
                {
                    throw new BadImageFormatException("The file is not a ReadyToRun image");
                }

                Machine   = peReader.PEHeaders.CoffHeader.Machine;
                ImageBase = peReader.PEHeaders.PEHeader.ImageBase;

                // initialize R2RHeader
                DirectoryEntry r2rHeaderDirectory = peReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
                int            r2rHeaderOffset    = GetOffset(r2rHeaderDirectory.RelativeVirtualAddress);

                R2RHeader = new R2RHeader(_image, r2rHeaderDirectory.RelativeVirtualAddress, r2rHeaderOffset);
                if (r2rHeaderDirectory.Size != R2RHeader.Size)
                {
                    throw new BadImageFormatException("The calculated size of the R2RHeader doesn't match the size saved in the ManagedNativeHeaderDirectory");
                }

                // initialize R2RMethods
                if (peReader.HasMetadata)
                {
                    var mdReader = peReader.GetMetadataReader();

                    int runtimeFunctionSize = 2;
                    if (Machine == Machine.Amd64)
                    {
                        runtimeFunctionSize = 3;
                    }
                    runtimeFunctionSize *= sizeof(int);
                    R2RSection runtimeFunctionSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS];
                    uint       nRuntimeFunctions      = (uint)(runtimeFunctionSection.Size / runtimeFunctionSize);
                    int        runtimeFunctionOffset  = GetOffset(runtimeFunctionSection.RelativeVirtualAddress);
                    bool[]     isEntryPoint           = new bool[nRuntimeFunctions];
                    for (int i = 0; i < nRuntimeFunctions; i++)
                    {
                        isEntryPoint[i] = false;
                    }

                    // initialize R2RMethods with method signatures from MethodDefHandle, and runtime function indices from MethodDefEntryPoints
                    int         methodDefEntryPointsRVA    = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS].RelativeVirtualAddress;
                    int         methodDefEntryPointsOffset = GetOffset(methodDefEntryPointsRVA);
                    NativeArray methodEntryPoints          = new NativeArray(_image, (uint)methodDefEntryPointsOffset);
                    uint        nMethodEntryPoints         = methodEntryPoints.GetCount();
                    R2RMethods = new List <R2RMethod>();
                    for (uint rid = 1; rid <= nMethodEntryPoints; rid++)
                    {
                        uint offset = 0;
                        if (methodEntryPoints.TryGetAt(_image, rid - 1, ref offset))
                        {
                            R2RMethod method = new R2RMethod(_image, mdReader, methodEntryPoints, offset, rid);
                            if (method.EntryPointRuntimeFunctionId >= nRuntimeFunctions)
                            {
                                throw new BadImageFormatException("Runtime function id out of bounds");
                            }
                            isEntryPoint[method.EntryPointRuntimeFunctionId] = true;
                            R2RMethods.Add(method);
                        }
                    }

                    // get the RVAs of the runtime functions for each method
                    int runtimeFunctionId = 0;
                    foreach (R2RMethod method in R2RMethods)
                    {
                        int curOffset = (int)(runtimeFunctionOffset + method.EntryPointRuntimeFunctionId * runtimeFunctionSize);
                        do
                        {
                            int startRva = ReadInt32(_image, ref curOffset);
                            int endRva   = -1;
                            if (Machine == Machine.Amd64)
                            {
                                endRva = ReadInt32(_image, ref curOffset);
                            }
                            int unwindRva = ReadInt32(_image, ref curOffset);

                            method.NativeCode.Add(new RuntimeFunction(startRva, endRva, unwindRva));
                            runtimeFunctionId++;
                        }while (runtimeFunctionId < nRuntimeFunctions && !isEntryPoint[runtimeFunctionId]);
                    }
                }
            }
        }
예제 #26
0
        internal override void DumpSectionContents(R2RSection section, XmlNode parentNode = null)
        {
            switch (section.Type)
            {
            case R2RSection.SectionType.READYTORUN_SECTION_AVAILABLE_TYPES:
                uint            availableTypesSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress);
                NativeParser    availableTypesParser        = new NativeParser(_r2r.Image, availableTypesSectionOffset);
                NativeHashtable availableTypes = new NativeHashtable(_r2r.Image, availableTypesParser, (uint)(availableTypesSectionOffset + section.Size));
                _writer.WriteLine(availableTypes.ToString());

                foreach (string name in _r2r.AvailableTypes)
                {
                    _writer.WriteLine(name);
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS:
                NativeArray methodEntryPoints = new NativeArray(_r2r.Image, (uint)_r2r.GetOffset(section.RelativeVirtualAddress));
                _writer.Write(methodEntryPoints.ToString());
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS:
                uint            instanceSectionOffset = (uint)_r2r.GetOffset(section.RelativeVirtualAddress);
                NativeParser    instanceParser        = new NativeParser(_r2r.Image, instanceSectionOffset);
                NativeHashtable instMethodEntryPoints = new NativeHashtable(_r2r.Image, instanceParser, (uint)(instanceSectionOffset + section.Size));
                _writer.Write(instMethodEntryPoints.ToString());
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS:
                int rtfOffset    = _r2r.GetOffset(section.RelativeVirtualAddress);
                int rtfEndOffset = rtfOffset + section.Size;
                int rtfIndex     = 0;
                while (rtfOffset < rtfEndOffset)
                {
                    int startRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    int endRva   = -1;
                    if (_r2r.Machine == Machine.Amd64)
                    {
                        endRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    }
                    int unwindRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                    _writer.WriteLine($"Index: {rtfIndex}");
                    _writer.WriteLine($"\tStartRva: 0x{startRva:X8}");
                    if (endRva != -1)
                    {
                        _writer.WriteLine($"\tEndRva: 0x{endRva:X8}");
                    }
                    _writer.WriteLine($"\tUnwindRva: 0x{unwindRva:X8}");
                    rtfIndex++;
                }
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_COMPILER_IDENTIFIER:
                _writer.WriteLine(_r2r.CompilerIdentifier);
                break;

            case R2RSection.SectionType.READYTORUN_SECTION_IMPORT_SECTIONS:
                foreach (R2RImportSection importSection in _r2r.ImportSections)
                {
                    _writer.Write(importSection.ToString());
                    if (_raw && importSection.Entries.Count != 0)
                    {
                        if (importSection.SectionRVA != 0)
                        {
                            _writer.WriteLine("Section Bytes:");
                            DumpBytes(importSection.SectionRVA, (uint)importSection.SectionSize);
                        }
                        if (importSection.SignatureRVA != 0)
                        {
                            _writer.WriteLine("Signature Bytes:");
                            DumpBytes(importSection.SignatureRVA, (uint)importSection.Entries.Count * sizeof(int));
                        }
                        if (importSection.AuxiliaryDataRVA != 0 && importSection.AuxiliaryData != null)
                        {
                            _writer.WriteLine("AuxiliaryData Bytes:");
                            DumpBytes(importSection.AuxiliaryDataRVA, (uint)importSection.AuxiliaryData.Size);
                        }
                    }
                    foreach (R2RImportSection.ImportSectionEntry entry in importSection.Entries)
                    {
                        _writer.WriteLine(entry.ToString());
                    }
                    _writer.WriteLine();
                }
                break;
            }
        }
예제 #27
0
        /// <summary>
        /// Initializes the fields of the R2RHeader and R2RMethods
        /// </summary>
        /// <param name="filename">PE image</param>
        /// <exception cref="BadImageFormatException">The Cor header flag must be ILLibrary</exception>
        public unsafe R2RReader(DumpOptions options, string filename)
            : base(options, filename, new List <string>())
        {
            IsR2R = ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) != 0);
            if (!IsR2R)
            {
                throw new BadImageFormatException("The file is not a ReadyToRun image");
            }

            uint machine = (uint)PEReader.PEHeaders.CoffHeader.Machine;

            OS = OperatingSystem.Unknown;
            foreach (OperatingSystem os in Enum.GetValues(typeof(OperatingSystem)))
            {
                Machine = (Machine)(machine ^ (uint)os);
                if (Enum.IsDefined(typeof(Machine), Machine))
                {
                    OS = os;
                    break;
                }
            }
            if (OS == OperatingSystem.Unknown)
            {
                throw new BadImageFormatException($"Invalid Machine: {machine}");
            }

            switch (Machine)
            {
            case Machine.I386:
                Architecture = Architecture.X86;
                PointerSize  = 4;
                break;

            case Machine.Amd64:
                Architecture = Architecture.X64;
                PointerSize  = 8;
                break;

            case Machine.Arm:
            case Machine.Thumb:
            case Machine.ArmThumb2:
                Architecture = Architecture.Arm;
                PointerSize  = 4;
                break;

            case Machine.Arm64:
                Architecture = Architecture.Arm64;
                PointerSize  = 8;
                break;

            default:
                throw new NotImplementedException(Machine.ToString());
            }


            ImageBase = PEReader.PEHeaders.PEHeader.ImageBase;

            // initialize R2RHeader
            DirectoryEntry r2rHeaderDirectory = PEReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
            int            r2rHeaderOffset    = GetOffset(r2rHeaderDirectory.RelativeVirtualAddress);

            R2RHeader = new R2RHeader(Image, r2rHeaderDirectory.RelativeVirtualAddress, r2rHeaderOffset);
            if (r2rHeaderDirectory.Size != R2RHeader.Size)
            {
                throw new BadImageFormatException("The calculated size of the R2RHeader doesn't match the size saved in the ManagedNativeHeaderDirectory");
            }

            ParseDebugInfo();

            if (R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_MANIFEST_METADATA))
            {
                R2RSection manifestMetadata = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_MANIFEST_METADATA];
                fixed(byte *image = Image)
                {
                    MetadataReader 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);
                        AssemblyReference       asmRef       = manifestReader.GetAssemblyReference(asmRefHandle);
                        string asmRefName = manifestReader.GetString(asmRef.Name);
                        ManifestReferenceAssemblies.Add(asmRefName);
                    }
                }
            }

            if (R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO))
            {
                R2RSection exceptionInfoSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO];
                EHLookupTable = new EHLookupTable(Image, GetOffset(exceptionInfoSection.RelativeVirtualAddress), exceptionInfoSection.Size);
            }

            ImportSections  = new List <R2RImportSection>();
            ImportCellNames = new Dictionary <int, string>();
            ParseImportSections();

            R2RMethods      = new List <R2RMethod>();
            InstanceMethods = new List <InstanceMethod>();

            if (R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS))
            {
                int        runtimeFunctionSize    = CalculateRuntimeFunctionSize();
                R2RSection runtimeFunctionSection = R2RHeader.Sections[R2RSection.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();
        }
예제 #28
0
        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);
                R2RImportSection.CorCompileImportFlags flags = (R2RImportSection.CorCompileImportFlags)NativeReader.ReadUInt16(Image, ref offset);
                byte type       = NativeReader.ReadByte(Image, ref offset);
                byte entrySize  = NativeReader.ReadByte(Image, ref offset);
                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>();
                switch (flags)
                {
                case R2RImportSection.CorCompileImportFlags.CORCOMPILE_IMPORT_FLAGS_EAGER:
                {
                    int  tempSignatureOffset = signatureOffset;
                    int  firstSigRva         = NativeReader.ReadInt32(Image, ref tempSignatureOffset);
                    uint sigRva = 0;
                    while (sigRva != firstSigRva)
                    {
                        int entryOffset = sectionOffset - startOffset;
                        sigRva = NativeReader.ReadUInt32(Image, ref signatureOffset);
                        long   section         = NativeReader.ReadInt64(Image, ref sectionOffset);
                        int    sigOff          = GetOffset((int)sigRva);
                        int    sigSampleLength = Math.Min(8, Image.Length - sigOff);
                        byte[] signatureSample = new byte[sigSampleLength];
                        Array.Copy(Image, sigOff, signatureSample, 0, sigSampleLength);
                        entries.Add(new R2RImportSection.ImportSectionEntry(entryOffset, section, sigRva, signatureSample));
                    }
                }
                break;

                case R2RImportSection.CorCompileImportFlags.CORCOMPILE_IMPORT_FLAGS_CODE:
                case R2RImportSection.CorCompileImportFlags.CORCOMPILE_IMPORT_FLAGS_PCODE:
                    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    sigOff          = GetOffset((int)sigRva);
                        int    sigSampleLength = Math.Min(8, Image.Length - sigOff);
                        byte[] signatureSample = new byte[sigSampleLength];
                        Array.Copy(Image, sigOff, signatureSample, 0, sigSampleLength);
                        entries.Add(new R2RImportSection.ImportSectionEntry(entryOffset, section, sigRva, signatureSample));
                    }
                    break;
                }

                int auxDataRVA    = NativeReader.ReadInt32(Image, ref offset);
                int auxDataOffset = 0;
                if (auxDataRVA != 0)
                {
                    auxDataOffset = GetOffset(auxDataRVA);
                }
                ImportSections.Add(new R2RImportSection(Image, rva, size, flags, type, entrySize, signatureRVA, entries, auxDataRVA, auxDataOffset, Machine, R2RHeader.MajorVersion));
            }
        }
예제 #29
0
파일: R2RDump.cs 프로젝트: zdrsh/coreclr
 abstract internal void DumpSectionContents(R2RSection section, XmlNode parentNode = null);
예제 #30
0
        /// <summary>
        /// Initialize generic method instances with argument types and runtime function indices from InstanceMethodEntrypoints
        /// </summary>
        private void ParseInstanceMethodEntrypoints(bool[] isEntryPoint)
        {
            if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS))
            {
                return;
            }
            R2RSection      instMethodEntryPointSection = R2RHeader.Sections[R2RSection.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(this, (int)curParser.Offset);

                string owningType = null;

                uint methodFlags = decoder.ReadUInt();
                if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType) != 0)
                {
                    owningType = decoder.ReadTypeSignature();
                }
                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.ReadTypeSignature();
                    }
                }

                string constrainedType = null;
                if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_Constrained) != 0)
                {
                    constrainedType = decoder.ReadTypeSignature();
                }

                int         runtimeFunctionId;
                FixupCell[] fixups;
                GetRuntimeFunctionIndexFromOffset((int)decoder.Offset, out runtimeFunctionId, out fixups);
                R2RMethod method = new R2RMethod(R2RMethods.Count, this, 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();
            }
        }