summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAmy Yu <amycmyu@gmail.com>2018-06-06 16:57:33 -0700
committerAmy Yu <amycmyu@gmail.com>2018-06-06 16:57:33 -0700
commitdf13a8e76ab279271607b38ed317ae290cc419bb (patch)
treee6a399b5b728631c01cd72fc92241ed991005803 /src
parentc366fb2ada7a040c0e249277b18dae5481dfe940 (diff)
downloadcoreclr-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.cs193
-rw-r--r--src/tools/r2rdump/GCInfoTypes.cs192
-rw-r--r--src/tools/r2rdump/GCSlotTable.cs64
-rw-r--r--src/tools/r2rdump/R2RDump.cs15
-rw-r--r--src/tools/r2rdump/UnwindInfo.cs2
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();
}