/// <summary> /// Initialize non-generic R2RMethods with method signatures from MethodDefHandle, and runtime function indices from MethodDefEntryPoints /// </summary> private void ParseMethodDefEntrypoints(bool[] isEntryPoint) { if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_METHODDEF_ENTRYPOINTS)) { return; } 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(); for (uint rid = 1; rid <= nMethodEntryPoints; rid++) { int offset = 0; if (methodEntryPoints.TryGetAt(Image, rid - 1, ref offset)) { int runtimeFunctionId; FixupCell[] fixups; GetRuntimeFunctionIndexFromOffset(offset, out runtimeFunctionId, out fixups); R2RMethod method = new R2RMethod(R2RMethods.Count, MetadataReader, rid, runtimeFunctionId, null, null, fixups); if (method.EntryPointRuntimeFunctionId < 0 || method.EntryPointRuntimeFunctionId >= isEntryPoint.Length) { throw new BadImageFormatException("EntryPointRuntimeFunctionId out of bounds"); } isEntryPoint[method.EntryPointRuntimeFunctionId] = true; R2RMethods.Add(method); } } }
public static void WriteTo(this R2RMethod theThis, TextWriter writer, DumpOptions options) { writer.WriteLine(theThis.SignatureString); writer.WriteLine($"Handle: 0x{MetadataTokens.GetToken(theThis.MetadataReader, theThis.MethodHandle):X8}"); writer.WriteLine($"Rid: {MetadataTokens.GetRowNumber(theThis.MetadataReader, theThis.MethodHandle)}"); if (!options.Naked) { writer.WriteLine($"EntryPointRuntimeFunctionId: {theThis.EntryPointRuntimeFunctionId}"); } writer.WriteLine($"Number of RuntimeFunctions: {theThis.RuntimeFunctions.Count}"); if (theThis.Fixups != null) { writer.WriteLine($"Number of fixups: {theThis.Fixups.Count()}"); IEnumerable <FixupCell> fixups = theThis.Fixups; if (options.Normalize) { fixups = fixups.OrderBy((fc) => fc.Signature); } foreach (FixupCell cell in fixups) { writer.Write(" "); if (!options.Naked) { writer.Write($"TableIndex {cell.TableIndex}, Offset {cell.CellOffset:X4}: "); } writer.WriteLine(cell.Signature); } } }
/// <summary> /// Returns true if the name/signature/id of <param>method</param> matches <param>query</param> /// </summary> /// <param name="exact">Specifies exact or partial match</param> /// <remarks>Case-insensitive and ignores whitespace</remarks> private bool Match(R2RMethod method, string query, bool exact) { int id; bool isNum = ArgStringToInt(query, out id); bool idMatch = isNum && (method.Rid == id || method.Token == id); bool sigMatch = false; if (exact) { sigMatch = method.Name.Equals(query, StringComparison.OrdinalIgnoreCase); if (!sigMatch) { string sig = method.SignatureString.Replace(" ", ""); string q = query.Replace(" ", ""); int iMatch = sig.IndexOf(q, StringComparison.OrdinalIgnoreCase); sigMatch = (iMatch == 0 || (iMatch > 0 && iMatch == (sig.Length - q.Length) && sig[iMatch - 1] == '.')); } } else { string sig = method.Signature.ReturnType + method.SignatureString.Replace(" ", ""); sigMatch = (sig.IndexOf(query.Replace(" ", ""), StringComparison.OrdinalIgnoreCase) >= 0); } return(idMatch || sigMatch); }
public RuntimeFunction(int id, int startRva, int endRva, int unwindRva, int codeOffset, R2RMethod method, BaseUnwindInfo unwindInfo, BaseGcInfo gcInfo) { Id = id; StartAddress = startRva; UnwindRVA = unwindRva; Method = method; UnwindInfo = unwindInfo; if (endRva != -1) { Size = endRva - startRva; } else if (unwindInfo is x86.UnwindInfo) { Size = (int)((x86.UnwindInfo)unwindInfo).FunctionLength; } else if (unwindInfo is Arm.UnwindInfo) { Size = (int)((Arm.UnwindInfo)unwindInfo).FunctionLength; } else if (unwindInfo is Arm64.UnwindInfo) { Size = (int)((Arm64.UnwindInfo)unwindInfo).FunctionLength; } else if (gcInfo != null) { Size = gcInfo.CodeLength; } CodeOffset = codeOffset; method.GcInfo = gcInfo; }
/// <summary> /// Dumps one R2RMethod. /// </summary> internal override void DumpMethod(R2RMethod method, XmlNode parentNode) { XmlNode methodNode = XmlDocument.CreateNode("element", "Method", ""); AddIndexAttribute(methodNode, $"{method.Rid}"); parentNode.AppendChild(methodNode); Serialize(method, methodNode); if (_gc && method.GcInfo != null) { XmlNode gcNode = XmlDocument.CreateNode("element", "GcInfo", ""); methodNode.AppendChild(gcNode); Serialize(method.GcInfo, gcNode); foreach (GcInfo.GcTransition transition in method.GcInfo.Transitions.Values) { Serialize(transition, gcNode); } if (_raw) { DumpBytes(method.GcInfo.Offset, (uint)method.GcInfo.Size, gcNode, "Raw", false); } } XmlNode rtfsNode = null; rtfsNode = XmlDocument.CreateNode("element", "RuntimeFunctions", ""); methodNode.AppendChild(rtfsNode); foreach (RuntimeFunction runtimeFunction in method.RuntimeFunctions) { DumpRuntimeFunction(runtimeFunction, rtfsNode); } }
/// <summary> /// Dumps one R2RMethod. /// </summary> private void DumpMethod(R2RReader r2r, R2RMethod method) { WriteSubDivider(); _writer.WriteLine(method.ToString()); foreach (RuntimeFunction runtimeFunction in method.RuntimeFunctions) { DumpRuntimeFunction(r2r, runtimeFunction); } }
public RuntimeFunction(int id, int startRva, int endRva, int unwindRva, R2RMethod method) { Id = id; StartAddress = startRva; Size = endRva - startRva; if (endRva == -1) { Size = -1; } UnwindRVA = unwindRva; Method = method; }
/// <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(); } }
public RuntimeFunction(int id, int startRva, int endRva, int unwindRva, R2RMethod method, UnwindInfo unwindInfo, GcInfo gcInfo) { Id = id; StartAddress = startRva; UnwindRVA = unwindRva; Method = method; UnwindInfo = unwindInfo; if (endRva != -1) { Size = endRva - startRva; } else if (gcInfo != null) { Size = gcInfo.CodeLength; } method.GcInfo = gcInfo; }
/// <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(); } }
/// <summary> /// Dumps one R2RMethod. /// </summary> private void DumpMethod(R2RReader r2r, R2RMethod method) { WriteSubDivider(); _writer.WriteLine(method.ToString()); if (_gc) { _writer.WriteLine("GcInfo:"); _writer.Write(method.GcInfo); if (_raw) { DumpBytes(r2r, method.GcInfo.Offset, (uint)method.GcInfo.Size); } } _writer.WriteLine(); foreach (RuntimeFunction runtimeFunction in method.RuntimeFunctions) { DumpRuntimeFunction(r2r, runtimeFunction); } }
/// <summary> /// Dumps one R2RMethod. /// </summary> internal override void DumpMethod(R2RMethod method) { WriteSubDivider(); method.WriteTo(_writer, _options); if (_options.GC && method.GcInfo != null) { _writer.WriteLine("GcInfo:"); _writer.Write(method.GcInfo); if (_options.Raw) { DumpBytes(method.GcInfo.Offset, (uint)method.GcInfo.Size, "", false); } } SkipLine(); foreach (RuntimeFunction runtimeFunction in method.RuntimeFunctions) { DumpRuntimeFunction(runtimeFunction); } }
/// <summary> /// Dumps one R2RMethod. /// </summary> internal override void DumpMethod(R2RMethod method, XmlNode parentNode = null) { WriteSubDivider(); _writer.WriteLine(method.ToString()); if (_gc && method.GcInfo != null) { _writer.WriteLine("GcInfo:"); _writer.Write(method.GcInfo); if (_raw) { DumpBytes(method.GcInfo.Offset, (uint)method.GcInfo.Size, null, "", false); } } SkipLine(); foreach (RuntimeFunction runtimeFunction in method.RuntimeFunctions) { DumpRuntimeFunction(runtimeFunction); } }
/// <summary> /// Initialize non-generic R2RMethods with method signatures from MethodDefHandle, and runtime function indices from MethodDefEntryPoints /// </summary> private void ParseMethodDefEntrypoints(bool[] isEntryPoint) { 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(); for (uint rid = 1; rid <= nMethodEntryPoints; rid++) { int offset = 0; if (methodEntryPoints.TryGetAt(Image, rid - 1, ref offset)) { R2RMethod method = new R2RMethod(_mdReader, rid, GetEntryPointIdFromOffset(offset), null, null); if (method.EntryPointRuntimeFunctionId < 0 || method.EntryPointRuntimeFunctionId >= isEntryPoint.Length) { throw new BadImageFormatException("EntryPointRuntimeFunctionId out of bounds"); } isEntryPoint[method.EntryPointRuntimeFunctionId] = true; R2RMethods.Add(method); } } }
/// <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]); } } } }
/// <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]); } } } }
/// <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(); } }
public InstanceMethod(byte bucket, R2RMethod method) { Bucket = bucket; Method = method; }
abstract internal void DumpMethod(R2RMethod method, XmlNode parentNode = null);
abstract internal void DumpMethod(R2RMethod method);