public readonly uint StackPop;
public readonly GCRefMapEntry[] Entries;
+ public GCRefMap()
+ {
+ }
+
public GCRefMap(uint stackPop, GCRefMapEntry[] entries)
{
StackPop = stackPop;
public bool GC;
public bool SectionContents;
public bool EntryPoints;
+
+ public IReadOnlyList<string> ReferenceAssemblies = Array.Empty<string>();
+ public IReadOnlyList<string> ReferencePaths = Array.Empty<string>();
+ public Dictionary<string, EcmaMetadataReader> AssemblyCache = new Dictionary<string, EcmaMetadataReader>(StringComparer.OrdinalIgnoreCase);
+
+ /// <summary>
+ /// Probing extensions to use when looking up assemblies under reference paths.
+ /// </summary>
+ private readonly static string[] ProbeExtensions = new string[] { ".ni.exe", ".ni.dll", ".exe", ".dll" };
+
+ /// <summary>
+ /// Try to locate a (reference) assembly using the list of explicit reference assemblies
+ /// and the list of reference paths passed to R2RDump.
+ /// </summary>
+ /// <param name="simpleName">Simple name of the assembly to look up</param>
+ /// <param name="parentFile">Name of assembly from which we're performing the lookup</param>
+ /// <returns></returns>
+ public string FindAssembly(string simpleName, string parentFile)
+ {
+ foreach (string refAsm in ReferenceAssemblies)
+ {
+ if (Path.GetFileNameWithoutExtension(refAsm).Equals(simpleName, StringComparison.OrdinalIgnoreCase))
+ {
+ return refAsm;
+ }
+ }
+
+ IEnumerable<string> allRefPaths = new string[] { Path.GetDirectoryName(parentFile) }.Concat(ReferencePaths);
+
+ foreach (string refPath in allRefPaths)
+ {
+ foreach (string extension in ProbeExtensions)
+ {
+ string probeFile = Path.Combine(refPath, simpleName + extension);
+ if (File.Exists(probeFile))
+ {
+ return probeFile;
+ }
+ }
+ }
+
+ return null;
+ }
}
public abstract class Dumper
syntax.DefineOption("naked", ref _options.Naked, "Naked dump suppresses most compilation details like placement addresses");
syntax.DefineOptionList("q|query", ref _queries, "Query method by exact name, signature, row id or token");
syntax.DefineOptionList("k|keyword", ref _keywords, "Search method by keyword");
- syntax.DefineOptionList("r|runtimefunction", ref _runtimeFunctions, ArgStringToInt, "Get one runtime function by id or relative virtual address");
+ syntax.DefineOptionList("f|runtimefunction", ref _runtimeFunctions, ArgStringToInt, "Get one runtime function by id or relative virtual address");
syntax.DefineOptionList("s|section", ref _sections, "Get section by keyword");
syntax.DefineOption("unwind", ref _options.Unwind, "Dump unwindInfo");
syntax.DefineOption("gc", ref _options.GC, "Dump gcInfo and slot table");
syntax.DefineOption("v|verbose", ref verbose, "Dump disassembly, unwindInfo, gcInfo and section contents");
syntax.DefineOption("diff", ref _diff, "Compare two R2R images");
syntax.DefineOption("ignoreSensitive", ref _ignoreSensitive, "Ignores sensitive properties in xml dump to avoid failing tests");
+ syntax.DefineOptionList("r|reference", ref _options.ReferenceAssemblies, "Explicit reference assembly files");
+ syntax.DefineOptionList("rp|referencepath", ref _options.ReferencePaths, "Search paths for reference assemblies");
});
if (verbose)
public string Signature { get; set; }
public GCRefMap GCRefMap { get; set; }
+ public ImportSectionEntry()
+ {
+ }
+
public ImportSectionEntry(int index, int startOffset, int startRVA, long section, uint signatureRVA, string signature)
{
Index = index;
}
}
- public class R2RReader
+ public class EcmaMetadataReader
{
/// <summary>
/// Option are used to specify details of signature formatting.
public readonly MetadataReader MetadataReader;
/// <summary>
+ /// Extra reference assemblies parsed from the manifest metadata.
+ /// Only used by R2R assemblies with larger version bubble.
+ /// The manifest contains extra assembly references created by resolved
+ /// inlines and facades (non-existent in the source MSIL).
+ /// In module overrides, these assembly references are represented
+ /// by indices larger than the number of AssemblyRef rows in MetadataReader.
+ /// The list originates in the top-level R2R image and is copied
+ /// to all reference assemblies for the sake of simplicity.
+ /// </summary>
+ public readonly List<string> ManifestReferenceAssemblies;
+
+ /// <summary>
/// Byte array containing the ReadyToRun image
/// </summary>
public byte[] Image { get; }
public string Filename { get; set; }
/// <summary>
+ /// The default constructor initializes an empty metadata reader.
+ /// </summary>
+ public EcmaMetadataReader()
+ {
+ }
+
+ /// <summary>
+ /// Open an MSIL binary and locate the metadata blob.
+ /// </summary>
+ /// <param name="options">Ambient options to use</param>
+ /// <param name="filename">PE image</param>
+ /// <param name="manifestReferenceAssemblies">List of reference assemblies from the R2R metadata manifest</param>
+ /// <exception cref="BadImageFormatException">The Cor header flag must be ILLibrary</exception>
+ public unsafe EcmaMetadataReader(DumpOptions options, string filename, List<string> manifestReferenceAssemblies)
+ {
+ Options = options;
+ Filename = filename;
+ ManifestReferenceAssemblies = manifestReferenceAssemblies;
+ Image = File.ReadAllBytes(filename);
+
+ fixed (byte* p = Image)
+ {
+ IntPtr ptr = (IntPtr)p;
+ PEReader = new PEReader(p, Image.Length);
+
+ if (!PEReader.HasMetadata)
+ {
+ throw new Exception($"ECMA metadata not found in file '{filename}'");
+ }
+
+ MetadataReader = PEReader.GetMetadataReader();
+ }
+ }
+
+ /// <summary>
+ /// Open a given reference assembly (relative to this ECMA metadata file).
+ /// </summary>
+ /// <param name="refAsmIndex">Reference assembly index</param>
+ /// <returns>EcmaMetadataReader instance representing the reference assembly</returns>
+ public EcmaMetadataReader OpenReferenceAssembly(int refAsmIndex)
+ {
+ if (refAsmIndex == 0)
+ {
+ return this;
+ }
+
+ int assemblyRefCount = MetadataReader.GetTableRowCount(TableIndex.AssemblyRef);
+ string name;
+ if (refAsmIndex <= assemblyRefCount)
+ {
+ AssemblyReference asmRef = MetadataReader.GetAssemblyReference(MetadataTokens.AssemblyReferenceHandle(refAsmIndex));
+ name = MetadataReader.GetString(asmRef.Name);
+ }
+ else
+ {
+ name = ManifestReferenceAssemblies[refAsmIndex - assemblyRefCount - 2];
+ }
+
+ EcmaMetadataReader ecmaReader;
+ if (!Options.AssemblyCache.TryGetValue(name, out ecmaReader))
+ {
+ string assemblyPath = Options.FindAssembly(name, Filename);
+ if (assemblyPath == null)
+ {
+ throw new Exception($"Missing reference assembly: {name}");
+ }
+ ecmaReader = new EcmaMetadataReader(Options, assemblyPath, ManifestReferenceAssemblies);
+ Options.AssemblyCache.Add(name, ecmaReader);
+ }
+ return ecmaReader;
+ }
+ }
+
+ public class R2RReader : EcmaMetadataReader
+ {
+ /// <summary>
/// True if the image is ReadyToRun
/// </summary>
public bool IsR2R { get; set; }
private Dictionary<int, DebugInfo> _runtimeFunctionToDebugInfo = new Dictionary<int, DebugInfo>();
- public unsafe R2RReader() { }
+ public R2RReader() { }
/// <summary>
/// Initializes the fields of the R2RHeader and R2RMethods
/// <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>())
{
- Options = options;
- Filename = filename;
- Image = File.ReadAllBytes(filename);
-
- fixed (byte* p = Image)
+ IsR2R = ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) != 0);
+ if (!IsR2R)
{
- IntPtr ptr = (IntPtr)p;
- PEReader = new PEReader(p, Image.Length);
+ throw new BadImageFormatException("The file is not a ReadyToRun image");
+ }
- IsR2R = ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) != 0);
- if (!IsR2R)
+ 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))
{
- throw new BadImageFormatException("The file is not a ReadyToRun image");
+ OS = os;
+ break;
}
+ }
+ if (OS == OperatingSystem.Unknown)
+ {
+ throw new BadImageFormatException($"Invalid Machine: {machine}");
+ }
- 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;
- switch (Machine)
- {
- case Machine.I386:
- Architecture = Architecture.X86;
- PointerSize = 4;
- break;
+ case Machine.Amd64:
+ Architecture = Architecture.X64;
+ PointerSize = 8;
+ 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.Arm:
- case Machine.Thumb:
- case Machine.ArmThumb2:
- Architecture = Architecture.Arm;
- PointerSize = 4;
- break;
+ case Machine.Arm64:
+ Architecture = Architecture.Arm64;
+ PointerSize = 8;
+ break;
- case Machine.Arm64:
- Architecture = Architecture.Arm64;
- PointerSize = 8;
- break;
+ default:
+ throw new NotImplementedException(Machine.ToString());
+ }
- default:
- throw new NotImplementedException(Machine.ToString());
- }
+ ImageBase = PEReader.PEHeaders.PEHeader.ImageBase;
- 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 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 (PEReader.HasMetadata)
+ 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 = PEReader.GetMetadataReader();
-
- ParseDebugInfo();
-
- if (R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO))
+ MetadataReader manifestReader = new MetadataReader(image + GetOffset(manifestMetadata.RelativeVirtualAddress), manifestMetadata.Size);
+ int assemblyRefCount = manifestReader.GetTableRowCount(TableIndex.AssemblyRef);
+ for (int assemblyRefIndex = 1; assemblyRefIndex <= assemblyRefCount; assemblyRefIndex++)
{
- R2RSection exceptionInfoSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO];
- EHLookupTable = new EHLookupTable(Image, GetOffset(exceptionInfoSection.RelativeVirtualAddress), exceptionInfoSection.Size);
+ AssemblyReferenceHandle asmRefHandle = MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex);
+ AssemblyReference asmRef = manifestReader.GetAssemblyReference(asmRefHandle);
+ string asmRefName = manifestReader.GetString(asmRef.Name);
+ ManifestReferenceAssemblies.Add(asmRefName);
}
+ }
+ }
- 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_EXCEPTION_INFO))
+ {
+ R2RSection exceptionInfoSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_EXCEPTION_INFO];
+ EHLookupTable = new EHLookupTable(Image, GetOffset(exceptionInfoSection.RelativeVirtualAddress), exceptionInfoSection.Size);
+ }
- if (R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS))
- {
- int runtimeFunctionSize = CalculateRuntimeFunctionSize();
- R2RSection runtimeFunctionSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS];
+ ImportSections = new List<R2RImportSection>();
+ ImportCellNames = new Dictionary<int, string>();
+ ParseImportSections();
- uint nRuntimeFunctions = (uint)(runtimeFunctionSection.Size / runtimeFunctionSize);
- int runtimeFunctionOffset = GetOffset(runtimeFunctionSection.RelativeVirtualAddress);
- bool[] isEntryPoint = new bool[nRuntimeFunctions];
+ R2RMethods = new List<R2RMethod>();
+ InstanceMethods = new List<InstanceMethod>();
- // initialize R2RMethods
- ParseMethodDefEntrypoints(isEntryPoint);
- ParseInstanceMethodEntrypoints(isEntryPoint);
- ParseRuntimeFunctions(isEntryPoint, runtimeFunctionOffset, runtimeFunctionSize);
- }
+ if (R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS))
+ {
+ int runtimeFunctionSize = CalculateRuntimeFunctionSize();
+ R2RSection runtimeFunctionSection = R2RHeader.Sections[R2RSection.SectionType.READYTORUN_SECTION_RUNTIME_FUNCTIONS];
- AvailableTypes = new List<string>();
- ParseAvailableTypes();
+ uint nRuntimeFunctions = (uint)(runtimeFunctionSection.Size / runtimeFunctionSize);
+ int runtimeFunctionOffset = GetOffset(runtimeFunctionSection.RelativeVirtualAddress);
+ bool[] isEntryPoint = new bool[nRuntimeFunctions];
- CompilerIdentifier = ParseCompilerIdentifier();
- }
+ // initialize R2RMethods
+ ParseMethodDefEntrypoints(isEntryPoint);
+ ParseInstanceMethodEntrypoints(isEntryPoint);
+ ParseRuntimeFunctions(isEntryPoint, runtimeFunctionOffset, runtimeFunctionSize);
}
+
+ AvailableTypes = new List<string>();
+ ParseAvailableTypes();
+
+ CompilerIdentifier = ParseCompilerIdentifier();
}
public bool InputArchitectureSupported()
{
Console.WriteLine($"Warning: Could not parse GC Info for method: {method.SignatureString}");
}
-
+
}
}
else if (Machine == Machine.I386)
READYTORUN_SECTION_AVAILABLE_TYPES = 108,
READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS = 109,
READYTORUN_SECTION_INLINING_INFO = 110,
- READYTORUN_SECTION_PROFILEDATA_INFO = 111
+ READYTORUN_SECTION_PROFILEDATA_INFO = 111,
+ READYTORUN_SECTION_MANIFEST_METADATA = 112, // Added in v2.3
}
/// <summary>
return formatter.EmitHandleName(handle, namespaceQualified, owningTypeOverride);
}
- public static string FormatSignature(DumpOptions options, R2RReader r2rReader, int imageOffset)
+ public static string FormatSignature(DumpOptions options, EcmaMetadataReader ecmaReader, int imageOffset)
{
- SignatureDecoder decoder = new SignatureDecoder(options, r2rReader, imageOffset);
+ SignatureDecoder decoder = new SignatureDecoder(options, ecmaReader, imageOffset);
string result = decoder.ReadR2RSignature();
return result;
}
case HandleKind.TypeDefinition:
return EmitTypeDefinitionName((TypeDefinitionHandle)handle, namespaceQualified);
+ case HandleKind.FieldDefinition:
+ return EmitFieldDefinitionName((FieldDefinitionHandle)handle, namespaceQualified, owningTypeOverride);
+
default:
throw new NotImplementedException();
}
return typeSpec.DecodeSignature<string, DisassemblingGenericContext>(this, genericContext);
}
+ /// <summary>
+ /// Emit the textual representation of a FieldDef metadata record.
+ /// </summary>
+ /// <param name="fieldDefHandle">Field definition handle to format</param>
+ /// <param name="namespaceQualified">True = display namespace information for the owning type</param>
+ /// <param name="owningTypeOverride">Owning type override when non-null</param>
+ /// <returns>Textual representation of the field declaration</returns>
+ private string EmitFieldDefinitionName(FieldDefinitionHandle fieldDefHandle, bool namespaceQualified, string owningTypeOverride)
+ {
+ FieldDefinition fieldDef = _metadataReader.GetFieldDefinition(fieldDefHandle);
+ DisassemblingGenericContext genericContext = new DisassemblingGenericContext(Array.Empty<string>(), Array.Empty<string>());
+ StringBuilder output = new StringBuilder();
+ output.Append(fieldDef.DecodeSignature<string, DisassemblingGenericContext>(this, genericContext));
+ output.Append(' ');
+ output.Append(EmitHandleName(fieldDef.GetDeclaringType(), namespaceQualified, owningTypeOverride));
+ output.Append('.');
+ output.Append(_metadataReader.GetString(fieldDef.Name));
+ return output.ToString();
+ }
+
private string EmitString(StringHandle handle)
{
return _metadataReader.GetString(handle);
public class SignatureDecoder
{
/// <summary>
- /// Metadata reader is used to access the embedded MSIL metadata blob in the R2R file.
+ /// ECMA reader is used to access the embedded MSIL metadata blob in the R2R file.
/// </summary>
- private readonly MetadataReader _metadataReader;
+ private readonly EcmaMetadataReader _ecmaReader;
/// <summary>
/// Dump options are used to specify details of signature formatting.
/// <summary>
/// Construct the signature decoder by storing the image byte array and offset within the array.
/// </summary>
- /// <param name="reader">R2RReader object representing the R2R PE file</param>
- /// <param name="offset">Signature offset within the array</param>
- /// <param name="options">Formatting options</param>
- public SignatureDecoder(DumpOptions options, R2RReader reader, int offset)
+ /// <param name="options">Dump options and paths</param>
+ /// <param name="ecmaReader">EcmaMetadataReader object representing the PE file containing the ECMA metadata</param>
+ /// <param name="offset">Signature offset within the PE file byte array</param>
+ public SignatureDecoder(DumpOptions options, EcmaMetadataReader ecmaReader, int offset)
{
- _metadataReader = reader.MetadataReader;
+ _ecmaReader = ecmaReader;
_options = options;
- _image = reader.Image;
+ _image = ecmaReader.Image;
_offset = offset;
}
/// <summary>
/// Construct the signature decoder by storing the image byte array and offset within the array.
/// </summary>
- /// <param name="metadataReader">Metadata reader for the R2R image</param>
+ /// <param name="options">Dump options and paths</param>
+ /// <param name="ecmaReader">Metadata reader for the R2R image</param>
/// <param name="signature">Signature to parse</param>
- /// <param name="offset">Optional signature offset within the signature byte array, 0 by default</param>
- public SignatureDecoder(DumpOptions options, MetadataReader metadataReader, byte[] signature, int offset = 0)
+ /// <param name="offset">Signature offset within the signature byte array</param>
+ public SignatureDecoder(DumpOptions options, EcmaMetadataReader ecmaReader, byte[] signature, int offset)
{
- _metadataReader = metadataReader;
+ _ecmaReader = ecmaReader;
_options = options;
_image = signature;
_offset = offset;
/// <summary>
/// Parse the signature into a given output string builder.
/// </summary>
- /// <param name="builder"></param>
+ /// <param name="builder">Output signature builder</param>
private void ParseSignature(StringBuilder builder)
{
uint fixupType = ReadByte();
bool moduleOverride = (fixupType & (byte)CORCOMPILE_FIXUP_BLOB_KIND.ENCODE_MODULE_OVERRIDE) != 0;
+ SignatureDecoder moduleDecoder = this;
+
// Check first byte for a module override being encoded
if (moduleOverride)
{
- builder.Append("ENCODE_MODULE_OVERRIDE @ ");
fixupType &= ~(uint)CORCOMPILE_FIXUP_BLOB_KIND.ENCODE_MODULE_OVERRIDE;
- uint moduleIndex = ReadUInt();
- builder.Append(string.Format(" Index: {0:X2}", moduleIndex));
+ int moduleIndex = (int)ReadUInt();
+ EcmaMetadataReader refAsmEcmaReader = _ecmaReader.OpenReferenceAssembly(moduleIndex);
+ moduleDecoder = new SignatureDecoder(_options, refAsmEcmaReader, _image, _offset);
}
- switch ((ReadyToRunFixupKind)fixupType)
+ moduleDecoder.ParseSignature((ReadyToRunFixupKind)fixupType, builder);
+ _offset = moduleDecoder.Offset;
+ }
+
+ /// <summary>
+ /// Parse the signature with a given fixup type after module overrides have been resolved.
+ /// </summary>
+ /// <param name="fixupType">Fixup type to parse</param>
+ /// <param name="builder">Output signature builder</param>
+ private void ParseSignature(ReadyToRunFixupKind fixupType, StringBuilder builder)
+ {
+ switch (fixupType)
{
case ReadyToRunFixupKind.READYTORUN_FIXUP_ThisObjDictionaryLookup:
builder.Append("THISOBJ_DICTIONARY_LOOKUP @ ");
break;
case ReadyToRunFixupKind.READYTORUN_FIXUP_FieldHandle:
- builder.Append("FIELD_HANDLE");
- // TODO
+ ParseField(builder);
+ builder.Append(" (FIELD_HANDLE)");
break;
break;
case ReadyToRunFixupKind.READYTORUN_FIXUP_MethodEntry_DefToken:
- if (!moduleOverride)
- {
- ParseMethodDefToken(builder, owningTypeOverride: null);
- }
+ ParseMethodDefToken(builder, owningTypeOverride: null);
builder.Append(" (METHOD_ENTRY");
builder.Append(_options.Naked ? ")" : "_DEF_TOKEN)");
break;
case ReadyToRunFixupKind.READYTORUN_FIXUP_VirtualEntry:
- if(!moduleOverride)
- {
- ParseMethod(builder);
- }
+ ParseMethod(builder);
builder.Append(" (VIRTUAL_ENTRY)");
break;
case ReadyToRunFixupKind.READYTORUN_FIXUP_VirtualEntry_Slot:
{
uint slot = ReadUInt();
- if (!moduleOverride)
- {
- ParseType(builder);
- }
+ ParseType(builder);
builder.Append($@" #{slot} (VIRTUAL_ENTRY_SLOT)");
}
break;
case CorElementType.ELEMENT_TYPE_MODULE_ZAPSIG:
- builder.Append("module_zapsig");
+ {
+ int moduleIndex = (int)ReadUInt();
+ EcmaMetadataReader refAsmReader = _ecmaReader.OpenReferenceAssembly(moduleIndex);
+ SignatureDecoder refAsmDecoder = new SignatureDecoder(_options, refAsmReader, _image, _offset);
+ refAsmDecoder.ParseType(builder);
+ _offset = refAsmDecoder.Offset;
+ }
break;
default:
private void ParseTypeToken(StringBuilder builder)
{
uint token = ReadToken();
- builder.Append(MetadataNameFormatter.FormatHandle(_metadataReader, MetadataTokens.Handle((int)token)));
+ builder.Append(MetadataNameFormatter.FormatHandle(_ecmaReader.MetadataReader, MetadataTokens.Handle((int)token)));
}
/// <summary>
private void ParseMethod(StringBuilder builder)
{
uint methodFlags = ReadUInt();
+
+ if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_UnboxingStub) != 0)
+ {
+ builder.Append("[UNBOX] ");
+ }
+ if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_InstantiatingStub) != 0)
+ {
+ builder.Append("[INST] ");
+ }
+
string owningTypeOverride = null;
if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType) != 0)
{
- SignatureDecoder owningTypeDecoder = new SignatureDecoder(_options, _metadataReader, _image, _offset);
+ SignatureDecoder owningTypeDecoder = new SignatureDecoder(_options, _ecmaReader, _image, _offset);
owningTypeOverride = owningTypeDecoder.ReadTypeSignature();
_offset = owningTypeDecoder._offset;
}
private void ParseMethodDefToken(StringBuilder builder, string owningTypeOverride)
{
uint methodDefToken = ReadUInt() | (uint)CorTokenType.mdtMethodDef;
- builder.Append(MetadataNameFormatter.FormatHandle(_metadataReader, MetadataTokens.Handle((int)methodDefToken), namespaceQualified: true, owningTypeOverride: owningTypeOverride));
+ builder.Append(MetadataNameFormatter.FormatHandle(_ecmaReader.MetadataReader, MetadataTokens.Handle((int)methodDefToken), namespaceQualified: true, owningTypeOverride: owningTypeOverride));
}
/// <summary>
private void ParseMethodRefToken(StringBuilder builder, string owningTypeOverride)
{
uint methodRefToken = ReadUInt() | (uint)CorTokenType.mdtMemberRef;
- builder.Append(MetadataNameFormatter.FormatHandle(_metadataReader, MetadataTokens.Handle((int)methodRefToken), namespaceQualified: false, owningTypeOverride: owningTypeOverride));
+ builder.Append(MetadataNameFormatter.FormatHandle(_ecmaReader.MetadataReader, MetadataTokens.Handle((int)methodRefToken), namespaceQualified: false, owningTypeOverride: owningTypeOverride));
}
/// <summary>
{
fieldToken = ReadUInt() | (uint)CorTokenType.mdtFieldDef;
}
- builder.Append(MetadataNameFormatter.FormatHandle(_metadataReader, MetadataTokens.Handle((int)fieldToken), namespaceQualified: false, owningTypeOverride: owningTypeOverride));
+ builder.Append(MetadataNameFormatter.FormatHandle(_ecmaReader.MetadataReader, MetadataTokens.Handle((int)fieldToken), namespaceQualified: false, owningTypeOverride: owningTypeOverride));
}
/// <summary>
{
uint rid = ReadUInt();
UserStringHandle stringHandle = MetadataTokens.UserStringHandle((int)rid);
- builder.Append(_metadataReader.GetUserString(stringHandle));
+ builder.Append(_ecmaReader.MetadataReader.GetUserString(stringHandle));
}
}
}
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Xml;
}
}
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;
}
}
_ignoredProperties.Add(typeof(RuntimeFunction), "UnwindRVA", attrs);
_ignoredProperties.Add(typeof(R2RSection), "RelativeVirtualAddress", attrs);
_ignoredProperties.Add(typeof(R2RSection), "Size", attrs);
+
+ XmlAttributes ignoreAlways = new XmlAttributes();
+ ignoreAlways.XmlIgnore = true;
+ _ignoredProperties.Add(typeof(R2RReader), "ImportCellNames", ignoreAlways);
}
internal override void Begin()