Three fixes for R2RDump bugs I discovered while investigating #38290 (#41303)
authorTomáš Rylek <trylek@microsoft.com>
Wed, 26 Aug 2020 23:33:45 +0000 (01:33 +0200)
committerGitHub <noreply@github.com>
Wed, 26 Aug 2020 23:33:45 +0000 (01:33 +0200)
1) As ReadyToRunMethod newly looks at method bodies, in the
composite case we need to pass around per-module IL info, not only
the metadata reader. I have replaced such usages of MetadataReader
with the new interface IAssemblyMetadata and I implemented the
standalone variant StandaloneAssemblyMetadata.

2) I hit an UnwindInfo decoding issue and I found out that the
UnwindCode decoder is weirdly split between the UnwindCode ctor
and a separate method ParseUnwindCode that weren't completely
consistent in whether the UnwindInfoArray refers to the raw 16-bit
entries in the UnwindInfo or to the parsed UnwindCode instances.
I have basically migrated ParseUnwindCode into the UnwindCode ctor
and I simplified the related logic.

3) We shouldn't block method dump on header dump, otherwise there's
no way to dump both headers and methods in one R2RDump execution.

Thanks

Tomas

13 files changed:
src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/Amd64/UnwindInfo.cs
src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/EHInfo.cs
src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/IAssemblyMetadata.cs [new file with mode: 0644]
src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/IAssemblyResolver.cs
src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs
src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs
src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs
src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/StandaloneAssemblyMetadata.cs [new file with mode: 0644]
src/coreclr/src/tools/dotnet-pgo/TraceTypeSystemContext.cs
src/coreclr/src/tools/r2rdump/Extensions.cs
src/coreclr/src/tools/r2rdump/R2RDiff.cs
src/coreclr/src/tools/r2rdump/R2RDump.cs
src/coreclr/src/tools/r2rdump/TextDumper.cs

index 08241e0..5d8cd2b 100644 (file)
@@ -3,7 +3,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.Text;
 
 namespace ILCompiler.Reflection.ReadyToRun.Amd64
@@ -43,8 +42,6 @@ namespace ILCompiler.Reflection.ReadyToRun.Amd64
     /// </summary>
     public class UnwindCode
     {
-        public int Index { get; set; }
-
         public byte CodeOffset { get; set; }
         public UnwindOpCodes UnwindOp { get; set; } //4 bits
 
@@ -54,43 +51,101 @@ namespace ILCompiler.Reflection.ReadyToRun.Amd64
         public byte OffsetLow { get; set; }
         public byte OffsetHigh { get; set; } //4 bits
 
-        public uint FrameOffset { get; set; }
+        public int FrameOffset { get; set; }
         public int NextFrameOffset { get; set; }
 
         public bool IsOpInfo { get; set; }
 
         public UnwindCode() { }
 
-        public UnwindCode(byte[] image, int index, ref int offset)
+        /// <summary>
+        /// Unwinde code parsing is based on <a href="https://github.com/dotnet/coreclr/blob/master/src/jit/unwindamd64.cpp">src\jit\unwindamd64.cpp</a> DumpUnwindInfo
+        /// </summary>
+        public UnwindCode(byte[] image, ref int frameOffset, ref int offset)
         {
-            Index = index;
-
-            int off = offset;
-            CodeOffset = NativeReader.ReadByte(image, ref off);
-            byte op = NativeReader.ReadByte(image, ref off);
+            CodeOffset = NativeReader.ReadByte(image, ref offset);
+            byte op = NativeReader.ReadByte(image, ref offset);
             UnwindOp = (UnwindOpCodes)(op & 15);
             OpInfo = (byte)(op >> 4);
 
             OffsetLow = CodeOffset;
             OffsetHigh = OpInfo;
 
-            FrameOffset = NativeReader.ReadUInt16(image, ref offset);
-            NextFrameOffset = -1;
+            FrameOffset = frameOffset;
 
-            if (UnwindOp == UnwindOpCodes.UWOP_ALLOC_LARGE)
+            switch (UnwindOp)
             {
-                uint codedSize;
-                if (OpInfo == 0)
-                {
-                    codedSize = NativeReader.ReadUInt16(image, ref offset);
-                }
-                else if (OpInfo == 1)
-                {
-                    codedSize = NativeReader.ReadUInt32(image, ref offset);
-                }
+                case UnwindOpCodes.UWOP_PUSH_NONVOL:
+                    OpInfoStr = $"{(Registers)OpInfo}({OpInfo})";
+                    break;
+                case UnwindOpCodes.UWOP_ALLOC_LARGE:
+                    OpInfoStr = $"{OpInfo} - ";
+                    if (OpInfo == 0)
+                    {
+                        OpInfoStr += "Scaled small";
+                        NextFrameOffset = 8 * NativeReader.ReadUInt16(image, ref offset);
+                    }
+                    else if (OpInfo == 1)
+                    {
+                        OpInfoStr += "Unscaled large";
+                        uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
+                        NextFrameOffset = (int)((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
+                    }
+                    else
+                    {
+                        OpInfoStr += "Unknown";
+                    }
+                    break;
+                case UnwindOpCodes.UWOP_ALLOC_SMALL:
+                    int opInfo = OpInfo * 8 + 8;
+                    OpInfoStr = $"{opInfo}";
+                    break;
+                case UnwindOpCodes.UWOP_SET_FPREG:
+                    OpInfoStr = $"Unused({OpInfo})";
+                    break;
+                case UnwindOpCodes.UWOP_SET_FPREG_LARGE:
+                    {
+                        OpInfoStr = $"Unused({OpInfo})";
+                        uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
+                        nextOffset = ((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
+                        NextFrameOffset = (int)nextOffset * 16;
+                        if ((NextFrameOffset & 0xF0000000) != 0)
+                        {
+                            throw new BadImageFormatException("Warning: Illegal unwindInfo unscaled offset: too large");
+                        }
+                    }
+                    break;
+                case UnwindOpCodes.UWOP_SAVE_NONVOL:
+                    {
+                        OpInfoStr = $"{(Registers)OpInfo}({OpInfo})";
+                        NextFrameOffset = NativeReader.ReadUInt16(image, ref offset) * 8;
+                    }
+                    break;
+                case UnwindOpCodes.UWOP_SAVE_NONVOL_FAR:
+                    {
+                        OpInfoStr = $"{(Registers)OpInfo}({OpInfo})";
+                        uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
+                        NextFrameOffset = (int)((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
+                    }
+                    break;
+                case UnwindOpCodes.UWOP_SAVE_XMM128:
+                    {
+                        OpInfoStr = $"XMM{OpInfo}({OpInfo})";
+                        NextFrameOffset = (int)NativeReader.ReadUInt16(image, ref offset) * 16;
+                    }
+                    break;
+                case UnwindOpCodes.UWOP_SAVE_XMM128_FAR:
+                    {
+                        OpInfoStr = $"XMM{OpInfo}({OpInfo})";
+                        uint nextOffset = NativeReader.ReadUInt16(image, ref offset);
+                        NextFrameOffset = (int)((uint)(NativeReader.ReadUInt16(image, ref offset) << 16) | nextOffset);
+                    }
+                    break;
+                default:
+                    throw new NotImplementedException(UnwindOp.ToString());
             }
 
-            IsOpInfo = false;
+            NextFrameOffset = frameOffset;
         }
     }
 
@@ -108,8 +163,8 @@ namespace ILCompiler.Reflection.ReadyToRun.Amd64
         public byte CountOfUnwindCodes { get; set; }
         public Registers FrameRegister { get; set; } //4 bits
         public byte FrameOffset { get; set; } //4 bits
-        public UnwindCode[] UnwindCodeArray { get; set; }
-        public Dictionary<int, UnwindCode> UnwindCodes { get; set; }
+        public Dictionary<int, int> CodeOffsetToUnwindCodeIndex { get; set; }
+        public List<UnwindCode> UnwindCodes { get; set; }
         public uint PersonalityRoutineRVA { get; set; }
 
         public UnwindInfo() { }
@@ -128,20 +183,19 @@ namespace ILCompiler.Reflection.ReadyToRun.Amd64
             FrameRegister = (Registers)(frameRegisterAndOffset & 15);
             FrameOffset = (byte)(frameRegisterAndOffset >> 4);
 
-            UnwindCodeArray = new UnwindCode[CountOfUnwindCodes];
-            UnwindCodes = new Dictionary<int, UnwindCode>();
-            for (int i = 0; i < CountOfUnwindCodes; i++)
+            UnwindCodes = new List<UnwindCode>(CountOfUnwindCodes);
+            CodeOffsetToUnwindCodeIndex = new Dictionary<int, int>();
+            int frameOffset = FrameOffset;
+            int sizeOfUnwindCodes = CountOfUnwindCodes * _sizeofUnwindCode;
+            int endOffset = offset + sizeOfUnwindCodes;
+            while (offset < endOffset)
             {
-                UnwindCodeArray[i] = new UnwindCode(image, i, ref offset);
-            }
-            for (int i = 0; i < CountOfUnwindCodes; i++)
-            {
-                ParseUnwindCode(ref i);
-                Debug.Assert(!UnwindCodes.ContainsKey(UnwindCodeArray[i].CodeOffset));
-                UnwindCodes.Add(UnwindCodeArray[i].CodeOffset, UnwindCodeArray[i]);
+                UnwindCode unwindCode = new UnwindCode(image, ref frameOffset, ref offset);
+                CodeOffsetToUnwindCodeIndex.Add(unwindCode.CodeOffset, UnwindCodes.Count);
+                UnwindCodes.Add(unwindCode);
             }
 
-            Size = _offsetofUnwindCode + CountOfUnwindCodes * _sizeofUnwindCode;
+            Size = _offsetofUnwindCode + sizeOfUnwindCodes;
             int alignmentPad = -Size & 3;
             Size += alignmentPad + sizeof(uint);
 
@@ -177,16 +231,14 @@ namespace ILCompiler.Reflection.ReadyToRun.Amd64
             sb.AppendLine($"    FrameOffset: {FrameOffset}");
             sb.AppendLine($"    Unwind Codes:");
             sb.AppendLine($"        ------------------");
-            for (int i = 0; i < CountOfUnwindCodes; i++)
+            foreach (UnwindCode unwindCode in UnwindCodes)
             {
-                if (!UnwindCodeArray[i].IsOpInfo)
-                    continue;
-                sb.AppendLine($"        CodeOffset: 0x{UnwindCodeArray[i].CodeOffset:X2}");
-                sb.AppendLine($"        UnwindOp: {UnwindCodeArray[i].UnwindOp}({(byte)UnwindCodeArray[i].UnwindOp})");
-                sb.AppendLine($"        OpInfo: {UnwindCodeArray[i].OpInfoStr}");
-                if (UnwindCodeArray[i].NextFrameOffset != -1)
+                sb.AppendLine($"        CodeOffset: 0x{unwindCode.CodeOffset:X2}");
+                sb.AppendLine($"        UnwindOp: {unwindCode.UnwindOp}({(byte)unwindCode.UnwindOp})");
+                sb.AppendLine($"        OpInfo: {unwindCode.OpInfoStr}");
+                if (unwindCode.NextFrameOffset != -1)
                 {
-                    sb.AppendLine($"        FrameOffset: {UnwindCodeArray[i].NextFrameOffset}");
+                    sb.AppendLine($"        FrameOffset: {unwindCode.NextFrameOffset}");
                 }
                 sb.AppendLine($"        ------------------");
             }
@@ -196,98 +248,5 @@ namespace ILCompiler.Reflection.ReadyToRun.Amd64
             return sb.ToString();
         }
 
-        /// <summary>
-        /// based on <a href="https://github.com/dotnet/coreclr/blob/master/src/jit/unwindamd64.cpp">src\jit\unwindamd64.cpp</a> DumpUnwindInfo
-        /// </summary>
-        private void ParseUnwindCode(ref int i)
-        {
-            UnwindCode code = UnwindCodeArray[i];
-            code.IsOpInfo = true;
-            switch (code.UnwindOp)
-            {
-                case UnwindOpCodes.UWOP_PUSH_NONVOL:
-                    code.OpInfoStr = $"{(Registers)code.OpInfo}({code.OpInfo})";
-                    break;
-                case UnwindOpCodes.UWOP_ALLOC_LARGE:
-                    code.OpInfoStr = $"{code.OpInfo} - ";
-                    if (code.OpInfo == 0)
-                    {
-                        i++;
-                        UnwindCodeArray[i].OpInfoStr += "Scaled small";
-                        code.NextFrameOffset = (int)UnwindCodeArray[i].FrameOffset * 8;
-                    }
-                    else if (code.OpInfo == 1)
-                    {
-                        i++;
-                        UnwindCodeArray[i].OpInfoStr += "Unscaled large";
-                        uint offset = UnwindCodeArray[i].FrameOffset;
-                        i++;
-                        offset = ((UnwindCodeArray[i].FrameOffset << 16) | offset);
-                        code.NextFrameOffset = (int)offset;
-                    }
-                    else
-                    {
-                        code.OpInfoStr += "Unknown";
-                    }
-                    break;
-                case UnwindOpCodes.UWOP_ALLOC_SMALL:
-                    int opInfo = code.OpInfo * 8 + 8;
-                    code.OpInfoStr = $"{opInfo}";
-                    break;
-                case UnwindOpCodes.UWOP_SET_FPREG:
-                    code.OpInfoStr = $"Unused({code.OpInfo})";
-                    break;
-                case UnwindOpCodes.UWOP_SET_FPREG_LARGE:
-                    {
-                        code.OpInfoStr = $"Unused({code.OpInfo})";
-                        i++;
-                        uint offset = UnwindCodeArray[i].FrameOffset;
-                        i++;
-                        offset = ((UnwindCodeArray[i].FrameOffset << 16) | offset);
-                        code.NextFrameOffset = (int)offset * 16;
-                        if ((UnwindCodeArray[i].FrameOffset & 0xF0000000) != 0)
-                        {
-                            throw new BadImageFormatException("Warning: Illegal unwindInfo unscaled offset: too large");
-                        }
-                    }
-                    break;
-                case UnwindOpCodes.UWOP_SAVE_NONVOL:
-                    {
-                        code.OpInfoStr = $"{(Registers)code.OpInfo}({code.OpInfo})";
-                        i++;
-                        uint offset = UnwindCodeArray[i].FrameOffset * 8;
-                        code.NextFrameOffset = (int)offset;
-                    }
-                    break;
-                case UnwindOpCodes.UWOP_SAVE_NONVOL_FAR:
-                    {
-                        code.OpInfoStr = $"{(Registers)code.OpInfo}({code.OpInfo})";
-                        i++;
-                        uint offset = UnwindCodeArray[i].FrameOffset;
-                        i++;
-                        offset = ((UnwindCodeArray[i].FrameOffset << 16) | offset);
-                        code.NextFrameOffset = (int)offset;
-                    }
-                    break;
-                case UnwindOpCodes.UWOP_SAVE_XMM128:
-                    {
-                        code.OpInfoStr = $"XMM{code.OpInfo}({code.OpInfo})";
-                        i++;
-                        uint offset = UnwindCodeArray[i].FrameOffset * 16;
-                        code.NextFrameOffset = (int)offset;
-                    }
-                    break;
-                case UnwindOpCodes.UWOP_SAVE_XMM128_FAR:
-                    {
-                        code.OpInfoStr = $"XMM{code.OpInfo}({code.OpInfo})";
-                        i++;
-                        uint offset = UnwindCodeArray[i].FrameOffset;
-                        i++;
-                        offset = ((UnwindCodeArray[i].FrameOffset << 16) | offset);
-                        code.NextFrameOffset = (int)offset;
-                    }
-                    break;
-            }
-        }
     }
 }
index 32e4eab..a6627f8 100644 (file)
@@ -101,7 +101,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                 }
                 else
                 {
-                    ClassName = MetadataNameFormatter.FormatHandle(reader.GetGlobalMetadataReader(), MetadataTokens.Handle((int)ClassTokenOrFilterOffset));
+                    ClassName = MetadataNameFormatter.FormatHandle(reader.GetGlobalMetadata()?.MetadataReader, MetadataTokens.Handle((int)ClassTokenOrFilterOffset));
                 }
             }
         }
diff --git a/src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/IAssemblyMetadata.cs b/src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/IAssemblyMetadata.cs
new file mode 100644 (file)
index 0000000..5a49d9a
--- /dev/null
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+
+namespace ILCompiler.Reflection.ReadyToRun
+{
+    /// <summary>
+    /// This interface represents MSIL information for a single component assembly.
+    /// </summary>
+    public interface IAssemblyMetadata
+    {
+        PEReader ImageReader { get; }
+
+        MetadataReader MetadataReader { get;  }
+    }
+}
index 411aabe..677eadd 100644 (file)
@@ -7,8 +7,8 @@ namespace ILCompiler.Reflection.ReadyToRun
 {
     public interface IAssemblyResolver
     {
-        MetadataReader FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile);
-        MetadataReader FindAssembly(string simpleName, string parentFile);
+        IAssemblyMetadata FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile);
+        IAssemblyMetadata FindAssembly(string simpleName, string parentFile);
         // TODO (refactoring) - signature formatting options should be independent of assembly resolver
         bool Naked { get; }
         bool SignatureBinary { get; }
index 266a75b..4910c1e 100644 (file)
@@ -214,9 +214,9 @@ namespace ILCompiler.Reflection.ReadyToRun
         private const int _mdtMethodDef = 0x06000000;
 
         /// <summary>
-        /// MetadataReader representing the method module.
+        /// MSIL module containing the method.
         /// </summary>
-        public MetadataReader MetadataReader { get; private set; }
+        public IAssemblyMetadata ComponentReader { get; private set; }
 
         /// <summary>
         /// The name of the method
@@ -296,8 +296,7 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// </summary>
         public ReadyToRunMethod(
             ReadyToRunReader readyToRunReader,
-            PEReader peReader,
-            MetadataReader metadataReader,
+            IAssemblyMetadata componentReader,
             EntityHandle methodHandle,
             int entryPointId,
             string owningType,
@@ -310,7 +309,7 @@ namespace ILCompiler.Reflection.ReadyToRun
             MethodHandle = methodHandle;
             EntryPointRuntimeFunctionId = entryPointId;
 
-            MetadataReader = metadataReader;
+            ComponentReader = componentReader;
 
             EntityHandle owningTypeHandle;
             GenericParameterHandleCollection genericParams = default(GenericParameterHandleCollection);
@@ -323,17 +322,17 @@ namespace ILCompiler.Reflection.ReadyToRun
             {
                 case HandleKind.MethodDefinition:
                     {
-                        MethodDefinition methodDef = MetadataReader.GetMethodDefinition((MethodDefinitionHandle)MethodHandle);
+                        MethodDefinition methodDef = ComponentReader.MetadataReader.GetMethodDefinition((MethodDefinitionHandle)MethodHandle);
                         if (methodDef.RelativeVirtualAddress != 0)
                         {
-                            MethodBodyBlock mbb = peReader.GetMethodBody(methodDef.RelativeVirtualAddress);
+                            MethodBodyBlock mbb = ComponentReader.ImageReader.GetMethodBody(methodDef.RelativeVirtualAddress);
                             if (!mbb.LocalSignature.IsNil)
                             {
-                                StandaloneSignature ss = MetadataReader.GetStandaloneSignature(mbb.LocalSignature);
+                                StandaloneSignature ss = ComponentReader.MetadataReader.GetStandaloneSignature(mbb.LocalSignature);
                                 LocalSignature = ss.DecodeLocalSignature(typeProvider, genericContext);
                             }
                         }
-                        Name = MetadataReader.GetString(methodDef.Name);
+                        Name = ComponentReader.MetadataReader.GetString(methodDef.Name);
                         Signature = methodDef.DecodeSignature<string, DisassemblingGenericContext>(typeProvider, genericContext);
                         owningTypeHandle = methodDef.GetDeclaringType();
                         genericParams = methodDef.GetGenericParameters();
@@ -342,8 +341,8 @@ namespace ILCompiler.Reflection.ReadyToRun
 
                 case HandleKind.MemberReference:
                     {
-                        MemberReference memberRef = MetadataReader.GetMemberReference((MemberReferenceHandle)MethodHandle);
-                        Name = MetadataReader.GetString(memberRef.Name);
+                        MemberReference memberRef = ComponentReader.MetadataReader.GetMemberReference((MemberReferenceHandle)MethodHandle);
+                        Name = ComponentReader.MetadataReader.GetString(memberRef.Name);
                         Signature = memberRef.DecodeMethodSignature<string, DisassemblingGenericContext>(typeProvider, genericContext);
                         owningTypeHandle = memberRef.Parent;
                     }
@@ -359,7 +358,7 @@ namespace ILCompiler.Reflection.ReadyToRun
             }
             else
             {
-                DeclaringType = MetadataNameFormatter.FormatHandle(MetadataReader, owningTypeHandle);
+                DeclaringType = MetadataNameFormatter.FormatHandle(ComponentReader.MetadataReader, owningTypeHandle);
             }
 
             StringBuilder sb = new StringBuilder();
@@ -459,7 +458,7 @@ namespace ILCompiler.Reflection.ReadyToRun
         {
             int runtimeFunctionId = EntryPointRuntimeFunctionId;
             int runtimeFunctionSize = _readyToRunReader.CalculateRuntimeFunctionSize();
-            int runtimeFunctionOffset = _readyToRunReader.PEReader.GetOffset(_readyToRunReader.ReadyToRunHeader.Sections[ReadyToRunSectionType.RuntimeFunctions].RelativeVirtualAddress);
+            int runtimeFunctionOffset = _readyToRunReader.CompositeReader.GetOffset(_readyToRunReader.ReadyToRunHeader.Sections[ReadyToRunSectionType.RuntimeFunctions].RelativeVirtualAddress);
             int curOffset = runtimeFunctionOffset + runtimeFunctionId * runtimeFunctionSize;
             BaseGcInfo gcInfo = null;
             int codeOffset = 0;
@@ -472,7 +471,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                     endRva = NativeReader.ReadInt32(_readyToRunReader.Image, ref curOffset);
                 }
                 int unwindRva = NativeReader.ReadInt32(_readyToRunReader.Image, ref curOffset);
-                int unwindOffset = _readyToRunReader.PEReader.GetOffset(unwindRva);
+                int unwindOffset = _readyToRunReader.CompositeReader.GetOffset(unwindRva);
 
                 BaseUnwindInfo unwindInfo = null;
                 if (_readyToRunReader.Machine == Machine.Amd64)
index 5bb297b..3e31631 100644 (file)
@@ -54,19 +54,14 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// <summary>
         /// MetadataReader for the system module (normally System.Private.CoreLib)
         /// </summary>
-        private MetadataReader _systemModuleReader;
+        private IAssemblyMetadata _systemModuleReader;
 
         private readonly IAssemblyResolver _assemblyResolver;
 
         /// <summary>
         /// Reference assembly cache indexed by module indices as used in signatures
         /// </summary>
-        private List<MetadataReader> _assemblyCache;
-
-        /// <summary>
-        /// Assembly headers for composite R2R images
-        /// </summary>
-        private List<ReadyToRunCoreHeader> _assemblyHeaders;
+        private List<IAssemblyMetadata> _assemblyCache;
 
         // Header
         private OperatingSystem _operatingSystem;
@@ -109,7 +104,7 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// Underlying PE image reader is used to access raw PE structures like header
         /// or section list.
         /// </summary>
-        public PEReader PEReader { get; private set; }
+        public PEReader CompositeReader { get; private set; }
 
         /// <summary>
         /// Byte array containing the ReadyToRun image
@@ -363,10 +358,10 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// </summary>
         /// <param name="filename">PE image</param>
         /// <exception cref="BadImageFormatException">The Cor header flag must be ILLibrary</exception>
-        public ReadyToRunReader(IAssemblyResolver assemblyResolver, MetadataReader metadata, PEReader peReader, string filename)
+        public ReadyToRunReader(IAssemblyResolver assemblyResolver, IAssemblyMetadata metadata, PEReader peReader, string filename)
         {
             _assemblyResolver = assemblyResolver;
-            PEReader = peReader;
+            CompositeReader = peReader;
             Filename = filename;
             Initialize(metadata);
         }
@@ -383,32 +378,31 @@ namespace ILCompiler.Reflection.ReadyToRun
             Initialize(metadata: null);
         }
 
-        private unsafe void Initialize(MetadataReader metadata)
+        private unsafe void Initialize(IAssemblyMetadata metadata)
         {
-            _assemblyCache = new List<MetadataReader>();
-            _assemblyHeaders = new List<ReadyToRunCoreHeader>();
+            _assemblyCache = new List<IAssemblyMetadata>();
 
-            if (PEReader == null)
+            if (CompositeReader == null)
             {
                 byte[] image = File.ReadAllBytes(Filename);
                 Image = image;
 
-                PEReader = new PEReader(Unsafe.As<byte[], ImmutableArray<byte>>(ref image));
+                CompositeReader = new PEReader(Unsafe.As<byte[], ImmutableArray<byte>>(ref image));
             }
             else
             {
-                ImmutableArray<byte> content = PEReader.GetEntireImage().GetContent();
+                ImmutableArray<byte> content = CompositeReader.GetEntireImage().GetContent();
                 Image = Unsafe.As<ImmutableArray<byte>, byte[]>(ref content);
             }
 
-            if (metadata == null && PEReader.HasMetadata)
+            if (metadata == null && CompositeReader.HasMetadata)
             {
-                metadata = PEReader.GetMetadataReader();
+                metadata = new StandaloneAssemblyMetadata(CompositeReader);
             }
 
             if (metadata != null)
             {
-                if ((PEReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) == 0)
+                if ((CompositeReader.PEHeaders.CorHeader.Flags & CorFlags.ILLibrary) == 0)
                 {
                     if (!TryLocateNativeReadyToRunHeader())
                         throw new BadImageFormatException("The file is not a ReadyToRun image");
@@ -419,7 +413,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                 {
                     _assemblyCache.Add(metadata);
 
-                    DirectoryEntry r2rHeaderDirectory = PEReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
+                    DirectoryEntry r2rHeaderDirectory = CompositeReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
                     _readyToRunHeaderRVA = r2rHeaderDirectory.RelativeVirtualAddress;
                     Debug.Assert(!Composite);
                 }
@@ -490,7 +484,7 @@ namespace ILCompiler.Reflection.ReadyToRun
 
         private bool TryLocateNativeReadyToRunHeader()
         {
-            PEExportTable exportTable = PEReader.GetExportTable();
+            PEExportTable exportTable = CompositeReader.GetExportTable();
             if (exportTable.TryGetValue("RTR_HEADER", out _readyToRunHeaderRVA))
             {
                 _composite = true;
@@ -499,7 +493,7 @@ namespace ILCompiler.Reflection.ReadyToRun
             return false;
         }
 
-        private MetadataReader GetSystemModuleMetadataReader()
+        private IAssemblyMetadata GetSystemModuleMetadataReader()
         {
             if (_systemModuleReader == null)
             {
@@ -511,7 +505,7 @@ namespace ILCompiler.Reflection.ReadyToRun
             return _systemModuleReader;
         }
 
-        public MetadataReader GetGlobalMetadataReader()
+        public IAssemblyMetadata GetGlobalMetadata()
         {
             EnsureHeader();
             return (_composite ? null : _assemblyCache[0]);
@@ -523,7 +517,7 @@ namespace ILCompiler.Reflection.ReadyToRun
             {
                 return;
             }
-            uint machine = (uint)PEReader.PEHeaders.CoffHeader.Machine;
+            uint machine = (uint)CompositeReader.PEHeaders.CoffHeader.Machine;
             _operatingSystem = OperatingSystem.Unknown;
             foreach (OperatingSystem os in Enum.GetValues(typeof(OperatingSystem)))
             {
@@ -568,7 +562,7 @@ namespace ILCompiler.Reflection.ReadyToRun
             }
 
 
-            _imageBase = PEReader.PEHeaders.PEHeader.ImageBase;
+            _imageBase = CompositeReader.PEHeaders.PEHeader.ImageBase;
 
             // Initialize R2RHeader
             Debug.Assert(_readyToRunHeaderRVA != 0);
@@ -699,12 +693,12 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// <summary>
         /// Initialize non-generic R2RMethods with method signatures from MethodDefHandle, and runtime function indices from MethodDefEntryPoints
         /// </summary>
-        private void ParseMethodDefEntrypoints(Action<ReadyToRunSection, MetadataReader> methodDefSectionReader)
+        private void ParseMethodDefEntrypoints(Action<ReadyToRunSection, IAssemblyMetadata> methodDefSectionReader)
         {
             ReadyToRunSection methodEntryPointSection;
             if (ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.MethodDefEntryPoints, out methodEntryPointSection))
             {
-                methodDefSectionReader(methodEntryPointSection, GetGlobalMetadataReader());
+                methodDefSectionReader(methodEntryPointSection, GetGlobalMetadata());
             }
             else if (ReadyToRunAssemblyHeaders != null)
             {
@@ -723,9 +717,9 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// are method entrypoints are stored separately for each component assembly of the composite R2R executable.
         /// </summary>
         /// <param name="section">Method entrypoint section to parse</param>
-        /// <param name="metadataReader">ECMA metadata reader representing this method entrypoint section</param>
+        /// <param name="componentReader">Assembly metadata reader representing this method entrypoint section</param>
         /// <param name="isEntryPoint">Set to true for each runtime function index representing a method entrypoint</param>
-        private void ParseMethodDefEntrypointsSection(ReadyToRunSection section, MetadataReader metadataReader, bool[] isEntryPoint)
+        private void ParseMethodDefEntrypointsSection(ReadyToRunSection section, IAssemblyMetadata componentReader, bool[] isEntryPoint)
         {
             int methodDefEntryPointsOffset = GetOffset(section.RelativeVirtualAddress);
             NativeArray methodEntryPoints = new NativeArray(Image, (uint)methodDefEntryPointsOffset);
@@ -740,7 +734,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                     int runtimeFunctionId;
                     int? fixupOffset;
                     GetRuntimeFunctionIndexFromOffset(offset, out runtimeFunctionId, out fixupOffset);
-                    ReadyToRunMethod method = new ReadyToRunMethod(this, this.PEReader, metadataReader, methodHandle, runtimeFunctionId, owningType: null, constrainedType: null, instanceArgs: null, fixupOffset: fixupOffset);
+                    ReadyToRunMethod method = new ReadyToRunMethod(this, componentReader, methodHandle, runtimeFunctionId, owningType: null, constrainedType: null, instanceArgs: null, fixupOffset: fixupOffset);
 
                     if (method.EntryPointRuntimeFunctionId < 0 || method.EntryPointRuntimeFunctionId >= isEntryPoint.Length)
                     {
@@ -764,7 +758,7 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// <param name="section">Method entrypoint section to parse</param>
         /// <param name="metadataReader">ECMA metadata reader representing this method entrypoint section</param>
         /// <param name="isEntryPoint">Set to true for each runtime function index representing a method entrypoint</param>
-        private void ParseMethodDefEntrypointsSectionCustom<TType, TMethod, TGenericContext>(IR2RSignatureTypeProvider<TType, TMethod, TGenericContext> provider, Dictionary<TMethod, ReadyToRunMethod> foundMethods, ReadyToRunSection section, MetadataReader metadataReader)
+        private void ParseMethodDefEntrypointsSectionCustom<TType, TMethod, TGenericContext>(IR2RSignatureTypeProvider<TType, TMethod, TGenericContext> provider, Dictionary<TMethod, ReadyToRunMethod> foundMethods, ReadyToRunSection section, IAssemblyMetadata metadataReader)
         {
             int methodDefEntryPointsOffset = GetOffset(section.RelativeVirtualAddress);
             NativeArray methodEntryPoints = new NativeArray(Image, (uint)methodDefEntryPointsOffset);
@@ -780,7 +774,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                     int? fixupOffset;
                     GetRuntimeFunctionIndexFromOffset(offset, out runtimeFunctionId, out fixupOffset);
                     ReadyToRunMethod r2rMethod = _runtimeFunctionToMethod[runtimeFunctionId];
-                    var customMethod = provider.GetMethodFromMethodDef(metadataReader, MetadataTokens.MethodDefinitionHandle((int)rid), default(TType));
+                    var customMethod = provider.GetMethodFromMethodDef(metadataReader.MetadataReader, MetadataTokens.MethodDefinitionHandle((int)rid), default(TType));
                     
                     if (!Object.ReferenceEquals(customMethod, null) && !foundMethods.ContainsKey(customMethod))
                         foundMethods.Add(customMethod, r2rMethod);
@@ -804,8 +798,8 @@ namespace ILCompiler.Reflection.ReadyToRun
             NativeParser curParser = allEntriesEnum.GetNext();
             while (!curParser.IsNull())
             {
-                MetadataReader mdReader = _composite ? null : _assemblyCache[0];
-                var decoder = new R2RSignatureDecoder<TType, TMethod, TGenericContext>(provider, default(TGenericContext), mdReader, this, (int)curParser.Offset);
+                IAssemblyMetadata mdReader = GetGlobalMetadata();
+                var decoder = new R2RSignatureDecoder<TType, TMethod, TGenericContext>(provider, default(TGenericContext), mdReader.MetadataReader, this, (int)curParser.Offset);
 
                 TMethod customMethod = decoder.ParseMethod();
 
@@ -836,8 +830,8 @@ namespace ILCompiler.Reflection.ReadyToRun
             NativeParser curParser = allEntriesEnum.GetNext();
             while (!curParser.IsNull())
             {
-                MetadataReader mdReader = _composite ? null : _assemblyCache[0];
-                SignatureDecoder decoder = new SignatureDecoder(_assemblyResolver, mdReader, this, (int)curParser.Offset);
+                IAssemblyMetadata mdReader = GetGlobalMetadata();
+                SignatureDecoder decoder = new SignatureDecoder(_assemblyResolver, mdReader?.MetadataReader, this, (int)curParser.Offset);
 
                 string owningType = null;
 
@@ -888,7 +882,6 @@ namespace ILCompiler.Reflection.ReadyToRun
                 GetRuntimeFunctionIndexFromOffset((int)decoder.Offset, out runtimeFunctionId, out fixupOffset);
                 ReadyToRunMethod method = new ReadyToRunMethod(
                     this,
-                    this.PEReader,
                     mdReader,
                     methodHandle,
                     runtimeFunctionId,
@@ -943,7 +936,7 @@ namespace ILCompiler.Reflection.ReadyToRun
             ReadyToRunSection availableTypesSection;
             if (ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.AvailableTypes, out availableTypesSection))
             {
-                ParseAvailableTypesSection(availableTypesSection, GetGlobalMetadataReader());
+                ParseAvailableTypesSection(availableTypesSection, GetGlobalMetadata());
             }
             else if (_readyToRunAssemblyHeaders != null)
             {
@@ -963,7 +956,7 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// as available types are stored separately for each component assembly of the composite R2R executable.
         /// </summary>
         /// <param name="availableTypesSection"></param>
-        private void ParseAvailableTypesSection(ReadyToRunSection availableTypesSection, MetadataReader metadataReader)
+        private void ParseAvailableTypesSection(ReadyToRunSection availableTypesSection, IAssemblyMetadata metadataReader)
         {
             int availableTypesOffset = GetOffset(availableTypesSection.RelativeVirtualAddress);
             NativeParser parser = new NativeParser(Image, (uint)availableTypesOffset);
@@ -980,7 +973,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                 if (isExportedType)
                 {
                     ExportedTypeHandle exportedTypeHandle = MetadataTokens.ExportedTypeHandle((int)rid);
-                    string exportedTypeName = GetExportedTypeFullName(metadataReader, exportedTypeHandle);
+                    string exportedTypeName = GetExportedTypeFullName(metadataReader.MetadataReader, exportedTypeHandle);
                     if (!AvailableTypes.TryGetValue(availableTypesSection, out List<string> sectionTypes))
                     {
                         sectionTypes = new List<string>();
@@ -991,7 +984,7 @@ namespace ILCompiler.Reflection.ReadyToRun
                 else
                 {
                     TypeDefinitionHandle typeDefHandle = MetadataTokens.TypeDefinitionHandle((int)rid);
-                    string typeDefName = MetadataNameFormatter.FormatHandle(metadataReader, typeDefHandle);
+                    string typeDefName = MetadataNameFormatter.FormatHandle(metadataReader.MetadataReader, typeDefHandle);
                     if (!AvailableTypes.TryGetValue(availableTypesSection, out List<string> sectionTypes))
                     {
                         sectionTypes = new List<string>();
@@ -1137,7 +1130,7 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// <param name="rva">The relative virtual address</param>
         public int GetOffset(int rva)
         {
-            return PEReader.GetOffset(rva);
+            return CompositeReader.GetOffset(rva);
         }
 
         /// <summary>
@@ -1196,11 +1189,11 @@ namespace ILCompiler.Reflection.ReadyToRun
         {
             Debug.Assert(refAsmIndex != 0);
 
-            int assemblyRefCount = (_composite ? 0 : _assemblyCache[0].GetTableRowCount(TableIndex.AssemblyRef) + 1);
+            int assemblyRefCount = (_composite ? 0 : _assemblyCache[0].MetadataReader.GetTableRowCount(TableIndex.AssemblyRef) + 1);
             AssemblyReferenceHandle assemblyReferenceHandle;
             if (refAsmIndex < assemblyRefCount)
             {
-                metadataReader = _assemblyCache[0];
+                metadataReader = _assemblyCache[0].MetadataReader;
                 assemblyReferenceHandle = MetadataTokens.AssemblyReferenceHandle(refAsmIndex);
             }
             else
@@ -1223,9 +1216,9 @@ namespace ILCompiler.Reflection.ReadyToRun
         /// </summary>
         /// <param name="refAsmIndex">Reference assembly index</param>
         /// <returns>MetadataReader instance representing the reference assembly</returns>
-        internal MetadataReader OpenReferenceAssembly(int refAsmIndex)
+        internal IAssemblyMetadata OpenReferenceAssembly(int refAsmIndex)
         {
-            MetadataReader result = (refAsmIndex < _assemblyCache.Count ? _assemblyCache[refAsmIndex] : null);
+            IAssemblyMetadata result = (refAsmIndex < _assemblyCache.Count ? _assemblyCache[refAsmIndex] : null);
             if (result == null)
             {
                 AssemblyReferenceHandle assemblyReferenceHandle = GetAssemblyAtIndex(refAsmIndex, out MetadataReader metadataReader);
index c8fca51..9832745 100644 (file)
@@ -66,7 +66,7 @@ namespace ILCompiler.Reflection.ReadyToRun
 
         public static string FormatSignature(IAssemblyResolver assemblyResolver, ReadyToRunReader r2rReader, int imageOffset, out ReadyToRunSignature result)
         {
-            SignatureDecoder decoder = new SignatureDecoder(assemblyResolver, r2rReader.GetGlobalMetadataReader(), r2rReader, imageOffset);
+            SignatureDecoder decoder = new SignatureDecoder(assemblyResolver, r2rReader.GetGlobalMetadata()?.MetadataReader, r2rReader, imageOffset);
             string answer = decoder.ReadR2RSignature(out result);
             return answer;
         }
@@ -697,8 +697,8 @@ namespace ILCompiler.Reflection.ReadyToRun
                 case CorElementType.ELEMENT_TYPE_MODULE_ZAPSIG:
                     {
                         int moduleIndex = (int)ReadUInt();
-                        MetadataReader refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex);
-                        var refAsmDecoder = new R2RSignatureDecoder<TType, TMethod, TGenericContext>(_provider, Context, refAsmReader, _image, _offset, _outerReader, _contextReader);
+                        IAssemblyMetadata refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex);
+                        var refAsmDecoder = new R2RSignatureDecoder<TType, TMethod, TGenericContext>(_provider, Context, refAsmReader.MetadataReader, _image, _offset, _outerReader, _contextReader);
                         var result = refAsmDecoder.ParseType();
                         _offset = refAsmDecoder.Offset;
                         return result;
@@ -1065,8 +1065,8 @@ namespace ILCompiler.Reflection.ReadyToRun
             {
                 fixupType &= ~(uint)ReadyToRunFixupKind.ModuleOverride;
                 int moduleIndex = (int)ReadUIntAndEmitInlineSignatureBinary(builder);
-                MetadataReader refAsmEcmaReader = _contextReader.OpenReferenceAssembly(moduleIndex);
-                moduleDecoder = new SignatureDecoder(Context.Options, refAsmEcmaReader, _image, Offset, refAsmEcmaReader, _contextReader);
+                IAssemblyMetadata refAsmEcmaReader = _contextReader.OpenReferenceAssembly(moduleIndex);
+                moduleDecoder = new SignatureDecoder(Context.Options, refAsmEcmaReader.MetadataReader, _image, Offset, refAsmEcmaReader.MetadataReader, _contextReader);
             }
 
             ReadyToRunSignature result = moduleDecoder.ParseSignature((ReadyToRunFixupKind)fixupType, builder);
@@ -1356,7 +1356,7 @@ namespace ILCompiler.Reflection.ReadyToRun
             builder.Append(base.ParseType());
         }
 
-        public MetadataReader GetMetadataReaderFromModuleOverride()
+        public IAssemblyMetadata GetMetadataReaderFromModuleOverride()
         {
             if (PeekElementType() == CorElementType.ELEMENT_TYPE_MODULE_ZAPSIG)
             {
@@ -1364,7 +1364,7 @@ namespace ILCompiler.Reflection.ReadyToRun
 
                 ReadElementType();
                 int moduleIndex = (int)ReadUInt();
-                MetadataReader refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex);
+                IAssemblyMetadata refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex);
 
                 UpdateOffset(currentOffset);
 
diff --git a/src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/StandaloneAssemblyMetadata.cs b/src/coreclr/src/tools/aot/ILCompiler.Reflection.ReadyToRun/StandaloneAssemblyMetadata.cs
new file mode 100644 (file)
index 0000000..a5ccea1
--- /dev/null
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+
+namespace ILCompiler.Reflection.ReadyToRun
+{
+    /// <summary>
+    /// Metadata access interface for standalone assemblies represented by MSIL PE files.
+    /// </summary>
+    public class StandaloneAssemblyMetadata : IAssemblyMetadata
+    {
+        /// <summary>
+        /// Reader representing the MSIL assembly file.
+        /// </summary>
+        private readonly PEReader _peReader;
+
+        /// <summary>
+        /// Metadata reader for the MSIL assembly. We create one upfront to avoid going
+        /// through the GetMetadataReader() helper and constructing a new instance every time.
+        /// </summary>
+        private readonly MetadataReader _metadataReader;
+
+        public StandaloneAssemblyMetadata(PEReader peReader)
+        {
+            _peReader = peReader;
+            _metadataReader = _peReader.GetMetadataReader();
+        }
+
+        public PEReader ImageReader => _peReader;
+
+        public MetadataReader MetadataReader => _metadataReader;
+    }
+}
index 7371f92..84927fe 100644 (file)
@@ -360,14 +360,16 @@ namespace Microsoft.Diagnostics.Tools.Pgo
             return _metadataStringDecoder;
         }
 
-        MetadataReader IAssemblyResolver.FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile)
+        IAssemblyMetadata IAssemblyResolver.FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile)
         {
-            return ((EcmaAssembly)this.GetModuleForSimpleName(metadataReader.GetString(metadataReader.GetAssemblyReference(assemblyReferenceHandle).Name), false)).MetadataReader;
+            EcmaAssembly ecmaAssembly = (EcmaAssembly)this.GetModuleForSimpleName(metadataReader.GetString(metadataReader.GetAssemblyReference(assemblyReferenceHandle).Name), false);
+            return new StandaloneAssemblyMetadata(ecmaAssembly.PEReader);
         }
 
-        MetadataReader IAssemblyResolver.FindAssembly(string simpleName, string parentFile)
+        IAssemblyMetadata IAssemblyResolver.FindAssembly(string simpleName, string parentFile)
         {
-            return ((EcmaAssembly)this.GetModuleForSimpleName(simpleName, false)).MetadataReader;
+            EcmaAssembly ecmaAssembly = (EcmaAssembly)this.GetModuleForSimpleName(simpleName, false);
+            return new StandaloneAssemblyMetadata(ecmaAssembly.PEReader);
         }
         bool IAssemblyResolver.Naked => false;
 
index f8ca578..2c9bd70 100644 (file)
@@ -8,6 +8,7 @@ using System.Linq;
 using System.Reflection.Metadata.Ecma335;
 
 using ILCompiler.Reflection.ReadyToRun;
+using ILCompiler.Reflection.ReadyToRun.Amd64;
 using Internal.Runtime;
 
 namespace R2RDump
@@ -138,8 +139,8 @@ namespace R2RDump
         {
             writer.WriteLine(theThis.SignatureString);
 
-            writer.WriteLine($"Handle: 0x{MetadataTokens.GetToken(theThis.MetadataReader, theThis.MethodHandle):X8}");
-            writer.WriteLine($"Rid: {MetadataTokens.GetRowNumber(theThis.MetadataReader, theThis.MethodHandle)}");
+            writer.WriteLine($"Handle: 0x{MetadataTokens.GetToken(theThis.ComponentReader.MetadataReader, theThis.MethodHandle):X8}");
+            writer.WriteLine($"Rid: {MetadataTokens.GetRowNumber(theThis.ComponentReader.MetadataReader, theThis.MethodHandle)}");
             if (!options.Naked)
             {
                 writer.WriteLine($"EntryPointRuntimeFunctionId: {theThis.EntryPointRuntimeFunctionId}");
@@ -215,15 +216,16 @@ namespace R2RDump
                     writer.WriteLine($"PersonalityRVA:     0x{amd64UnwindInfo.PersonalityRoutineRVA:X4}");
                 }
 
-                for (int unwindCodeIndex = 0; unwindCodeIndex < amd64UnwindInfo.CountOfUnwindCodes; unwindCodeIndex++)
+                for (int uwcIndex = 0; uwcIndex < amd64UnwindInfo.UnwindCodes.Count; uwcIndex++)
                 {
-                    ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode unwindCode = amd64UnwindInfo.UnwindCodeArray[unwindCodeIndex];
-                    writer.Write($"UnwindCode[{unwindCode.Index}]: ");
+                    UnwindCode unwindCode = amd64UnwindInfo.UnwindCodes[uwcIndex];
+                    writer.Write($"UnwindCode[{uwcIndex}]: ");
                     writer.Write($"CodeOffset 0x{unwindCode.CodeOffset:X4} ");
                     writer.Write($"FrameOffset 0x{unwindCode.FrameOffset:X4} ");
                     writer.Write($"NextOffset 0x{unwindCode.NextFrameOffset} ");
                     writer.Write($"Op {unwindCode.OpInfoStr}");
                     writer.WriteLine();
+                    uwcIndex++;
                 }
             }
             writer.WriteLine();
index 4f3fd9f..7e19653 100644 (file)
@@ -255,7 +255,7 @@ namespace R2RDump
         {
             Dictionary<string, int> sectionMap = new Dictionary<string, int>();
 
-            foreach (SectionHeader sectionHeader in reader.PEReader.PEHeaders.SectionHeaders)
+            foreach (SectionHeader sectionHeader in reader.CompositeReader.PEHeaders.SectionHeaders)
             {
                 sectionMap.Add(sectionHeader.Name, sectionHeader.SizeOfRawData);
             }
index 62f2618..0cfc36d 100644 (file)
@@ -70,7 +70,7 @@ namespace R2RDump
         /// <param name="parentFile">Name of assembly from which we're performing the lookup</param>
         /// <returns></returns>
 
-        public MetadataReader FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile)
+        public IAssemblyMetadata FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile)
         {
             string simpleName = metadataReader.GetString(metadataReader.GetAssemblyReference(assemblyReferenceHandle).Name);
             return FindAssembly(simpleName, parentFile);
@@ -83,7 +83,7 @@ namespace R2RDump
         /// <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 MetadataReader FindAssembly(string simpleName, string parentFile)
+        public IAssemblyMetadata FindAssembly(string simpleName, string parentFile)
         {
             foreach (FileInfo refAsm in Reference ?? Enumerable.Empty<FileInfo>())
             {
@@ -117,7 +117,7 @@ namespace R2RDump
             return null;
         }
 
-        private static unsafe MetadataReader Open(string filename)
+        private static unsafe IAssemblyMetadata Open(string filename)
         {
             byte[] image = File.ReadAllBytes(filename);
 
@@ -128,7 +128,7 @@ namespace R2RDump
                 throw new BadImageFormatException($"ECMA metadata not found in file '{filename}'");
             }
 
-            return peReader.GetMetadataReader();
+            return new StandaloneAssemblyMetadata(peReader);
         }
     }
 
@@ -395,7 +395,7 @@ namespace R2RDump
                     pdbWriter.WritePDBData(r2r.Filename, ProducePdbWriterMethods(r2r));
                 }
 
-                if (!_options.Header && standardDump)
+                if (standardDump)
                 {
                     _dumper.DumpAllMethods();
                 }
@@ -411,8 +411,8 @@ namespace R2RDump
                 MethodInfo mi = new MethodInfo();
                 mi.Name = method.SignatureString;
                 mi.HotRVA = (uint)method.RuntimeFunctions[0].StartAddress;
-                mi.MethodToken = (uint)MetadataTokens.GetToken(method.MetadataReader, method.MethodHandle);
-                mi.AssemblyName = method.MetadataReader.GetString(method.MetadataReader.GetAssemblyDefinition().Name);
+                mi.MethodToken = (uint)MetadataTokens.GetToken(method.ComponentReader.MetadataReader, method.MethodHandle);
+                mi.AssemblyName = method.ComponentReader.MetadataReader.GetString(method.ComponentReader.MetadataReader.GetAssemblyDefinition().Name);
                 mi.ColdRVA = 0;
                 
                 yield return mi;
@@ -428,7 +428,7 @@ namespace R2RDump
         {
             int id;
             bool isNum = ArgStringToInt(query, out id);
-            bool idMatch = isNum && (method.Rid == id || MetadataTokens.GetRowNumber(method.MetadataReader, method.MethodHandle) == id);
+            bool idMatch = isNum && (method.Rid == id || MetadataTokens.GetRowNumber(method.ComponentReader.MetadataReader, method.MethodHandle) == id);
 
             bool sigMatch = false;
             if (exact)
index 19aa23f..3232ab3 100644 (file)
@@ -215,9 +215,9 @@ namespace R2RDump
                 string instr;
                 int instrSize = _disassembler.GetInstruction(rtf, imageOffset, rtfOffset, out instr);
 
-                if (_r2r.Machine == Machine.Amd64 && ((ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo)rtf.UnwindInfo).UnwindCodes.ContainsKey(codeOffset))
+                if (_r2r.Machine == Machine.Amd64 && ((ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo)rtf.UnwindInfo).CodeOffsetToUnwindCodeIndex.TryGetValue(codeOffset, out int unwindCodeIndex))
                 {
-                    ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode code = ((ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo)rtf.UnwindInfo).UnwindCodes[codeOffset];                    
+                    ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode code = ((ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo)rtf.UnwindInfo).UnwindCodes[unwindCodeIndex];
                     _writer.Write($"{indentString}{code.UnwindOp} {code.OpInfoStr}");
                     if (code.NextFrameOffset != -1)
                     {
@@ -345,6 +345,8 @@ namespace R2RDump
                     int rtfOffset = _r2r.GetOffset(section.RelativeVirtualAddress);
                     int rtfEndOffset = rtfOffset + section.Size;
                     int rtfIndex = 0;
+                    _writer.WriteLine("  Index | StartRVA |  EndRVA  | UnwindRVA");
+                    _writer.WriteLine("-----------------------------------------");
                     while (rtfOffset < rtfEndOffset)
                     {
                         int startRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
@@ -354,11 +356,8 @@ namespace R2RDump
                             endRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
                         }
                         int unwindRva = NativeReader.ReadInt32(_r2r.Image, ref rtfOffset);
-                        _writer.WriteLine($"Index: {rtfIndex}");
-                        _writer.WriteLine($"        StartRva: 0x{startRva:X8}");
-                        if (endRva != -1)
-                            _writer.WriteLine($"        EndRva: 0x{endRva:X8}");
-                        _writer.WriteLine($"        UnwindRva: 0x{unwindRva:X8}");
+                        string endRvaText = (endRva != -1 ? endRva.ToString("x8") : "        ");
+                        _writer.WriteLine($"{rtfIndex,7} | {startRva:X8} | {endRvaText} | {unwindRva:X8}");
                         rtfIndex++;
                     }
                     break;
@@ -406,7 +405,7 @@ namespace R2RDump
                     int assemblyRefCount = 0;
                     if (!_r2r.Composite)
                     {
-                        MetadataReader globalReader = _r2r.GetGlobalMetadataReader();
+                        MetadataReader globalReader = _r2r.GetGlobalMetadata().MetadataReader;
                         assemblyRefCount = globalReader.GetTableRowCount(TableIndex.AssemblyRef) + 1;
                         _writer.WriteLine($"MSIL AssemblyRef's ({assemblyRefCount} entries):");
                         for (int assemblyRefIndex = 1; assemblyRefIndex < assemblyRefCount; assemblyRefIndex++)