From e5f3881d5dd1da61efc46f74b6abd783bcc0d0b4 Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Sun, 29 Dec 2019 13:51:46 -0800 Subject: [PATCH] More R2RDump refactoring to make it easier for ILSpy to consume the APIs (#1209) --- .../IAssemblyResolver.cs | 10 +- .../ILCompiler.Reflection.ReadyToRun/R2RReader.cs | 325 ++++++++++----------- .../R2RSignature.cs | 44 +-- src/coreclr/src/tools/r2rdump/R2RDump.cs | 30 +- src/coreclr/src/tools/r2rdump/TextDumper.cs | 8 +- 5 files changed, 214 insertions(+), 203 deletions(-) diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/IAssemblyResolver.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/IAssemblyResolver.cs index b58344c..1b859c2 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/IAssemblyResolver.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/IAssemblyResolver.cs @@ -1,12 +1,14 @@ -using System; -using System.Collections.Generic; -using System.Text; +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Reflection.Metadata; namespace ILCompiler.Reflection.ReadyToRun { public interface IAssemblyResolver { - string FindAssembly(string name, string filename); + MetadataReader FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile); // TODO (refactoring) - signature formatting options should be independent of assembly resolver bool Naked { get; } bool SignatureBinary { get; } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/R2RReader.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/R2RReader.cs index c3704d9..6e89eec 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/R2RReader.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/R2RReader.cs @@ -77,142 +77,57 @@ namespace ILCompiler.Reflection.ReadyToRun } } - public class EcmaMetadataReader + public sealed class R2RReader { - protected IAssemblyResolver _assemblyResolver; - protected Dictionary _assemblyCache; - + private IAssemblyResolver _assemblyResolver; + private Dictionary _assemblyCache; + private Dictionary _runtimeFunctionToDebugInfo; + private MetadataReader _manifestReader; + private List _manifestReferences; /// /// Underlying PE image reader is used to access raw PE structures like header /// or section list. /// - public readonly PEReader PEReader; + public PEReader PEReader { get; private set; } /// /// MetadataReader is used to access the MSIL metadata in the R2R file. /// - public readonly MetadataReader MetadataReader; - - /// - /// 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. - /// - public readonly List ManifestReferenceAssemblies; + public MetadataReader MetadataReader { get; private set; } /// /// Byte array containing the ReadyToRun image /// - public byte[] Image { get; } + public byte[] Image { get; private set; } /// /// Name of the image file /// - public string Filename { get; set; } + public string Filename { get; private set; } /// - /// The default constructor initializes an empty metadata reader. - /// - public EcmaMetadataReader() - { - } - - public EcmaMetadataReader(IAssemblyResolver assemblyResolver, MetadataReader metadata, PEReader peReader, string filename, List manifestReferenceAssemblies) - { - _assemblyResolver = assemblyResolver; - _assemblyCache = new Dictionary(); - MetadataReader = metadata; - PEReader = peReader; - ImmutableArray content = peReader.GetEntireImage().GetContent(); - // TODO: Avoid copying - Image = new byte[content.Length]; - content.CopyTo(Image); - Filename = filename; - ManifestReferenceAssemblies = manifestReferenceAssemblies; - } - - /// - /// Open an MSIL binary and locate the metadata blob. + /// 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. /// - /// Ambient options to use - /// PE image - /// List of reference assemblies from the R2R metadata manifest - /// The Cor header flag must be ILLibrary - public unsafe EcmaMetadataReader(IAssemblyResolver assemblyResolver, string filename, List manifestReferenceAssemblies) + public IEnumerable ManifestReferenceAssemblies { - _assemblyResolver = assemblyResolver; - _assemblyCache = new Dictionary(); - Filename = filename; - ManifestReferenceAssemblies = manifestReferenceAssemblies; - Image = File.ReadAllBytes(filename); - - fixed (byte* p = Image) + get { - IntPtr ptr = (IntPtr)p; - PEReader = new PEReader(p, Image.Length); - - if (!PEReader.HasMetadata) + foreach (AssemblyReferenceHandle _manifestReference in _manifestReferences) { - throw new Exception($"ECMA metadata not found in file '{filename}'"); + yield return _manifestReader.GetString(_manifestReader.GetAssemblyReference(_manifestReference).Name); } - - MetadataReader = PEReader.GetMetadataReader(); } } /// - /// Open a given reference assembly (relative to this ECMA metadata file). - /// - /// Reference assembly index - /// EcmaMetadataReader instance representing the reference assembly - 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 (!_assemblyCache.TryGetValue(name, out ecmaReader)) - { - string assemblyPath = _assemblyResolver.FindAssembly(name, Filename); - if (assemblyPath == null) - { - throw new Exception($"Missing reference assembly: {name}"); - } - ecmaReader = new EcmaMetadataReader(_assemblyResolver, assemblyPath, ManifestReferenceAssemblies); - _assemblyCache.Add(name, ecmaReader); - } - return ecmaReader; - } - } - - public class R2RReader : EcmaMetadataReader - { - /// - /// True if the image is ReadyToRun - /// - public bool IsR2R { get; set; } - - /// /// The type of target machine /// public Machine Machine { get; set; } @@ -278,18 +193,17 @@ namespace ILCompiler.Reflection.ReadyToRun /// public Dictionary ImportCellNames { get; private set; } - private Dictionary _runtimeFunctionToDebugInfo = new Dictionary(); - - public R2RReader() { } - /// /// Initializes the fields of the R2RHeader and R2RMethods /// /// PE image /// The Cor header flag must be ILLibrary public R2RReader(IAssemblyResolver assemblyResolver, MetadataReader metadata, PEReader peReader, string filename) - : base(assemblyResolver, metadata, peReader, filename, new List()) { + _assemblyResolver = assemblyResolver; + MetadataReader = metadata; + PEReader = peReader; + Filename = filename; Initialize(); } @@ -298,16 +212,99 @@ namespace ILCompiler.Reflection.ReadyToRun /// /// PE image /// The Cor header flag must be ILLibrary - public R2RReader(IAssemblyResolver assemblyResolver, string filename) - : base(assemblyResolver, filename, new List()) + public unsafe R2RReader(IAssemblyResolver assemblyResolver, string filename) { + _assemblyResolver = assemblyResolver; + Filename = filename; Initialize(); } private unsafe void Initialize() { - IsR2R = ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) != 0); - if (!IsR2R) + _assemblyCache = new Dictionary(); + this._manifestReferences = new List(); + + if (MetadataReader == null) + { + 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(); + } + } + else + { + ImmutableArray content = PEReader.GetEntireImage().GetContent(); + // TODO: Avoid copying + Image = new byte[content.Length]; + content.CopyTo(Image); + } + + ParseHeader(); + + 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) + { + _manifestReader = new MetadataReader(image + GetOffset(manifestMetadata.RelativeVirtualAddress), manifestMetadata.Size); + int assemblyRefCount = _manifestReader.GetTableRowCount(TableIndex.AssemblyRef); + for (int assemblyRefIndex = 1; assemblyRefIndex <= assemblyRefCount; assemblyRefIndex++) + { + AssemblyReferenceHandle asmRefHandle = MetadataTokens.AssemblyReferenceHandle(assemblyRefIndex); + _manifestReferences.Add(asmRefHandle); + } + } + } + + if (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(); + ImportCellNames = new Dictionary(); + ParseImportSections(); + + R2RMethods = new List(); + InstanceMethods = new List(); + + 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(); + ParseAvailableTypes(); + + CompilerIdentifier = ParseCompilerIdentifier(); + } + + private unsafe void ParseHeader() + { + if ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) == 0) { throw new BadImageFormatException("The file is not a ReadyToRun image"); } @@ -367,58 +364,6 @@ namespace ILCompiler.Reflection.ReadyToRun { 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(); - ImportCellNames = new Dictionary(); - ParseImportSections(); - - R2RMethods = new List(); - InstanceMethods = new List(); - - 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(); - ParseAvailableTypes(); - - CompilerIdentifier = ParseCompilerIdentifier(); } public bool InputArchitectureSupported() @@ -784,6 +729,7 @@ namespace ILCompiler.Reflection.ReadyToRun private void ParseDebugInfo() { + _runtimeFunctionToDebugInfo = new Dictionary(); if (!R2RHeader.Sections.ContainsKey(R2RSection.SectionType.READYTORUN_SECTION_DEBUG_INFO)) { return; @@ -824,7 +770,7 @@ namespace ILCompiler.Reflection.ReadyToRun /// /// Get the full name of an ExportedType, including namespace /// - public static string GetExportedTypeFullName(MetadataReader mdReader, ExportedTypeHandle handle) + private static string GetExportedTypeFullName(MetadataReader mdReader, ExportedTypeHandle handle) { string typeNamespace = ""; string typeStr = ""; @@ -912,5 +858,46 @@ namespace ILCompiler.Reflection.ReadyToRun return cells.ToArray(); } + + /// + /// Open a given reference assembly (relative to this ECMA metadata file). + /// + /// Reference assembly index + /// MetadataReader instance representing the reference assembly + internal MetadataReader OpenReferenceAssembly(int refAsmIndex) + { + if (refAsmIndex == 0) + { + return this.MetadataReader; + } + + int assemblyRefCount = MetadataReader.GetTableRowCount(TableIndex.AssemblyRef); + MetadataReader metadataReader; + AssemblyReferenceHandle assemblyReferenceHandle; + if (refAsmIndex <= assemblyRefCount) + { + metadataReader = MetadataReader; + assemblyReferenceHandle = MetadataTokens.AssemblyReferenceHandle(refAsmIndex); + } + else + { + metadataReader = _manifestReader; + assemblyReferenceHandle = _manifestReferences[refAsmIndex - assemblyRefCount - 2]; + } + + + MetadataReader result; + if (!_assemblyCache.TryGetValue(refAsmIndex, out result)) + { + result = _assemblyResolver.FindAssembly(metadataReader, assemblyReferenceHandle, Filename); + if (result == null) + { + string name = metadataReader.GetString(metadataReader.GetAssemblyReference(assemblyReferenceHandle).Name); + throw new Exception($"Missing reference assembly: {name}"); + } + _assemblyCache.Add(refAsmIndex, result); + } + return result; + } } } diff --git a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/R2RSignature.cs b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/R2RSignature.cs index 40a2bd3..87c0361 100644 --- a/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/R2RSignature.cs +++ b/src/coreclr/src/tools/crossgen2/ILCompiler.Reflection.ReadyToRun/R2RSignature.cs @@ -39,9 +39,9 @@ namespace ILCompiler.Reflection.ReadyToRun return formatter.EmitHandleName(handle, namespaceQualified, owningTypeOverride, signaturePrefix); } - public static string FormatSignature(IAssemblyResolver assemblyResolver, EcmaMetadataReader ecmaReader, int imageOffset) + public static string FormatSignature(IAssemblyResolver assemblyResolver, R2RReader r2rReader, int imageOffset) { - SignatureDecoder decoder = new SignatureDecoder(assemblyResolver, ecmaReader, imageOffset); + SignatureDecoder decoder = new SignatureDecoder(assemblyResolver, r2rReader, imageOffset); string result = decoder.ReadR2RSignature(); return result; } @@ -348,12 +348,12 @@ namespace ILCompiler.Reflection.ReadyToRun /// /// ECMA reader is used to access the embedded MSIL metadata blob in the R2R file. /// - private readonly EcmaMetadataReader _ecmaReader; + private readonly MetadataReader _metadataReader; /// /// ECMA reader representing the top-level signature context. /// - private readonly EcmaMetadataReader _contextReader; + private readonly R2RReader _contextReader; /// /// Dump options are used to specify details of signature formatting. @@ -379,28 +379,28 @@ namespace ILCompiler.Reflection.ReadyToRun /// Construct the signature decoder by storing the image byte array and offset within the array. /// /// Dump options and paths - /// EcmaMetadataReader object representing the PE file containing the ECMA metadata + /// R2RReader object representing the PE file containing the ECMA metadata /// Signature offset within the PE file byte array - public SignatureDecoder(IAssemblyResolver options, EcmaMetadataReader ecmaReader, int offset) + public SignatureDecoder(IAssemblyResolver options, R2RReader r2rReader, int offset) { - _ecmaReader = ecmaReader; + _metadataReader = r2rReader.MetadataReader; _options = options; - _image = ecmaReader.Image; + _image = r2rReader.Image; _offset = offset; - _contextReader = ecmaReader; + _contextReader = r2rReader; } /// /// Construct the signature decoder by storing the image byte array and offset within the array. /// /// Dump options and paths - /// Metadata reader for the R2R image + /// Metadata reader for the R2R image /// Signature to parse /// Signature offset within the signature byte array /// Top-level signature context reader - public SignatureDecoder(IAssemblyResolver options, EcmaMetadataReader ecmaReader, byte[] signature, int offset, EcmaMetadataReader contextReader) + private SignatureDecoder(IAssemblyResolver options, MetadataReader metadataReader, byte[] signature, int offset, R2RReader contextReader) { - _ecmaReader = ecmaReader; + _metadataReader = metadataReader; _options = options; _image = signature; _offset = offset; @@ -638,7 +638,7 @@ namespace ILCompiler.Reflection.ReadyToRun { fixupType &= ~(uint)ReadyToRunFixupKind.ModuleOverride; int moduleIndex = (int)ReadUIntAndEmitInlineSignatureBinary(builder); - EcmaMetadataReader refAsmEcmaReader = _contextReader.OpenReferenceAssembly(moduleIndex); + MetadataReader refAsmEcmaReader = _contextReader.OpenReferenceAssembly(moduleIndex); moduleDecoder = new SignatureDecoder(_options, refAsmEcmaReader, _image, _offset, _contextReader); } @@ -1069,7 +1069,7 @@ namespace ILCompiler.Reflection.ReadyToRun case CorElementType.ELEMENT_TYPE_MODULE_ZAPSIG: { int moduleIndex = (int)ReadUIntAndEmitInlineSignatureBinary(builder); - EcmaMetadataReader refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex); + MetadataReader refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex); SignatureDecoder refAsmDecoder = new SignatureDecoder(_options, refAsmReader, _image, _offset, _contextReader); refAsmDecoder.ParseType(builder); _offset = refAsmDecoder.Offset; @@ -1089,11 +1089,11 @@ namespace ILCompiler.Reflection.ReadyToRun ReadElementType(); int moduleIndex = (int)ReadUInt(); - EcmaMetadataReader refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex); + MetadataReader refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex); _offset = currentOffset; - return refAsmReader.MetadataReader; + return refAsmReader; } return null; } @@ -1119,7 +1119,7 @@ namespace ILCompiler.Reflection.ReadyToRun StringBuilder signaturePrefixBuilder = new StringBuilder(); uint token = ReadTokenAndEmitInlineSignatureBinary(signaturePrefixBuilder); builder.Append(MetadataNameFormatter.FormatHandle( - _ecmaReader.MetadataReader, + _metadataReader, MetadataTokens.Handle((int)token), owningTypeOverride: null, signaturePrefix: signaturePrefixBuilder.ToString())); @@ -1145,7 +1145,7 @@ namespace ILCompiler.Reflection.ReadyToRun string owningTypeOverride = null; if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_OwnerType) != 0) { - SignatureDecoder owningTypeDecoder = new SignatureDecoder(_options, _ecmaReader, _image, _offset, _contextReader); + SignatureDecoder owningTypeDecoder = new SignatureDecoder(_options, _metadataReader, _image, _offset, _contextReader); owningTypeOverride = owningTypeDecoder.ReadTypeSignatureNoEmit(); _offset = owningTypeDecoder._offset; } @@ -1193,7 +1193,7 @@ namespace ILCompiler.Reflection.ReadyToRun StringBuilder signaturePrefixBuilder = new StringBuilder(); uint methodDefToken = ReadUIntAndEmitInlineSignatureBinary(signaturePrefixBuilder) | (uint)CorTokenType.mdtMethodDef; builder.Append(MetadataNameFormatter.FormatHandle( - _ecmaReader.MetadataReader, + _metadataReader, MetadataTokens.Handle((int)methodDefToken), namespaceQualified: true, owningTypeOverride: owningTypeOverride, @@ -1210,7 +1210,7 @@ namespace ILCompiler.Reflection.ReadyToRun StringBuilder signaturePrefixBuilder = new StringBuilder(); uint methodRefToken = ReadUIntAndEmitInlineSignatureBinary(signaturePrefixBuilder) | (uint)CorTokenType.mdtMemberRef; builder.Append(MetadataNameFormatter.FormatHandle( - _ecmaReader.MetadataReader, + _metadataReader, MetadataTokens.Handle((int)methodRefToken), namespaceQualified: false, owningTypeOverride: owningTypeOverride, @@ -1242,7 +1242,7 @@ namespace ILCompiler.Reflection.ReadyToRun fieldToken = ReadUIntAndEmitInlineSignatureBinary(signaturePrefixBuilder) | (uint)CorTokenType.mdtFieldDef; } builder.Append(MetadataNameFormatter.FormatHandle( - _ecmaReader.MetadataReader, + _metadataReader, MetadataTokens.Handle((int)fieldToken), namespaceQualified: false, owningTypeOverride: owningTypeOverride, @@ -1640,7 +1640,7 @@ namespace ILCompiler.Reflection.ReadyToRun { uint rid = ReadUIntAndEmitInlineSignatureBinary(builder); UserStringHandle stringHandle = MetadataTokens.UserStringHandle((int)rid); - builder.Append(_ecmaReader.MetadataReader.GetUserString(stringHandle)); + builder.Append(_metadataReader.GetUserString(stringHandle)); } } } diff --git a/src/coreclr/src/tools/r2rdump/R2RDump.cs b/src/coreclr/src/tools/r2rdump/R2RDump.cs index 45ae837..5f8a330 100644 --- a/src/coreclr/src/tools/r2rdump/R2RDump.cs +++ b/src/coreclr/src/tools/r2rdump/R2RDump.cs @@ -9,7 +9,9 @@ using System.CommandLine; using System.CommandLine.Invocation; using System.IO; using System.Linq; +using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; +using System.Reflection.PortableExecutable; using System.Text; using System.Threading.Tasks; @@ -44,8 +46,6 @@ namespace R2RDump public bool SignatureBinary { get; set; } public bool InlineSignatureBinary { get; set; } - public Dictionary AssemblyCache = new Dictionary(StringComparer.OrdinalIgnoreCase); - /// /// Probing extensions to use when looking up assemblies under reference paths. /// @@ -58,13 +58,15 @@ namespace R2RDump /// Simple name of the assembly to look up /// Name of assembly from which we're performing the lookup /// - public string FindAssembly(string simpleName, string parentFile) + + public MetadataReader FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile) { + string simpleName = metadataReader.GetString(metadataReader.GetAssemblyReference(assemblyReferenceHandle).Name); foreach (FileInfo refAsm in Reference ?? Enumerable.Empty()) { if (Path.GetFileNameWithoutExtension(refAsm.FullName).Equals(simpleName, StringComparison.OrdinalIgnoreCase)) { - return refAsm.FullName; + return Open(refAsm.FullName); } } @@ -78,13 +80,31 @@ namespace R2RDump string probeFile = Path.Combine(refPath, simpleName + extension); if (File.Exists(probeFile)) { - return probeFile; + return Open(probeFile); } } } return null; } + + private static unsafe MetadataReader Open(string filename) + { + byte[] Image = File.ReadAllBytes(filename); + + fixed (byte* p = Image) + { + IntPtr ptr = (IntPtr)p; + PEReader peReader = new PEReader(p, Image.Length); + + if (!peReader.HasMetadata) + { + throw new Exception($"ECMA metadata not found in file '{filename}'"); + } + + return peReader.GetMetadataReader(); + } + } } public abstract class Dumper diff --git a/src/coreclr/src/tools/r2rdump/TextDumper.cs b/src/coreclr/src/tools/r2rdump/TextDumper.cs index 0784778..4a4e338 100644 --- a/src/coreclr/src/tools/r2rdump/TextDumper.cs +++ b/src/coreclr/src/tools/r2rdump/TextDumper.cs @@ -377,10 +377,12 @@ namespace R2RDump _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($"Manifest metadata AssemblyRef's ({_r2r.ManifestReferenceAssemblies.Count()} entries):"); + int manifestAsmIndex = 0; + foreach (string manifestReferenceAssembly in _r2r.ManifestReferenceAssemblies) { - _writer.WriteLine($"[ID 0x{manifestAsmIndex + assemblyRefCount + 2:X2}]: {_r2r.ManifestReferenceAssemblies[manifestAsmIndex]}"); + _writer.WriteLine($"[ID 0x{manifestAsmIndex + assemblyRefCount + 2:X2}]: {manifestReferenceAssembly}"); + manifestAsmIndex++; } break; case R2RSection.SectionType.READYTORUN_SECTION_ATTRIBUTEPRESENCE: -- 2.7.4