Beispiel #1
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();
                }
            }
        }
Beispiel #2
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 peReader = new PEReader(p, _image.Length);

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

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

                SectionHeader textSection;
                int           nSections = peReader.PEHeaders.CoffHeader.NumberOfSections;

                for (int i = 0; i < nSections; i++)
                {
                    SectionHeader section = peReader.PEHeaders.SectionHeaders[i];
                    if (section.Name.Equals(".text"))
                    {
                        textSection = section;
                    }
                }

                DirectoryEntry r2rHeaderDirectory = peReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
                int            r2rHeaderOffset    = r2rHeaderDirectory.RelativeVirtualAddress - textSection.VirtualAddress + textSection.PointerToRawData;

                R2RHeader = new R2RHeader(_image, (uint)r2rHeaderDirectory.RelativeVirtualAddress, r2rHeaderOffset);
                if (r2rHeaderDirectory.Size != R2RHeader.Size)
                {
                    throw new System.BadImageFormatException("The calculated size of the R2RHeader doesn't match the size saved in the ManagedNativeHeaderDirectory");
                }
            }
        }
Beispiel #3
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)
                {
                    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]);
                    }
                }
            }
        }
Beispiel #4
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();
                }
            }
        }
Beispiel #5
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();
        }
Beispiel #6
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]);
                    }
                }
            }
        }