diff options
author | Amy Yu <amycmyu@gmail.com> | 2018-06-06 16:57:33 -0700 |
---|---|---|
committer | Amy Yu <amycmyu@gmail.com> | 2018-06-06 16:57:33 -0700 |
commit | df13a8e76ab279271607b38ed317ae290cc419bb (patch) | |
tree | e6a399b5b728631c01cd72fc92241ed991005803 /src | |
parent | c366fb2ada7a040c0e249277b18dae5481dfe940 (diff) | |
download | coreclr-df13a8e76ab279271607b38ed317ae290cc419bb.tar.gz coreclr-df13a8e76ab279271607b38ed317ae290cc419bb.tar.bz2 coreclr-df13a8e76ab279271607b38ed317ae290cc419bb.zip |
Refactoring gcInfo, added verbose option to cli
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/r2rdump/GCInfo.cs | 193 | ||||
-rw-r--r-- | src/tools/r2rdump/GCInfoTypes.cs | 192 | ||||
-rw-r--r-- | src/tools/r2rdump/GCSlotTable.cs | 64 | ||||
-rw-r--r-- | src/tools/r2rdump/R2RDump.cs | 15 | ||||
-rw-r--r-- | src/tools/r2rdump/UnwindInfo.cs | 2 |
5 files changed, 234 insertions, 232 deletions
diff --git a/src/tools/r2rdump/GCInfo.cs b/src/tools/r2rdump/GCInfo.cs index 8464e0851c..358444f98c 100644 --- a/src/tools/r2rdump/GCInfo.cs +++ b/src/tools/r2rdump/GCInfo.cs @@ -11,7 +11,7 @@ namespace R2RDump { class GcInfo { - public enum GcInfoHeaderFlags + private enum GcInfoHeaderFlags { GC_INFO_IS_VARARG = 0x1, GC_INFO_HAS_SECURITY_OBJECT = 0x2, @@ -31,24 +31,6 @@ namespace R2RDump GC_INFO_FLAGS_BIT_SIZE = 10, }; - public enum ReturnKinds - { - RT_Scalar = 0, - RT_Object = 1, - RT_ByRef = 2, - RT_Unset = 3, // Encoding 3 means RT_Float on X86 - RT_Scalar_Obj = RT_Object << 2 | RT_Scalar, - RT_Scalar_ByRef = RT_ByRef << 2 | RT_Scalar, - - RT_Obj_Obj = RT_Object << 2 | RT_Object, - RT_Obj_ByRef = RT_ByRef << 2 | RT_Object, - - RT_ByRef_Obj = RT_Object << 2 | RT_ByRef, - RT_ByRef_ByRef = RT_ByRef << 2 | RT_ByRef, - - RT_Illegal = 0xFF - }; - public struct InterruptibleRange { public uint StartOffset { get; } @@ -64,6 +46,15 @@ namespace R2RDump private const int MIN_GCINFO_VERSION_WITH_RETURN_KIND = 2; private const int MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME = 2; + private bool _slimHeader; + private bool _hasSecurityObject; + private bool _hasGSCookie; + private bool _hasPSPSym; + private bool _hasGenericsInstContext; + private bool _hasStackBaseRegister; + private bool _hasSizeOfEditAndContinuePreservedArea; + private bool _hasReversePInvokeFrame; + public int Version { get; } public int CodeLength { get; } public ReturnKinds ReturnKind { get; } @@ -97,122 +88,86 @@ namespace R2RDump SizeOfEditAndContinuePreservedArea = 0xffffffff; ReversePInvokeFrameStackSlot = -1; - GcInfoHeaderFlags headerFlags; Version = ReadyToRunVersionToGcInfoVersion(majorVersion); int bitOffset = offset * 8; int startBitOffset = bitOffset; - bool slimHeader = (NativeReader.ReadBits(image, 1, ref bitOffset) == 0); - - if (slimHeader) - { - headerFlags = NativeReader.ReadBits(image, 1,ref bitOffset) == 1 ? GcInfoHeaderFlags.GC_INFO_HAS_STACK_BASE_REGISTER : 0; - } - else - { - int numFlagBits = (int)((Version == 1) ? GcInfoHeaderFlags.GC_INFO_FLAGS_BIT_SIZE_VERSION_1 : GcInfoHeaderFlags.GC_INFO_FLAGS_BIT_SIZE); - headerFlags = (GcInfoHeaderFlags)NativeReader.ReadBits(image, numFlagBits, ref bitOffset); - } - - bool hasReversePInvokeFrame = false; - if (Version >= MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME) // IsReversePInvokeFrameAvailable - { - hasReversePInvokeFrame = (headerFlags & GcInfoHeaderFlags.GC_INFO_REVERSE_PINVOKE_FRAME) != 0; - } + + ParseHeaderFlags(image, ref bitOffset); if (Version >= MIN_GCINFO_VERSION_WITH_RETURN_KIND) // IsReturnKindAvailable { - int returnKindBits = (slimHeader) ? gcInfoTypes.SIZE_OF_RETURN_KIND_SLIM : gcInfoTypes.SIZE_OF_RETURN_KIND_FAT; + int returnKindBits = (_slimHeader) ? gcInfoTypes.SIZE_OF_RETURN_KIND_SLIM : gcInfoTypes.SIZE_OF_RETURN_KIND_FAT; ReturnKind = (ReturnKinds)NativeReader.ReadBits(image, returnKindBits, ref bitOffset); } - CodeLength = DenormalizeCodeLength(machine, (int)NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.CODE_LENGTH_ENCBASE, ref bitOffset)); + CodeLength = gcInfoTypes.DenormalizeCodeLength((int)NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.CODE_LENGTH_ENCBASE, ref bitOffset)); - if ((headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_GS_COOKIE) != 0) + if (_hasGSCookie) { - // Decode prolog/epilog information uint normPrologSize = NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.NORM_PROLOG_SIZE_ENCBASE, ref bitOffset) + 1; uint normEpilogSize = NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.NORM_PROLOG_SIZE_ENCBASE, ref bitOffset); ValidRangeStart = normPrologSize; ValidRangeEnd = (uint)CodeLength - normEpilogSize; } - else if ((headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_SECURITY_OBJECT) != 0 || (headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) != GcInfoHeaderFlags.GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE) + else if (_hasSecurityObject || _hasGenericsInstContext) { - // Decode prolog information ValidRangeStart = NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.NORM_PROLOG_SIZE_ENCBASE, ref bitOffset) + 1; - // satisfy asserts that assume m_GSCookieValidRangeStart != 0 ==> m_GSCookieValidRangeStart < m_GSCookieValidRangeEnd ValidRangeEnd = ValidRangeStart + 1; } - // Decode the offset to the security object. - if ((headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_SECURITY_OBJECT) != 0) + if (_hasSecurityObject) { - SecurityObjectStackSlot = DenormalizeStackSlot(machine, NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.SECURITY_OBJECT_STACK_SLOT_ENCBASE, ref bitOffset)); + SecurityObjectStackSlot = gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.SECURITY_OBJECT_STACK_SLOT_ENCBASE, ref bitOffset)); } - if ((headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_GS_COOKIE) != 0) + if (_hasGSCookie) { - GSCookieStackSlot = DenormalizeStackSlot(machine, NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.GS_COOKIE_STACK_SLOT_ENCBASE, ref bitOffset)); + GSCookieStackSlot = gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.GS_COOKIE_STACK_SLOT_ENCBASE, ref bitOffset)); } - if ((headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_PSP_SYM) != 0) + if (_hasPSPSym) { - PSPSymStackSlot = DenormalizeStackSlot(machine, NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.PSP_SYM_STACK_SLOT_ENCBASE, ref bitOffset)); + PSPSymStackSlot = gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.PSP_SYM_STACK_SLOT_ENCBASE, ref bitOffset)); } - if ((headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) != GcInfoHeaderFlags.GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE) + if (_hasGenericsInstContext) { - GenericsInstContextStackSlot = DenormalizeStackSlot(machine, NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE, ref bitOffset)); + GenericsInstContextStackSlot = gcInfoTypes.DenormalizeStackSlot(NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE, ref bitOffset)); } - if ((headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_STACK_BASE_REGISTER) != 0) + if (_hasStackBaseRegister && !_slimHeader) { - if (slimHeader) - { - StackBaseRegister = DenormalizeStackBaseRegister(machine, 0); - } - else - { - StackBaseRegister = DenormalizeStackBaseRegister(machine, NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.STACK_BASE_REGISTER_ENCBASE, ref bitOffset)); - } + StackBaseRegister = gcInfoTypes.DenormalizeStackBaseRegister(NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.STACK_BASE_REGISTER_ENCBASE, ref bitOffset)); } - if ((headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_EDIT_AND_CONTINUE_PRESERVED_SLOTS) != 0) + if (_hasSizeOfEditAndContinuePreservedArea) { SizeOfEditAndContinuePreservedArea = NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE, ref bitOffset); } - if (hasReversePInvokeFrame) + if (_hasReversePInvokeFrame) { ReversePInvokeFrameStackSlot = NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.REVERSE_PINVOKE_FRAME_ENCBASE, ref bitOffset); } - // FIXED_STACK_PARAMETER_SCRATCH_AREA - if (slimHeader) - { - SizeOfStackOutgoingAndScratchArea = 0; - } - else + // FIXED_STACK_PARAMETER_SCRATCH_AREA (this macro is always defined in gcinfotypes.h) + if (!_slimHeader) { - SizeOfStackOutgoingAndScratchArea = DenormalizeSizeOfStackArea(machine, NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.SIZE_OF_STACK_AREA_ENCBASE, ref bitOffset)); + SizeOfStackOutgoingAndScratchArea = gcInfoTypes.DenormalizeSizeOfStackArea(NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.SIZE_OF_STACK_AREA_ENCBASE, ref bitOffset)); } - // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED (this macro is always defined in gcinfotypes.h) NumSafePoints = NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.NUM_SAFE_POINTS_ENCBASE, ref bitOffset); - if (slimHeader) - { - NumInterruptibleRanges = 0; - } - else + if (!_slimHeader) { NumInterruptibleRanges = NativeReader.DecodeVarLengthUnsigned(image, gcInfoTypes.NUM_INTERRUPTIBLE_RANGES_ENCBASE, ref bitOffset); } - // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED (this macro is always defined in gcinfotypes.h) SafePointOffsets = EnumerateSafePoints(image, ref bitOffset); - - uint numBitsPerOffset = CeilOfLog2(CodeLength); + uint numBitsPerOffset = GcInfoTypes.CeilOfLog2(CodeLength); bitOffset += (int)(NumSafePoints * numBitsPerOffset); InterruptibleRanges = EnumerateInterruptibleRanges(image, gcInfoTypes.INTERRUPTIBLE_RANGE_DELTA1_ENCBASE, gcInfoTypes.INTERRUPTIBLE_RANGE_DELTA2_ENCBASE, ref bitOffset); @@ -261,81 +216,41 @@ namespace R2RDump } sb.AppendLine($"{tab}SlotTable:"); sb.Append(SlotTable.ToString()); + sb.AppendLine($"{tab}Size: {Size} bytes"); return sb.ToString(); } - private int DenormalizeCodeLength(Machine target, int x) - { - switch (target) - { - case Machine.Arm: - return (x << 1); - case Machine.Arm64: - return (x << 2); - } - return x; - } - - private int DenormalizeStackSlot(Machine target, int x) + private void ParseHeaderFlags(byte[] image, ref int bitOffset) { - switch (target) - { - case Machine.Amd64: - return (x << 3); - case Machine.Arm: - return (x << 2); - case Machine.Arm64: - return (x << 3); - } - return x; - } - - private uint DenormalizeStackBaseRegister(Machine target, uint x) - { - switch (target) + GcInfoHeaderFlags headerFlags; + _slimHeader = (NativeReader.ReadBits(image, 1, ref bitOffset) == 0); + if (_slimHeader) { - case Machine.Amd64: - return (x ^ 5); - case Machine.Arm: - return ((x ^ 7) + 4); - case Machine.Arm64: - return (x ^ 29); + headerFlags = NativeReader.ReadBits(image, 1, ref bitOffset) == 1 ? GcInfoHeaderFlags.GC_INFO_HAS_STACK_BASE_REGISTER : 0; } - return x; - } - - private uint DenormalizeSizeOfStackArea(Machine target, uint x) - { - switch (target) + else { - case Machine.Amd64: - return (x << 3); - case Machine.Arm: - return (x << 2); - case Machine.Arm64: - return (x << 3); + int numFlagBits = (int)((Version == 1) ? GcInfoHeaderFlags.GC_INFO_FLAGS_BIT_SIZE_VERSION_1 : GcInfoHeaderFlags.GC_INFO_FLAGS_BIT_SIZE); + headerFlags = (GcInfoHeaderFlags)NativeReader.ReadBits(image, numFlagBits, ref bitOffset); } - return x; - } - private uint CeilOfLog2(int x) - { - if (x == 0) - return 0; - uint result = (uint)((x & (x - 1)) != 0 ? 1 : 0); - while (x != 1) + _hasSecurityObject = (headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_SECURITY_OBJECT) != 0; + _hasGSCookie = (headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_GS_COOKIE) != 0; + _hasPSPSym = (headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_PSP_SYM) != 0; + _hasGenericsInstContext = (headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) != GcInfoHeaderFlags.GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE; + _hasStackBaseRegister = (headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_STACK_BASE_REGISTER) != 0; + _hasSizeOfEditAndContinuePreservedArea = (headerFlags & GcInfoHeaderFlags.GC_INFO_HAS_EDIT_AND_CONTINUE_PRESERVED_SLOTS) != 0; + if (Version >= MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME) // IsReversePInvokeFrameAvailable { - result++; - x >>= 1; + _hasReversePInvokeFrame = (headerFlags & GcInfoHeaderFlags.GC_INFO_REVERSE_PINVOKE_FRAME) != 0; } - return result; } private IEnumerable<uint> EnumerateSafePoints(byte[] image, ref int bitOffset) { List<uint> safePoints = new List<uint>(); - uint numBitsPerOffset = CeilOfLog2(CodeLength); + uint numBitsPerOffset = GcInfoTypes.CeilOfLog2(CodeLength); for (int i = 0; i < NumSafePoints; i++) { uint normOffset = (uint)NativeReader.ReadBits(image, (int)numBitsPerOffset, ref bitOffset); @@ -367,7 +282,7 @@ namespace R2RDump /// GcInfo version is 1 up to ReadyTorun version 1.x. /// GcInfo version is current from ReadyToRun version 2.0 /// </summary> - static int ReadyToRunVersionToGcInfoVersion(int readyToRunMajorVersion) + private int ReadyToRunVersionToGcInfoVersion(int readyToRunMajorVersion) { return (readyToRunMajorVersion == 1) ? 1 : GCINFO_VERSION; } diff --git a/src/tools/r2rdump/GCInfoTypes.cs b/src/tools/r2rdump/GCInfoTypes.cs index 46354f8a35..5fe5848a61 100644 --- a/src/tools/r2rdump/GCInfoTypes.cs +++ b/src/tools/r2rdump/GCInfoTypes.cs @@ -2,40 +2,46 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Reflection.PortableExecutable; +using System.Text; namespace R2RDump { class GcInfoTypes { - public int SIZE_OF_RETURN_KIND_SLIM { get; } = 2; - public int SIZE_OF_RETURN_KIND_FAT { get; } = 2; - public int CODE_LENGTH_ENCBASE { get; } = 8; - public int NORM_PROLOG_SIZE_ENCBASE { get; } = 5; - public int SECURITY_OBJECT_STACK_SLOT_ENCBASE { get; } = 6; - public int GS_COOKIE_STACK_SLOT_ENCBASE { get; } = 6; - public int PSP_SYM_STACK_SLOT_ENCBASE { get; } = 6; - public int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE { get; } = 6; - public int STACK_BASE_REGISTER_ENCBASE { get; } = 3; - public int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE { get; } = 4; - public int REVERSE_PINVOKE_FRAME_ENCBASE { get; } = 6; - public int SIZE_OF_STACK_AREA_ENCBASE { get; } = 3; - public int NUM_SAFE_POINTS_ENCBASE { get; } = 3; - public int NUM_INTERRUPTIBLE_RANGES_ENCBASE { get; } = 1; - public int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE { get; } = 6; - public int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE { get; } = 6; - - public int MAX_PREDECODED_SLOTS { get; } = 64; - public int NUM_REGISTERS_ENCBASE { get; } = 2; - public int NUM_STACK_SLOTS_ENCBASE { get; } = 2; - public int NUM_UNTRACKED_SLOTS_ENCBASE { get; } = 1; - public int REGISTER_ENCBASE { get; } = 3; - public int REGISTER_DELTA_ENCBASE { get; } = 2; - public int STACK_SLOT_ENCBASE { get; } = 6; - public int STACK_SLOT_DELTA_ENCBASE { get; } = 4; - - public GcInfoTypes(Machine machine) + private Machine _target; + + internal int SIZE_OF_RETURN_KIND_SLIM { get; } = 2; + internal int SIZE_OF_RETURN_KIND_FAT { get; } = 2; + internal int CODE_LENGTH_ENCBASE { get; } = 8; + internal int NORM_PROLOG_SIZE_ENCBASE { get; } = 5; + internal int SECURITY_OBJECT_STACK_SLOT_ENCBASE { get; } = 6; + internal int GS_COOKIE_STACK_SLOT_ENCBASE { get; } = 6; + internal int PSP_SYM_STACK_SLOT_ENCBASE { get; } = 6; + internal int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE { get; } = 6; + internal int STACK_BASE_REGISTER_ENCBASE { get; } = 3; + internal int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE { get; } = 4; + internal int REVERSE_PINVOKE_FRAME_ENCBASE { get; } = 6; + internal int SIZE_OF_STACK_AREA_ENCBASE { get; } = 3; + internal int NUM_SAFE_POINTS_ENCBASE { get; } = 3; + internal int NUM_INTERRUPTIBLE_RANGES_ENCBASE { get; } = 1; + internal int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE { get; } = 6; + internal int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE { get; } = 6; + + internal int MAX_PREDECODED_SLOTS { get; } = 64; + internal int NUM_REGISTERS_ENCBASE { get; } = 2; + internal int NUM_STACK_SLOTS_ENCBASE { get; } = 2; + internal int NUM_UNTRACKED_SLOTS_ENCBASE { get; } = 1; + internal int REGISTER_ENCBASE { get; } = 3; + internal int REGISTER_DELTA_ENCBASE { get; } = 2; + internal int STACK_SLOT_ENCBASE { get; } = 6; + internal int STACK_SLOT_DELTA_ENCBASE { get; } = 4; + + internal GcInfoTypes(Machine machine) { + _target = machine; + switch (machine) { case Machine.Amd64: @@ -78,6 +84,134 @@ namespace R2RDump break; } } - -} + + internal int DenormalizeCodeLength(int x) + { + switch (_target) + { + case Machine.Arm: + return (x << 1); + case Machine.Arm64: + return (x << 2); + } + return x; + } + + internal int DenormalizeStackSlot(int x) + { + switch (_target) + { + case Machine.Amd64: + return (x << 3); + case Machine.Arm: + return (x << 2); + case Machine.Arm64: + return (x << 3); + } + return x; + } + + internal uint DenormalizeStackBaseRegister(uint x) + { + switch (_target) + { + case Machine.Amd64: + return (x ^ 5); + case Machine.Arm: + return ((x ^ 7) + 4); + case Machine.Arm64: + return (x ^ 29); + } + return x; + } + + internal uint DenormalizeSizeOfStackArea(uint x) + { + switch (_target) + { + case Machine.Amd64: + return (x << 3); + case Machine.Arm: + return (x << 2); + case Machine.Arm64: + return (x << 3); + } + return x; + } + + internal static uint CeilOfLog2(int x) + { + if (x == 0) + return 0; + uint result = (uint)((x & (x - 1)) != 0 ? 1 : 0); + while (x != 1) + { + result++; + x >>= 1; + } + return result; + } + } + + public enum ReturnKinds + { + RT_Scalar = 0, + RT_Object = 1, + RT_ByRef = 2, + RT_Unset = 3, // Encoding 3 means RT_Float on X86 + RT_Scalar_Obj = RT_Object << 2 | RT_Scalar, + RT_Scalar_ByRef = RT_ByRef << 2 | RT_Scalar, + + RT_Obj_Obj = RT_Object << 2 | RT_Object, + RT_Obj_ByRef = RT_ByRef << 2 | RT_Object, + + RT_ByRef_Obj = RT_Object << 2 | RT_ByRef, + RT_ByRef_ByRef = RT_ByRef << 2 | RT_ByRef, + + RT_Illegal = 0xFF + }; + + public enum GcSlotFlags + { + GC_SLOT_BASE = 0x0, + GC_SLOT_INTERIOR = 0x1, + GC_SLOT_PINNED = 0x2, + GC_SLOT_UNTRACKED = 0x4, + + // For internal use by the encoder/decoder + GC_SLOT_IS_REGISTER = 0x8, + GC_SLOT_IS_DELETED = 0x10, + }; + + public enum GcStackSlotBase + { + GC_CALLER_SP_REL = 0x0, + GC_SP_REL = 0x1, + GC_FRAMEREG_REL = 0x2, + + GC_SPBASE_FIRST = GC_CALLER_SP_REL, + GC_SPBASE_LAST = GC_FRAMEREG_REL, + }; + + public class GcStackSlot + { + public int SpOffset { get; } + public GcStackSlotBase Base { get; } + public GcStackSlot(int spOffset, GcStackSlotBase stackSlotBase) + { + SpOffset = spOffset; + Base = stackSlotBase; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + string tab4 = new string(' ', 16); + + sb.AppendLine($"{tab4}SpOffset: {SpOffset}"); + sb.Append($"{tab4}Base: {Enum.GetName(typeof(GcStackSlotBase), Base)}"); + + return sb.ToString(); + } + }; } diff --git a/src/tools/r2rdump/GCSlotTable.cs b/src/tools/r2rdump/GCSlotTable.cs index 4eae435780..5828b95418 100644 --- a/src/tools/r2rdump/GCSlotTable.cs +++ b/src/tools/r2rdump/GCSlotTable.cs @@ -44,50 +44,6 @@ namespace R2RDump } } - public enum GcSlotFlags - { - GC_SLOT_BASE = 0x0, - GC_SLOT_INTERIOR = 0x1, - GC_SLOT_PINNED = 0x2, - GC_SLOT_UNTRACKED = 0x4, - - // For internal use by the encoder/decoder - GC_SLOT_IS_REGISTER = 0x8, - GC_SLOT_IS_DELETED = 0x10, - }; - - public enum GcStackSlotBase - { - GC_CALLER_SP_REL = 0x0, - GC_SP_REL = 0x1, - GC_FRAMEREG_REL = 0x2, - - GC_SPBASE_FIRST = GC_CALLER_SP_REL, - GC_SPBASE_LAST = GC_FRAMEREG_REL, - }; - - public class GcStackSlot - { - public int SpOffset { get; } - public GcStackSlotBase Base { get; } - public GcStackSlot(int spOffset, GcStackSlotBase stackSlotBase) - { - SpOffset = spOffset; - Base = stackSlotBase; - } - - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - string tab4 = new string(' ', 16); - - sb.AppendLine($"{tab4}SpOffset: {SpOffset}"); - sb.Append($"{tab4}Base: {Enum.GetName(typeof(GcStackSlotBase), Base)}"); - - return sb.ToString(); - } - }; - public uint NumRegisters { get; } public uint NumStackSlots { get; } public uint NumUntracked { get; } @@ -140,20 +96,6 @@ namespace R2RDump return sb.ToString(); } - private int DenormalizeStackSlot(Machine target, int x) - { - switch (target) - { - case Machine.Amd64: - return (x << 3); - case Machine.Arm: - return (x << 2); - case Machine.Arm64: - return (x << 3); - } - return x; - } - private void DecodeRegisters(byte[] image, GcInfoTypes gcInfoTypes, ref int bitOffset) { // We certainly predecode the first register @@ -182,7 +124,7 @@ namespace R2RDump // We have stack slots left and more room to predecode GcStackSlotBase spBase = (GcStackSlotBase)NativeReader.ReadBits(image, 2, ref bitOffset); int normSpOffset = NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.STACK_SLOT_ENCBASE, ref bitOffset); - int spOffset = DenormalizeStackSlot(machine, normSpOffset); + int spOffset = gcInfoTypes.DenormalizeStackSlot(normSpOffset); GcSlotFlags flags = (GcSlotFlags)NativeReader.ReadBits(image, 2, ref bitOffset); GcSlots.Add(new GcSlot(-1, new GcStackSlot(spOffset, spBase), flags)); @@ -192,14 +134,14 @@ namespace R2RDump if ((uint)flags != 0) { normSpOffset = NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.STACK_SLOT_ENCBASE, ref bitOffset); - spOffset = DenormalizeStackSlot(machine, normSpOffset); + spOffset = gcInfoTypes.DenormalizeStackSlot(normSpOffset); flags = (GcSlotFlags)NativeReader.ReadBits(image, 2, ref bitOffset); } else { int normSpOffsetDelta = NativeReader.DecodeVarLengthSigned(image, gcInfoTypes.STACK_SLOT_DELTA_ENCBASE, ref bitOffset); normSpOffset += normSpOffsetDelta; - spOffset = DenormalizeStackSlot(machine, normSpOffset); + spOffset = gcInfoTypes.DenormalizeStackSlot(normSpOffset); } GcSlots.Add(new GcSlot(-1, new GcStackSlot(spOffset, spBase), flags)); } diff --git a/src/tools/r2rdump/R2RDump.cs b/src/tools/r2rdump/R2RDump.cs index cc43fbf204..6f099eaaa6 100644 --- a/src/tools/r2rdump/R2RDump.cs +++ b/src/tools/r2rdump/R2RDump.cs @@ -34,6 +34,7 @@ namespace R2RDump private ArgumentSyntax ParseCommandLine(string[] args) { + bool verbose = false; ArgumentSyntax argSyntax = ArgumentSyntax.Parse(args, syntax => { syntax.ApplicationName = "R2RDump"; @@ -43,7 +44,7 @@ namespace R2RDump syntax.DefineOption("h|help", ref _help, "Help message for R2RDump"); syntax.DefineOptionList("i|in", ref _inputFilenames, "Input file(s) to dump. Expects them to by ReadyToRun images"); syntax.DefineOption("o|out", ref _outputFilename, "Output file path. Dumps everything to the specified file except help message and exception messages"); - syntax.DefineOption("v|verbose|raw", ref _raw, "Dump the raw bytes of each section or runtime function"); + syntax.DefineOption("raw", ref _raw, "Dump the raw bytes of each section or runtime function"); syntax.DefineOption("header", ref _header, "Dump R2R header"); syntax.DefineOption("d|disasm", ref _disasm, "Show disassembly of methods or runtime functions"); syntax.DefineOptionList("q|query", ref _queries, "Query method by exact name, signature, row id or token"); @@ -53,9 +54,18 @@ namespace R2RDump syntax.DefineOption("types", ref _types, "Dump available types"); syntax.DefineOption("unwind", ref _unwind, "Dump unwindInfo"); syntax.DefineOption("gc", ref _gc, "Dump gcInfo and slot table"); - syntax.DefineOption("diff", ref _diff, "Compare two R2R images (not yet implemented)"); // not yet implemented + syntax.DefineOption("v|verbose", ref verbose, "Dump raw bytes, disassembly, unwindInfo and gcInfo"); + syntax.DefineOption("diff", ref _diff, "Compare two R2R images (not yet implemented)"); }); + if (verbose) + { + _raw = true; + _disasm = true; + _unwind = true; + _gc = true; + } + return argSyntax; } @@ -169,6 +179,7 @@ namespace R2RDump } if (_raw) { + _writer.WriteLine("Raw Bytes:"); DumpBytes(r2r, rtf.StartAddress, (uint)rtf.Size); } if (_unwind) diff --git a/src/tools/r2rdump/UnwindInfo.cs b/src/tools/r2rdump/UnwindInfo.cs index dd95756228..9742aa0944 100644 --- a/src/tools/r2rdump/UnwindInfo.cs +++ b/src/tools/r2rdump/UnwindInfo.cs @@ -111,7 +111,7 @@ namespace R2RDump sb.Append(UnwindCode[i].ToString()); } sb.AppendLine($"{tab}PersonalityRoutineRVA: 0x{PersonalityRoutineRVA:X8}"); - sb.AppendLine($"{tab}Size: {Size}"); + sb.AppendLine($"{tab}Size: {Size} bytes"); return sb.ToString(); } |