Skip to content

R2RDump changes to allow separation of presentation from parsing #267

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 16, 2019

Conversation

cshung
Copy link
Contributor

@cshung cshung commented Nov 26, 2019

The overall goal of this refactoring is to separate parsing from the presentation so that parsing can be its own library and the presentation is stacked on top of it.

The goal is to have a .NET Core console application, depending on a class library targeting .NET Standard 2.0, so that the library is virtually usable anywhere we cared.

To make it compile, I have to make some changes, here is an overview of significant changes I made:

  1. Change all the WriteTo() instance methods into extension methods and placed in Extensions.cs.
  2. Expose various DebugInfo structures
  3. Sort DebugInfo outside of the parsing
  4. Remove dependency of EcmaMetadataReader/SignatureDecoder on DumpOptions, and use an IAssemblyResolver instance instead.
  5. Expose various Native* structures to allow DumpSectionObjects in TextDumper/XmlDumper to compile.

Hopefully this can make the review easier.

There are few things that I wanted to do but turn out trickier:

  1. Avoid exposing the Native* structs - it appears to me how to read the sections should be encapsulated within the library itself
  2. Split IAssemblyResolver and SignatureFormattingOptions
  3. Rethink about error tolerance - how do we deal with the various 'Warnings'?

Last but not least, here is a summary of the public interface of the new library, it is fairly large now. It would be nice if we can make this smaller and cleaner:

namespace ILCompiler.Reflection.ReadyToRun
{
    public abstract class BaseGcInfo
    {
        protected BaseGcInfo();
        public int CodeLength { get; set; }
        public List<List<BaseGcSlot>> LiveSlotsAtSafepoints { get; set; }
        public int Offset { get; set; }
        public int Size { get; set; }
        public Dictionary<int,List<BaseGcTransition>> Transitions { get; set; }
    }

    public abstract class BaseGcSlot
    {
        protected BaseGcSlot();
    }

    public abstract class BaseGcTransition
    {
        public BaseGcTransition();
        public BaseGcTransition(int codeOffset);
        public int CodeOffset { get; set; }
    }

    public abstract class BaseUnwindInfo
    {
        protected BaseUnwindInfo();
        public int Size { get; set; }
    }

    public class DebugInfo
    {
        public DebugInfo(byte[] image, int offset, Machine machine);
        public List<DebugInfoBoundsEntry> BoundsList { get; }
        public Machine Machine { get; }
        public List<NativeVarInfo> VariablesList { get; }
        public static string GetPlatformSpecificRegister(Machine machine, int regnum);
    }

    public struct DebugInfoBoundsEntry
    {
        public uint ILOffset;
        public uint NativeOffset;
        public SourceTypes SourceTypes;
    }

    public class DisassemblingGenericContext
    {
        public DisassemblingGenericContext(string[] typeParameters, string[] methodParameters);
        public string[] MethodParameters { get; }
        public string[] TypeParameters { get; }
    }

    public class DisassemblingTypeProvider: ISignatureTypeProvider
    {
        public DisassemblingTypeProvider();
        public virtual string GetArrayType(string elementType, ArrayShape shape);
        public virtual string GetByReferenceType(string elementType);
        public virtual string GetFunctionPointerType(MethodSignature<string> signature);
        public virtual string GetGenericInstantiation(string genericType, ImmutableArray<string> typeArguments);
        public virtual string GetGenericMethodParameter(DisassemblingGenericContext genericContext, int index);
        public virtual string GetGenericTypeParameter(DisassemblingGenericContext genericContext, int index);
        public virtual string GetModifiedType(string modifierType, string unmodifiedType, bool isRequired);
        public virtual string GetPinnedType(string elementType);
        public virtual string GetPointerType(string elementType);
        public virtual string GetPrimitiveType(PrimitiveTypeCode typeCode);
        public virtual string GetSZArrayType(string elementType);
        public virtual string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind);
        public virtual string GetTypeFromHandle(MetadataReader reader, DisassemblingGenericContext genericContext, EntityHandle handle);
        public virtual string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind);
        public virtual string GetTypeFromSpecification(MetadataReader reader, DisassemblingGenericContext genericContext, TypeSpecificationHandle handle, byte rawTypeKind);
    }

    public class EcmaMetadataReader
    {
        public EcmaMetadataReader();
        public EcmaMetadataReader(IAssemblyResolver assemblyResolver, string filename, List<string> manifestReferenceAssemblies);
        protected Dictionary<string,EcmaMetadataReader> _assemblyCache;
        protected IAssemblyResolver _assemblyResolver;
        public readonly List<string> ManifestReferenceAssemblies;
        public readonly MetadataReader MetadataReader;
        public readonly PEReader PEReader;
        public string Filename { get; set; }
        public byte[] Image { get; }
        public EcmaMetadataReader OpenReferenceAssembly(int refAsmIndex);
    }

    public class EHClause
    {
        public EHClause(R2RReader reader, int offset);
        public string ClassName;
        public uint ClassTokenOrFilterOffset;
        public uint HandlerEnd;
        public uint HandlerOffset;
        public const int Length;
        public uint TryEnd;
        public uint TryOffset;
        public void WriteTo(TextWriter writer, int methodRva);
    }

    public class EHInfo
    {
        public EHInfo(R2RReader reader, int ehInfoRva, int methodRva, int offset, int clauseCount);
        public readonly EHClause[] EHClauses;
        public readonly int EHInfoRVA;
        public readonly int MethodRVA;
        public void WriteTo(TextWriter writer);
    }

    public class EHInfoLocation
    {
        public EHInfoLocation(int ehInfoRva, int clauseCount);
        public readonly int ClauseCount;
        public readonly int EHInfoRVA;
    }

    public class EHLookupTable
    {
        public EHLookupTable(byte[] image, int offset, int length);
        public readonly Dictionary<int,EHInfoLocation> RuntimeFunctionToEHInfoMap;
    }

    public struct FixupCell
    {
        public FixupCell(int index, uint tableIndex, uint cellOffset, string signature);
        public uint CellOffset;
        public string Signature;
        public uint TableIndex;
        public int Index { get; set; }
    }

    public class GcInfoTypes
    {
    }

    public class GCRefMap
    {
        public GCRefMap();
        public GCRefMap(uint stackPop, GCRefMapEntry[] entries);
        public readonly GCRefMapEntry[] Entries;
        public const int GCREFMAP_LOOKUP_STRIDE;
        public const uint InvalidStackPop;
        public readonly uint StackPop;
    }

    public class GCRefMapDecoder
    {
        public GCRefMapDecoder(R2RReader reader, int offset);
        public bool AtEnd();
        public int CurrentPos();
        public int GetBit();
        public int GetInt();
        public int GetOffset();
        public int GetTwoBit();
        public GCRefMap ReadMap();
        public uint ReadStackPop();
        public CORCOMPILE_GCREFMAP_TOKENS ReadToken();
    }

    public struct GCRefMapEntry
    {
        public GCRefMapEntry(int offset, CORCOMPILE_GCREFMAP_TOKENS token);
        public readonly int Offset;
        public readonly CORCOMPILE_GCREFMAP_TOKENS Token;
    }

    public class GcStackSlot
    {
        public GcStackSlot();
        public GcStackSlot(int spOffset, GcStackSlotBase stackSlotBase);
        public GcStackSlotBase Base { get; set; }
        public int SpOffset { get; set; }
        public override string ToString();
    }

    public interface IAssemblyResolver
    {
        public bool InlineSignatureBinary { get; }
        public bool Naked { get; }
        public bool SignatureBinary { get; }
        public string FindAssembly(string name, string filename);
    }

    public struct InstanceMethod
    {
        public InstanceMethod(byte bucket, R2RMethod method);
        public byte Bucket;
        public R2RMethod Method;
    }

    public class MetadataNameFormatter: DisassemblingTypeProvider, ISignatureTypeProvider
    {
        public MetadataNameFormatter(MetadataReader metadataReader);
        public static string FormatHandle(MetadataReader metadataReader, Handle handle, bool namespaceQualified, string owningTypeOverride, string signaturePrefix);
        public static string FormatSignature(IAssemblyResolver assemblyResolver, EcmaMetadataReader ecmaReader, int imageOffset);
    }

    public class NativeArray
    {
        public NativeArray(byte[] image, uint offset);
        public uint GetCount();
        public override string ToString();
        public bool TryGetAt(byte[] image, uint index, ref int pOffset);
    }

    public struct NativeCuckooFilter
    {
        public NativeCuckooFilter(byte[] image, int filterStartOffset, int filterEndOffset);
        public override string ToString();
    }

    public struct NativeHashtable
    {
        public NativeHashtable(byte[] image, NativeParser parser, uint endOffset);
        public AllEntriesEnumerator EnumerateAllEntries();
        public Enumerator Lookup(int hashcode);
        public override string ToString();
    }

    public struct NativeParser
    {
        public NativeParser(byte[] image, uint offset, byte lowHashcode);
        public byte LowHashcode { get; }
        public uint Offset { get; set; }
        public byte GetByte();
        public uint GetCompressedData();
        public NativeParser GetParserFromRelativeOffset();
        public uint GetRelativeOffset();
        public int GetSigned();
        public uint GetUnsigned();
        public bool IsNull();
    }

    public class NativeReader
    {
        public NativeReader();
        public static uint DecodeSigned(byte[] image, uint offset, ref int pValue);
        public static int DecodeSignedGc(byte[] image, ref int start);
        public static uint DecodeUDelta(byte[] image, ref int start, uint lastValue);
        public static uint DecodeUnsigned(byte[] image, uint offset, ref uint pValue);
        public static uint DecodeUnsignedGc(byte[] image, ref int start);
        public static int DecodeVarLengthSigned(byte[] image, int len, ref int bitOffset);
        public static uint DecodeVarLengthUnsigned(byte[] image, int len, ref int bitOffset);
        public static int ReadBits(byte[] image, int numBits, ref int bitOffset);
        public static byte ReadByte(byte[] image, ref int start);
        public static uint ReadCompressedData(byte[] image, ref int start);
        public static int ReadInt32(byte[] image, ref int start);
        public static long ReadInt64(byte[] image, ref int start);
        public static ushort ReadUInt16(byte[] image, ref int start);
        public static uint ReadUInt32(byte[] image, ref int start);
    }

    public struct NativeVarInfo
    {
        public uint EndOffset;
        public uint StartOffset;
        public VarLoc VariableLocation;
        public uint VariableNumber;
    }

    public class NativeVarInfoComparer: IComparer
    {
        public NativeVarInfoComparer();
        public int Compare(NativeVarInfo left, NativeVarInfo right);
    }

    public class R2RHeader
    {
        public R2RHeader();
        public R2RHeader(byte[] image, int rva, int curOffset);
        public const uint READYTORUN_SIGNATURE;
        public uint Flags { get; set; }
        public ushort MajorVersion { get; set; }
        public ushort MinorVersion { get; set; }
        public int RelativeVirtualAddress { get; set; }
        public IDictionary<SectionType,R2RSection> Sections { get; }
        public uint Signature { get; set; }
        public string SignatureString { get; set; }
        public int Size { get; set; }
        public override string ToString();
    }

    public struct R2RImportSection
    {
        public R2RImportSection(int index, R2RReader reader, int rva, int size, CorCompileImportFlags flags, byte type, byte entrySize, int signatureRVA, List<ImportSectionEntry> entries, int auxDataRVA, int auxDataOffset, Machine machine, ushort majorVersion);
        public int AuxiliaryDataRVA { get; set; }
        public int AuxiliaryDataSize { get; set; }
        public List<ImportSectionEntry> Entries { get; set; }
        public byte EntrySize { get; set; }
        public CorCompileImportFlags Flags { get; set; }
        public int Index { get; set; }
        public int SectionRVA { get; set; }
        public int SectionSize { get; set; }
        public int SignatureRVA { get; set; }
        public CorCompileImportType Type { get; set; }
        public override string ToString();
        public void WriteTo(TextWriter writer);
    }

    public class R2RMethod
    {
        public R2RMethod();
        public R2RMethod(int index, MetadataReader metadataReader, EntityHandle methodHandle, int entryPointId, string owningType, string constrainedType, string[] instanceArgs, FixupCell[] fixups);
        public string DeclaringType { get; set; }
        public int EntryPointRuntimeFunctionId { get; set; }
        public FixupCell[] Fixups { get; set; }
        public BaseGcInfo GcInfo { get; set; }
        public int Index { get; set; }
        public MetadataReader MetadataReader { get; set; }
        public EntityHandle MethodHandle { get; set; }
        public string Name { get; set; }
        public uint Rid { get; set; }
        public IList<RuntimeFunction> RuntimeFunctions { get; }
        public MethodSignature<string> Signature { get; }
        public string SignatureString { get; set; }
    }

    public class R2RReader: EcmaMetadataReader
    {
        public R2RReader();
        public R2RReader(IAssemblyResolver assemblyResolver, string filename);
        public Architecture Architecture { get; set; }
        public IList<string> AvailableTypes { get; }
        public string CompilerIdentifier { get; }
        public EHLookupTable EHLookupTable { get; }
        public ulong ImageBase { get; set; }
        public Dictionary<int,string> ImportCellNames { get; }
        public IList<R2RImportSection> ImportSections { get; }
        public IList<InstanceMethod> InstanceMethods { get; }
        public bool IsR2R { get; set; }
        public Machine Machine { get; set; }
        public OperatingSystem OS { get; set; }
        public int PointerSize { get; set; }
        public R2RHeader R2RHeader { get; }
        public IList<R2RMethod> R2RMethods { get; }
        public bool DisassemblerArchitectureSupported();
        public static string GetExportedTypeFullName(MetadataReader mdReader, ExportedTypeHandle handle);
        public int GetOffset(int rva);
        public bool InputArchitectureSupported();
    }

    public struct R2RSection
    {
        public R2RSection(SectionType type, int rva, int size);
        public int RelativeVirtualAddress { get; set; }
        public int Size { get; set; }
        public SectionType Type { get; set; }
        public override string ToString();
    }

    public class RuntimeFunction
    {
        public RuntimeFunction();
        public RuntimeFunction(int id, int startRva, int endRva, int unwindRva, int codeOffset, R2RMethod method, BaseUnwindInfo unwindInfo, BaseGcInfo gcInfo, EHInfo ehInfo, DebugInfo debugInfo);
        public int CodeOffset { get; set; }
        public DebugInfo DebugInfo { get; }
        public EHInfo EHInfo { get; }
        public int Id { get; set; }
        public R2RMethod Method { get; }
        public int Size { get; set; }
        public int StartAddress { get; set; }
        public BaseUnwindInfo UnwindInfo { get; }
        public int UnwindRVA { get; set; }
    }

    public class SignatureDecoder
    {
        public SignatureDecoder(IAssemblyResolver options, EcmaMetadataReader ecmaReader, byte[] signature, int offset, EcmaMetadataReader contextReader);
        public SignatureDecoder(IAssemblyResolver options, EcmaMetadataReader ecmaReader, int offset);
        public int Offset { get; }
        public MetadataReader GetMetadataReaderFromModuleOverride();
        public CorElementType PeekElementType();
        public byte ReadByte();
        public CorElementType ReadElementType();
        public int ReadInt();
        public string ReadR2RSignature();
        public uint ReadToken();
        public string ReadTypeSignature();
        public string ReadTypeSignatureNoEmit();
        public uint ReadUInt();
    }

    public abstract class TransitionBlock
    {
        protected TransitionBlock();
        public R2RReader _reader;
        public abstract int NumArgumentRegisters { get; }
        public abstract int NumCalleeSavedRegisters { get; }
        public int OffsetOfArgs { get; }
        public abstract int OffsetOfArgumentRegisters { get; }
        public abstract int PointerSize { get; }
        public int SizeOfArgumentRegisters { get; }
        public int SizeOfCalleeSavedRegisters { get; }
        public abstract int SizeOfTransitionBlock { get; }
        public static TransitionBlock FromReader(R2RReader reader);
        public virtual int OffsetFromGCRefMapPos(int pos);
    }

    public struct VarLoc
    {
        public int Data1;
        public int Data2;
        public int Data3;
        public VarLocType VarLocType;
    }

    public enum CORCOMPILE_FIXUP_BLOB_KIND
    {
        ENCODE_MODULE_OVERRIDE,
    }

    public enum CORCOMPILE_GCREFMAP_TOKENS
    {
        GCREFMAP_INTERIOR,
        GCREFMAP_METHOD_PARAM,
        GCREFMAP_REF,
        GCREFMAP_SKIP,
        GCREFMAP_TYPE_PARAM,
        GCREFMAP_VASIG_COOKIE,
    }

    public enum CorCompileImportFlags
    {
        CORCOMPILE_IMPORT_FLAGS_CODE,
        CORCOMPILE_IMPORT_FLAGS_EAGER,
        CORCOMPILE_IMPORT_FLAGS_PCODE,
        CORCOMPILE_IMPORT_FLAGS_UNKNOWN,
    }

    public enum CorCompileImportType
    {
        CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD,
        CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE,
        CORCOMPILE_IMPORT_TYPE_STRING_HANDLE,
        CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH,
        CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE,
        CORCOMPILE_IMPORT_TYPE_UNKNOWN,
        CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD,
    }

    public enum CorElementType
    {
        ELEMENT_TYPE_ARRAY,
        ELEMENT_TYPE_BOOLEAN,
        ELEMENT_TYPE_BYREF,
        ELEMENT_TYPE_CANON_ZAPSIG,
        ELEMENT_TYPE_CHAR,
        ELEMENT_TYPE_CLASS,
        ELEMENT_TYPE_CMOD_OPT,
        ELEMENT_TYPE_CMOD_REQD,
        ELEMENT_TYPE_FNPTR,
        ELEMENT_TYPE_GENERICINST,
        ELEMENT_TYPE_HANDLE,
        ELEMENT_TYPE_I,
        ELEMENT_TYPE_I1,
        ELEMENT_TYPE_I2,
        ELEMENT_TYPE_I4,
        ELEMENT_TYPE_I8,
        ELEMENT_TYPE_MODULE_ZAPSIG,
        ELEMENT_TYPE_MVAR,
        ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG,
        ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG,
        ELEMENT_TYPE_OBJECT,
        ELEMENT_TYPE_PINNED,
        ELEMENT_TYPE_PTR,
        ELEMENT_TYPE_R4,
        ELEMENT_TYPE_R8,
        ELEMENT_TYPE_SENTINEL,
        ELEMENT_TYPE_STRING,
        ELEMENT_TYPE_SZARRAY,
        ELEMENT_TYPE_TYPEDBYREF,
        ELEMENT_TYPE_U,
        ELEMENT_TYPE_U1,
        ELEMENT_TYPE_U2,
        ELEMENT_TYPE_U4,
        ELEMENT_TYPE_U8,
        ELEMENT_TYPE_VALUETYPE,
        ELEMENT_TYPE_VAR,
        ELEMENT_TYPE_VAR_ZAPSIG,
        ELEMENT_TYPE_VOID,
        Invalid,
    }

    [FlagsAttribute(..)]
    public enum CorExceptionFlag
    {
        COR_ILEXCEPTION_CLAUSE_DEPRECATED,
        COR_ILEXCEPTION_CLAUSE_DUPLICATED,
        COR_ILEXCEPTION_CLAUSE_FAULT,
        COR_ILEXCEPTION_CLAUSE_FILTER,
        COR_ILEXCEPTION_CLAUSE_FINALLY,
        COR_ILEXCEPTION_CLAUSE_KIND_MASK,
        COR_ILEXCEPTION_CLAUSE_NONE,
        COR_ILEXCEPTION_CLAUSE_OFFSETLEN,
    }

    public enum CorTokenType
    {
        mdtAssembly,
        mdtAssemblyRef,
        mdtBaseType,
        mdtCustomAttribute,
        mdtEvent,
        mdtExportedType,
        mdtFieldDef,
        mdtFile,
        mdtGenericParam,
        mdtGenericParamConstraint,
        mdtInterfaceImpl,
        mdtManifestResource,
        mdtMemberRef,
        mdtMethodDef,
        mdtMethodImpl,
        mdtMethodSpec,
        mdtModule,
        mdtModuleRef,
        mdtName,
        mdtParamDef,
        mdtPermission,
        mdtProperty,
        mdtSignature,
        mdtString,
        mdtTypeDef,
        mdtTypeRef,
        mdtTypeSpec,
    }

    public enum GcSlotFlags
    {
        GC_SLOT_BASE,
        GC_SLOT_INTERIOR,
        GC_SLOT_PINNED,
        GC_SLOT_UNTRACKED,
    }

    public enum GcStackSlotBase
    {
        GC_CALLER_SP_REL,
        GC_FRAMEREG_REL,
        GC_SP_REL,
        GC_SPBASE_FIRST,
        GC_SPBASE_LAST,
    }

    public enum ImplicitILArguments
    {
        Max,
        ReturnBuffer,
        TypeContext,
        Unknown,
        VarArgsHandle,
    }

    public enum MappingTypes
    {
        Epilog,
        MaxMappingValue,
        NoMapping,
        Prolog,
    }

    public enum OperatingSystem
    {
        Apple,
        FreeBSD,
        Linux,
        NetBSD,
        Unknown,
        Windows,
    }

    [FlagsAttribute(..)]
    public enum ReadyToRunFieldSigFlags
    {
        READYTORUN_FIELD_SIG_IndexInsteadOfToken,
        READYTORUN_FIELD_SIG_MemberRefToken,
        READYTORUN_FIELD_SIG_OwnerType,
    }

    public enum ReadyToRunFixupKind
    {
        READYTORUN_FIXUP_CctorTrigger,
        READYTORUN_FIXUP_Check_FieldOffset,
        READYTORUN_FIXUP_Check_TypeLayout,
        READYTORUN_FIXUP_ChkCast,
        READYTORUN_FIXUP_DeclaringTypeHandle,
        READYTORUN_FIXUP_DelegateCtor,
        READYTORUN_FIXUP_FieldAddress,
        READYTORUN_FIXUP_FieldBaseOffset,
        READYTORUN_FIXUP_FieldHandle,
        READYTORUN_FIXUP_FieldOffset,
        READYTORUN_FIXUP_Helper,
        READYTORUN_FIXUP_IndirectPInvokeTarget,
        READYTORUN_FIXUP_IsInstanceOf,
        READYTORUN_FIXUP_MethodDictionary,
        READYTORUN_FIXUP_MethodDictionaryLookup,
        READYTORUN_FIXUP_MethodEntry,
        READYTORUN_FIXUP_MethodEntry_DefToken,
        READYTORUN_FIXUP_MethodEntry_RefToken,
        READYTORUN_FIXUP_MethodHandle,
        READYTORUN_FIXUP_NewArray,
        READYTORUN_FIXUP_NewObject,
        READYTORUN_FIXUP_PInvokeTarget,
        READYTORUN_FIXUP_StaticBaseGC,
        READYTORUN_FIXUP_StaticBaseNonGC,
        READYTORUN_FIXUP_StringHandle,
        READYTORUN_FIXUP_ThisObjDictionaryLookup,
        READYTORUN_FIXUP_ThreadStaticBaseGC,
        READYTORUN_FIXUP_ThreadStaticBaseNonGC,
        READYTORUN_FIXUP_TypeDictionary,
        READYTORUN_FIXUP_TypeDictionaryLookup,
        READYTORUN_FIXUP_TypeHandle,
        READYTORUN_FIXUP_VirtualEntry,
        READYTORUN_FIXUP_VirtualEntry_DefToken,
        READYTORUN_FIXUP_VirtualEntry_RefToken,
        READYTORUN_FIXUP_VirtualEntry_Slot,
    }

    [FlagsAttribute(..)]
    public enum ReadyToRunHelper
    {
        READYTORUN_HELPER_Box,
        READYTORUN_HELPER_Box_Nullable,
        READYTORUN_HELPER_ByRefWriteBarrier,
        READYTORUN_HELPER_CheckCastAny,
        READYTORUN_HELPER_CheckedWriteBarrier,
        READYTORUN_HELPER_CheckedWriteBarrier_EAX,
        READYTORUN_HELPER_CheckedWriteBarrier_EBP,
        READYTORUN_HELPER_CheckedWriteBarrier_EBX,
        READYTORUN_HELPER_CheckedWriteBarrier_ECX,
        READYTORUN_HELPER_CheckedWriteBarrier_EDI,
        READYTORUN_HELPER_CheckedWriteBarrier_ESI,
        READYTORUN_HELPER_CheckInstanceAny,
        READYTORUN_HELPER_Dbl2Int,
        READYTORUN_HELPER_Dbl2IntOvf,
        READYTORUN_HELPER_Dbl2Lng,
        READYTORUN_HELPER_Dbl2LngOvf,
        READYTORUN_HELPER_Dbl2UInt,
        READYTORUN_HELPER_Dbl2UIntOvf,
        READYTORUN_HELPER_Dbl2ULng,
        READYTORUN_HELPER_Dbl2ULngOvf,
        READYTORUN_HELPER_DblRem,
        READYTORUN_HELPER_DblRound,
        READYTORUN_HELPER_DelayLoad_Helper,
        READYTORUN_HELPER_DelayLoad_Helper_Obj,
        READYTORUN_HELPER_DelayLoad_Helper_ObjObj,
        READYTORUN_HELPER_DelayLoad_MethodCall,
        READYTORUN_HELPER_Div,
        READYTORUN_HELPER_EndCatch,
        READYTORUN_HELPER_FailFast,
        READYTORUN_HELPER_FltRem,
        READYTORUN_HELPER_FltRound,
        READYTORUN_HELPER_GCPoll,
        READYTORUN_HELPER_GenericGcStaticBase,
        READYTORUN_HELPER_GenericGcTlsBase,
        READYTORUN_HELPER_GenericNonGcStaticBase,
        READYTORUN_HELPER_GenericNonGcTlsBase,
        READYTORUN_HELPER_GetRuntimeFieldHandle,
        READYTORUN_HELPER_GetRuntimeMethodHandle,
        READYTORUN_HELPER_GetRuntimeTypeHandle,
        READYTORUN_HELPER_GetString,
        READYTORUN_HELPER_GSCookie,
        READYTORUN_HELPER_Invalid,
        READYTORUN_HELPER_Ldelema_Ref,
        READYTORUN_HELPER_LDiv,
        READYTORUN_HELPER_LLsh,
        READYTORUN_HELPER_LMod,
        READYTORUN_HELPER_LMul,
        READYTORUN_HELPER_LMulOfv,
        READYTORUN_HELPER_Lng2Dbl,
        READYTORUN_HELPER_LogMethodEnter,
        READYTORUN_HELPER_LRsh,
        READYTORUN_HELPER_LRsz,
        READYTORUN_HELPER_MemCpy,
        READYTORUN_HELPER_MemSet,
        READYTORUN_HELPER_Mod,
        READYTORUN_HELPER_Module,
        READYTORUN_HELPER_MonitorEnter,
        READYTORUN_HELPER_MonitorExit,
        READYTORUN_HELPER_NewArray,
        READYTORUN_HELPER_NewMultiDimArr,
        READYTORUN_HELPER_NewMultiDimArr_NonVarArg,
        READYTORUN_HELPER_NewObject,
        READYTORUN_HELPER_Overflow,
        READYTORUN_HELPER_PersonalityRoutine,
        READYTORUN_HELPER_PersonalityRoutineFilterFunclet,
        READYTORUN_HELPER_PInvokeBegin,
        READYTORUN_HELPER_PInvokeEnd,
        READYTORUN_HELPER_Rethrow,
        READYTORUN_HELPER_RngChkFail,
        READYTORUN_HELPER_StackProbe,
        READYTORUN_HELPER_Stelem_Ref,
        READYTORUN_HELPER_Throw,
        READYTORUN_HELPER_ThrowDivZero,
        READYTORUN_HELPER_ThrowNullRef,
        READYTORUN_HELPER_UDiv,
        READYTORUN_HELPER_ULDiv,
        READYTORUN_HELPER_ULMod,
        READYTORUN_HELPER_ULMulOvf,
        READYTORUN_HELPER_ULng2Dbl,
        READYTORUN_HELPER_UMod,
        READYTORUN_HELPER_Unbox,
        READYTORUN_HELPER_Unbox_Nullable,
        READYTORUN_HELPER_VirtualFuncPtr,
        READYTORUN_HELPER_WriteBarrier,
        READYTORUN_HELPER_WriteBarrier_EAX,
        READYTORUN_HELPER_WriteBarrier_EBP,
        READYTORUN_HELPER_WriteBarrier_EBX,
        READYTORUN_HELPER_WriteBarrier_ECX,
        READYTORUN_HELPER_WriteBarrier_EDI,
        READYTORUN_HELPER_WriteBarrier_ESI,
    }

    [FlagsAttribute(..)]
    public enum ReadyToRunMethodSigFlags
    {
        READYTORUN_METHOD_SIG_Constrained,
        READYTORUN_METHOD_SIG_InstantiatingStub,
        READYTORUN_METHOD_SIG_MemberRefToken,
        READYTORUN_METHOD_SIG_MethodInstantiation,
        READYTORUN_METHOD_SIG_None,
        READYTORUN_METHOD_SIG_OwnerType,
        READYTORUN_METHOD_SIG_SlotInsteadOfToken,
        READYTORUN_METHOD_SIG_UnboxingStub,
    }

    [FlagsAttribute(..)]
    public enum ReadyToRunTypeLayoutFlags
    {
        READYTORUN_LAYOUT_Alignment,
        READYTORUN_LAYOUT_Alignment_Native,
        READYTORUN_LAYOUT_GCLayout,
        READYTORUN_LAYOUT_GCLayout_Empty,
        READYTORUN_LAYOUT_HFA,
    }

    public enum ReturnKinds
    {
        RT_ByRef,
        RT_ByRef_ByRef,
        RT_ByRef_Obj,
        RT_Illegal,
        RT_Obj_ByRef,
        RT_Obj_Obj,
        RT_Object,
        RT_Scalar,
        RT_Scalar_ByRef,
        RT_Scalar_Obj,
        RT_Unset,
    }

    [FlagsAttribute(..)]
    public enum SourceTypes
    {
        CallInstruction,
        CallSite,
        NativeEndOffsetUnknown,
        SequencePoint,
        SourceTypeInvalid,
        StackEmpty,
    }

    public enum VarLocType
    {
        VLT_COUNT,
        VLT_FIXED_VA,
        VLT_FPSTK,
        VLT_INVALID,
        VLT_REG,
        VLT_REG_BYREF,
        VLT_REG_FP,
        VLT_REG_REG,
        VLT_REG_STK,
        VLT_STK,
        VLT_STK_BYREF,
        VLT_STK_REG,
        VLT_STK2,
    }

} 
namespace ILCompiler.Reflection.ReadyToRun.Amd64
{
    public class GcInfo: BaseGcInfo
    {
        public GcInfo();
        public GcInfo(byte[] image, int offset, Machine machine, ushort majorVersion);
        public int GenericsInstContextStackSlot { get; set; }
        public int GSCookieStackSlot { get; set; }
        public List<InterruptibleRange> InterruptibleRanges { get; set; }
        public uint NumInterruptibleRanges { get; set; }
        public uint NumSafePoints { get; set; }
        public int PSPSymStackSlot { get; set; }
        public ReturnKinds ReturnKind { get; set; }
        public int ReversePInvokeFrameStackSlot { get; set; }
        public List<SafePointOffset> SafePointOffsets { get; set; }
        public int SecurityObjectStackSlot { get; set; }
        public uint SizeOfEditAndContinuePreservedArea { get; set; }
        public uint SizeOfStackOutgoingAndScratchArea { get; set; }
        public GcSlotTable SlotTable { get; set; }
        public uint StackBaseRegister { get; set; }
        public uint ValidRangeEnd { get; set; }
        public uint ValidRangeStart { get; set; }
        public int Version { get; set; }
        public Dictionary<int,List<BaseGcTransition>> GetTransitions(byte[] image, ref int bitOffset);
        public override string ToString();
    }

    public class GcSlotTable
    {
        public GcSlotTable();
        public GcSlotTable(byte[] image, Machine machine, GcInfoTypes gcInfoTypes, ref int bitOffset);
        public List<GcSlot> GcSlots { get; set; }
        public uint NumRegisters { get; set; }
        public uint NumSlots { get; set; }
        public uint NumStackSlots { get; set; }
        public uint NumTracked { get; }
        public uint NumUntracked { get; set; }
        public override string ToString();
    }

    public class GcTransition: BaseGcTransition
    {
        public GcTransition();
        public GcTransition(int codeOffset, int slotId, bool isLive, int chunkId, GcSlotTable slotTable, Machine machine);
        public int ChunkId { get; set; }
        public bool IsLive { get; set; }
        public int SlotId { get; set; }
        public string SlotState { get; set; }
        public string GetSlotState(GcSlotTable slotTable, Machine machine);
        public override string ToString();
    }

    public struct InterruptibleRange
    {
        public InterruptibleRange(uint index, uint start, uint stop);
        public uint Index { get; set; }
        public uint StartOffset { get; set; }
        public uint StopOffset { get; set; }
    }

    public class UnwindCode
    {
        public UnwindCode();
        public UnwindCode(byte[] image, int index, ref int offset);
        public byte CodeOffset { get; set; }
        public uint FrameOffset { get; set; }
        public int Index { get; set; }
        public bool IsOpInfo { get; set; }
        public int NextFrameOffset { get; set; }
        public byte OffsetHigh { get; set; }
        public byte OffsetLow { get; set; }
        public byte OpInfo { get; set; }
        public string OpInfoStr { get; set; }
        public UnwindOpCodes UnwindOp { get; set; }
    }

    public class UnwindInfo: BaseUnwindInfo
    {
        public UnwindInfo();
        public UnwindInfo(byte[] image, int offset);
        public byte CountOfUnwindCodes { get; set; }
        public byte Flags { get; set; }
        public byte FrameOffset { get; set; }
        public Registers FrameRegister { get; set; }
        public uint PersonalityRoutineRVA { get; set; }
        public byte SizeOfProlog { get; set; }
        public UnwindCode[] UnwindCodeArray { get; set; }
        public Dictionary<int,List<UnwindCode>> UnwindCodes { get; set; }
        public byte Version { get; set; }
        public override string ToString();
    }

    public enum Registers
    {
        R10,
        R11,
        R12,
        R13,
        R14,
        R15,
        R8,
        R9,
        RAX,
        RBP,
        RBX,
        RCX,
        RDI,
        RDX,
        RSI,
        RSP,
    }

    public enum UnwindFlags
    {
        UNW_FLAG_CHAININFO,
        UNW_FLAG_EHANDLER,
        UNW_FLAG_NHANDLER,
        UNW_FLAG_UHANDLER,
    }

    public enum UnwindOpCodes
    {
        UWOP_ALLOC_LARGE,
        UWOP_ALLOC_SMALL,
        UWOP_EPILOG,
        UWOP_PUSH_MACHFRAME,
        UWOP_PUSH_NONVOL,
        UWOP_SAVE_NONVOL,
        UWOP_SAVE_NONVOL_FAR,
        UWOP_SAVE_XMM128,
        UWOP_SAVE_XMM128_FAR,
        UWOP_SET_FPREG,
        UWOP_SET_FPREG_LARGE,
        UWOP_SPARE_CODE,
    }

} 
namespace ILCompiler.Reflection.ReadyToRun.Arm
{
    public class Epilog
    {
        public Epilog();
        public Epilog(int index, int dw, uint startOffset);
        public uint Condition { get; set; }
        public uint EpilogStartIndex { get; set; }
        public uint EpilogStartOffset { get; set; }
        public uint EpilogStartOffsetFromMainFunctionBegin { get; set; }
        public int Index { get; set; }
        public uint Res { get; set; }
        public override string ToString();
    }

    public class UnwindCode
    {
        public UnwindCode();
        public UnwindCode(int index);
        public int Index { get; set; }
    }

    public class UnwindInfo: BaseUnwindInfo
    {
        public UnwindInfo();
        public UnwindInfo(byte[] image, int offset);
        public uint CodeWords { get; set; }
        public uint EBit { get; set; }
        public uint EpilogCount { get; set; }
        public Epilog[] Epilogs { get; set; }
        public uint ExtendedCodeWords { get; set; }
        public uint ExtendedEpilogCount { get; set; }
        public uint FBit { get; set; }
        public uint FunctionLength { get; set; }
        public uint Vers { get; set; }
        public uint XBit { get; set; }
        public override string ToString();
    }

    public enum Registers
    {
        F0,
        F1,
        F10,
        F11,
        F12,
        F13,
        F14,
        F15,
        F16,
        F17,
        F18,
        F19,
        F2,
        F20,
        F21,
        F22,
        F23,
        F24,
        F25,
        F26,
        F27,
        F28,
        F29,
        F3,
        F30,
        F31,
        F4,
        F5,
        F6,
        F7,
        F8,
        F9,
        R0,
        R1,
        R10,
        R11,
        R12,
        R13,
        R14,
        R15,
        R2,
        R3,
        R4,
        R5,
        R6,
        R7,
        R8,
        R9,
    }

} 
namespace R2RDump.Arm64
{
    public class Epilog
    {
        public Epilog();
        public Epilog(int index, int dw, uint startOffset);
        public uint Condition { get; set; }
        public uint EpilogStartIndex { get; set; }
        public uint EpilogStartOffset { get; set; }
        public uint EpilogStartOffsetFromMainFunctionBegin { get; set; }
        public int Index { get; set; }
        public uint Res { get; set; }
        public override string ToString();
    }

    public class UnwindCode
    {
        public UnwindCode();
        public UnwindCode(int index);
        public int Index { get; set; }
    }

    public class UnwindInfo: BaseUnwindInfo
    {
        public UnwindInfo();
        public UnwindInfo(byte[] image, int offset);
        public uint CodeWords { get; set; }
        public uint EBit { get; set; }
        public uint EpilogCount { get; set; }
        public Epilog[] Epilogs { get; set; }
        public uint ExtendedCodeWords { get; set; }
        public uint ExtendedEpilogCount { get; set; }
        public uint FunctionLength { get; set; }
        public uint Vers { get; set; }
        public uint XBit { get; set; }
        public override string ToString();
    }

    public enum Registers
    {
        X0,
        X1,
        X10,
        X11,
        X12,
        X13,
        X14,
        X15,
        X16,
        X17,
        X18,
        X19,
        X2,
        X20,
        X21,
        X22,
        X23,
        X24,
        X25,
        X26,
        X27,
        X28,
        X29,
        X3,
        X30,
        X4,
        X5,
        X6,
        X7,
        X8,
        X9,
    }

} 
namespace ILCompiler.Reflection.ReadyToRun.x86
{
    public class CalleeSavedRegister: BaseGcTransition
    {
        public CalleeSavedRegister();
        public CalleeSavedRegister(int codeOffset, CalleeSavedRegisters reg);
        public CalleeSavedRegisters Register { get; set; }
        public override string ToString();
    }

    public class GcInfo: BaseGcInfo
    {
        public GcInfo();
        public GcInfo(byte[] image, int offset, Machine machine, ushort majorVersion);
        public InfoHdrSmall Header { get; set; }
        public GcSlotTable SlotTable { get; set; }
        public override string ToString();
    }

    public class GcSlotTable
    {
        public GcSlotTable();
        public GcSlotTable(byte[] image, InfoHdrSmall header, ref int offset);
        public List<GcSlot> GcSlots { get; set; }
        public override string ToString();
    }

    public class GcTransitionCall: BaseGcTransition
    {
        public GcTransitionCall();
        public GcTransitionCall(int codeOffset);
        public GcTransitionCall(int codeOffset, bool isEbpFrame, uint regMask, uint byRefRegMask);
        public uint ArgMask { get; set; }
        public List<CallRegister> CallRegisters { get; set; }
        public uint IArgs { get; set; }
        public List<PtrArg> PtrArgs { get; set; }
        public override string ToString();
    }

    public class GcTransitionPointer: BaseGcTransition
    {
        public GcTransitionPointer();
        public GcTransitionPointer(int codeOffset, uint argOffs, uint argCnt, Action act, bool isEbpFrame, bool isThis, bool iptr, bool isPtr);
        public Action Act { get; set; }
        public uint ArgCount { get; set; }
        public uint ArgOffset { get; set; }
        public bool Iptr { get; set; }
        public bool IsPtr { get; set; }
        public bool IsThis { get; set; }
        public override string ToString();
    }

    public class GcTransitionRegister: BaseGcTransition
    {
        public GcTransitionRegister();
        public GcTransitionRegister(int codeOffset, Registers reg, Action isLive, bool isThis, bool iptr, int pushCountOrPopSize);
        public bool Iptr { get; set; }
        public Action IsLive { get; set; }
        public bool IsThis { get; set; }
        public int PushCountOrPopSize { get; set; }
        public Registers Register { get; set; }
        public override string ToString();
    }

    public class InfoHdrDecoder
    {
        public InfoHdrDecoder();
        public static InfoHdrSmall DecodeHeader(byte[] image, ref int offset, int codeLength);
        public static InfoHdrSmall GetInfoHdr(byte encoding);
    }

    public struct InfoHdrSmall
    {
        public InfoHdrSmall(uint prologSize, uint epilogSize, byte epilogCount, byte epilogAtEnd, byte ediSaved, byte esiSaved, byte ebxSaved, byte ebpSaved, byte ebpFrame, byte interruptible, byte doubleAlign, byte security, byte handlers, byte localloc, byte editNcontinue, byte varargs, byte profCallbacks, byte genericsContext, byte genericsContextIsMethodDesc, byte returnKind, ushort argCount, uint frameSize, uint untrackedCnt, uint varPtrTableSize);
        public ushort ArgCount { get; set; }
        public uint ArgTabOffset { get; set; }
        public bool DoubleAlign { get; set; }
        public bool EbpFrame { get; set; }
        public bool EbpSaved { get; set; }
        public bool EbxSaved { get; set; }
        public bool EdiSaved { get; set; }
        public bool EditNcontinue { get; set; }
        public bool EpilogAtEnd { get; set; }
        public byte EpilogCount { get; set; }
        public List<int> Epilogs { get; set; }
        public uint EpilogSize { get; set; }
        public bool EsiSaved { get; set; }
        public uint FrameSize { get; set; }
        public byte GenericsContext { get; set; }
        public byte GenericsContextIsMethodDesc { get; set; }
        public uint GsCookieOffset { get; set; }
        public bool Handlers { get; set; }
        public bool HasArgTabOffset { get; set; }
        public bool Interruptible { get; set; }
        public bool Localloc { get; set; }
        public bool ProfCallbacks { get; set; }
        public uint PrologSize { get; set; }
        public ReturnKinds ReturnKind { get; set; }
        public uint RevPInvokeOffset { get; set; }
        public bool Security { get; set; }
        public uint SyncEndOffset { get; set; }
        public uint SyncStartOffset { get; set; }
        public uint UntrackedCnt { get; set; }
        public bool Varargs { get; set; }
        public uint VarPtrTableSize { get; set; }
        public override string ToString();
    }

    public class IPtrMask: BaseGcTransition
    {
        public IPtrMask();
        public IPtrMask(int codeOffset, uint imask);
        public uint IMask { get; set; }
        public override string ToString();
    }

    public class UnwindInfo: BaseUnwindInfo
    {
        public UnwindInfo();
        public UnwindInfo(byte[] image, int offset);
        public uint FunctionLength { get; set; }
        public override string ToString();
    }

    public enum Action
    {
        DEAD,
        KILL,
        LIVE,
        POP,
        PUSH,
    }

    public enum CalleeSavedRegisters
    {
        EBP,
        EBX,
        EDI,
        ESI,
    }

    public enum Registers
    {
        EAX,
        EBP,
        EBX,
        ECX,
        EDI,
        EDX,
        ESI,
        ESP,
    }
} 

@dotnet/crossgen-contrib

Earlier versions of the PR on the CoreCLR repo can be found here

@cshung cshung added the area-R2RDump-coreclr Ready-to-run image dump tool label Nov 26, 2019
@cshung cshung force-pushed the dev/andrewau/r2rdump-refactoring branch from 9badcc8 to ef0b1b8 Compare December 12, 2019 23:49
@cshung cshung changed the title [WIP] R2RDump changes to allow separation of presentation from parsing R2RDump changes to allow separation of presentation from parsing Dec 13, 2019
@cshung cshung requested a review from fadimounir December 13, 2019 03:22
@cshung cshung force-pushed the dev/andrewau/r2rdump-refactoring branch from ef0b1b8 to be9d80f Compare December 15, 2019 08:45
@cshung cshung mentioned this pull request Dec 16, 2019
2 tasks
@cshung cshung requested a review from davidwrighton December 16, 2019 22:16
Copy link
Member

@davidwrighton davidwrighton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but please file a bug about generation of warnings. There needs to be some way to see those, and to add them to parsers so that we can identify stuff that's not quite right.

@cshung cshung merged commit 1e38424 into dotnet:master Dec 16, 2019
@cshung cshung deleted the dev/andrewau/r2rdump-refactoring branch December 16, 2019 23:13
MichalStrehovsky pushed a commit to MichalStrehovsky/runtime that referenced this pull request Nov 4, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-R2RDump-coreclr Ready-to-run image dump tool
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants