using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Text;
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
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;
}
}
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() { }
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);
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($" ------------------");
}
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;
- }
- }
}
}
}
else
{
- ClassName = MetadataNameFormatter.FormatHandle(reader.GetGlobalMetadataReader(), MetadataTokens.Handle((int)ClassTokenOrFilterOffset));
+ ClassName = MetadataNameFormatter.FormatHandle(reader.GetGlobalMetadata()?.MetadataReader, MetadataTokens.Handle((int)ClassTokenOrFilterOffset));
}
}
}
--- /dev/null
+// 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; }
+ }
+}
{
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; }
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
/// </summary>
public ReadyToRunMethod(
ReadyToRunReader readyToRunReader,
- PEReader peReader,
- MetadataReader metadataReader,
+ IAssemblyMetadata componentReader,
EntityHandle methodHandle,
int entryPointId,
string owningType,
MethodHandle = methodHandle;
EntryPointRuntimeFunctionId = entryPointId;
- MetadataReader = metadataReader;
+ ComponentReader = componentReader;
EntityHandle owningTypeHandle;
GenericParameterHandleCollection genericParams = default(GenericParameterHandleCollection);
{
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();
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;
}
}
else
{
- DeclaringType = MetadataNameFormatter.FormatHandle(MetadataReader, owningTypeHandle);
+ DeclaringType = MetadataNameFormatter.FormatHandle(ComponentReader.MetadataReader, owningTypeHandle);
}
StringBuilder sb = new StringBuilder();
{
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;
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)
/// <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;
/// 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
/// </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);
}
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");
{
_assemblyCache.Add(metadata);
- DirectoryEntry r2rHeaderDirectory = PEReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
+ DirectoryEntry r2rHeaderDirectory = CompositeReader.PEHeaders.CorHeader.ManagedNativeHeaderDirectory;
_readyToRunHeaderRVA = r2rHeaderDirectory.RelativeVirtualAddress;
Debug.Assert(!Composite);
}
private bool TryLocateNativeReadyToRunHeader()
{
- PEExportTable exportTable = PEReader.GetExportTable();
+ PEExportTable exportTable = CompositeReader.GetExportTable();
if (exportTable.TryGetValue("RTR_HEADER", out _readyToRunHeaderRVA))
{
_composite = true;
return false;
}
- private MetadataReader GetSystemModuleMetadataReader()
+ private IAssemblyMetadata GetSystemModuleMetadataReader()
{
if (_systemModuleReader == null)
{
return _systemModuleReader;
}
- public MetadataReader GetGlobalMetadataReader()
+ public IAssemblyMetadata GetGlobalMetadata()
{
EnsureHeader();
return (_composite ? null : _assemblyCache[0]);
{
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)))
{
}
- _imageBase = PEReader.PEHeaders.PEHeader.ImageBase;
+ _imageBase = CompositeReader.PEHeaders.PEHeader.ImageBase;
// Initialize R2RHeader
Debug.Assert(_readyToRunHeaderRVA != 0);
/// <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)
{
/// 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);
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)
{
/// <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);
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);
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();
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;
GetRuntimeFunctionIndexFromOffset((int)decoder.Offset, out runtimeFunctionId, out fixupOffset);
ReadyToRunMethod method = new ReadyToRunMethod(
this,
- this.PEReader,
mdReader,
methodHandle,
runtimeFunctionId,
ReadyToRunSection availableTypesSection;
if (ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.AvailableTypes, out availableTypesSection))
{
- ParseAvailableTypesSection(availableTypesSection, GetGlobalMetadataReader());
+ ParseAvailableTypesSection(availableTypesSection, GetGlobalMetadata());
}
else if (_readyToRunAssemblyHeaders != null)
{
/// 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);
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>();
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>();
/// <param name="rva">The relative virtual address</param>
public int GetOffset(int rva)
{
- return PEReader.GetOffset(rva);
+ return CompositeReader.GetOffset(rva);
}
/// <summary>
{
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
/// </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);
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;
}
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;
{
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);
builder.Append(base.ParseType());
}
- public MetadataReader GetMetadataReaderFromModuleOverride()
+ public IAssemblyMetadata GetMetadataReaderFromModuleOverride()
{
if (PeekElementType() == CorElementType.ELEMENT_TYPE_MODULE_ZAPSIG)
{
ReadElementType();
int moduleIndex = (int)ReadUInt();
- MetadataReader refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex);
+ IAssemblyMetadata refAsmReader = _contextReader.OpenReferenceAssembly(moduleIndex);
UpdateOffset(currentOffset);
--- /dev/null
+// 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;
+ }
+}
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;
using System.Reflection.Metadata.Ecma335;
using ILCompiler.Reflection.ReadyToRun;
+using ILCompiler.Reflection.ReadyToRun.Amd64;
using Internal.Runtime;
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}");
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();
{
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);
}
/// <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);
/// <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>())
{
return null;
}
- private static unsafe MetadataReader Open(string filename)
+ private static unsafe IAssemblyMetadata Open(string filename)
{
byte[] image = File.ReadAllBytes(filename);
throw new BadImageFormatException($"ECMA metadata not found in file '{filename}'");
}
- return peReader.GetMetadataReader();
+ return new StandaloneAssemblyMetadata(peReader);
}
}
pdbWriter.WritePDBData(r2r.Filename, ProducePdbWriterMethods(r2r));
}
- if (!_options.Header && standardDump)
+ if (standardDump)
{
_dumper.DumpAllMethods();
}
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;
{
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)
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)
{
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);
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;
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++)