summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
authorAmy <amycmyu@gmail.com>2018-06-26 15:01:14 -0700
committerGitHub <noreply@github.com>2018-06-26 15:01:14 -0700
commit022f14f8575a8c371e0fc4a83ab7aef01ab79d7b (patch)
tree9726c3b7ea253bb4dd6a74915fa02cc1e80b1f84 /src/tools
parent4e237f058b12403f7ee69d62fd24053081d5fe13 (diff)
parent435166408afb004a94ead8f236eb71c282bc09f3 (diff)
downloadcoreclr-022f14f8575a8c371e0fc4a83ab7aef01ab79d7b.tar.gz
coreclr-022f14f8575a8c371e0fc4a83ab7aef01ab79d7b.tar.bz2
coreclr-022f14f8575a8c371e0fc4a83ab7aef01ab79d7b.zip
Merge pull request #18435 from acmyu/unwind
R2RDump - Use symbolic names for opcodes
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/r2rdump/Amd64/UnwindInfo.cs222
-rw-r--r--src/tools/r2rdump/R2RDump.cs2
-rw-r--r--src/tools/r2rdump/R2RMethod.cs9
-rw-r--r--src/tools/r2rdump/R2RReader.cs10
-rw-r--r--src/tools/r2rdump/UnwindInfo.cs114
5 files changed, 237 insertions, 120 deletions
diff --git a/src/tools/r2rdump/Amd64/UnwindInfo.cs b/src/tools/r2rdump/Amd64/UnwindInfo.cs
new file mode 100644
index 0000000000..1adca9a8c6
--- /dev/null
+++ b/src/tools/r2rdump/Amd64/UnwindInfo.cs
@@ -0,0 +1,222 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// 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.Text;
+
+namespace R2RDump.Amd64
+{
+ public enum UnwindOpCodes
+ {
+ UWOP_PUSH_NONVOL = 0,
+ UWOP_ALLOC_LARGE,
+ UWOP_ALLOC_SMALL,
+ UWOP_SET_FPREG,
+ UWOP_SAVE_NONVOL,
+ UWOP_SAVE_NONVOL_FAR,
+ UWOP_EPILOG,
+ UWOP_SPARE_CODE,
+ UWOP_SAVE_XMM128,
+ UWOP_SAVE_XMM128_FAR,
+ UWOP_PUSH_MACHFRAME,
+ UWOP_SET_FPREG_LARGE,
+ }
+
+ struct UnwindCode
+ {
+ public byte CodeOffset { get; }
+ public UnwindOpCodes UnwindOp { get; } //4 bits
+ public byte OpInfo { get; } //4 bits
+
+ public byte OffsetLow { get; }
+ public byte OffsetHigh { get; } //4 bits
+
+ public uint FrameOffset { get; }
+
+ public UnwindCode(byte[] image, ref int offset)
+ {
+ int off = offset;
+ CodeOffset = NativeReader.ReadByte(image, ref off);
+ byte op = NativeReader.ReadByte(image, ref off);
+ UnwindOp = (UnwindOpCodes)(op & 15);
+ OpInfo = (byte)(op >> 4);
+
+ OffsetLow = CodeOffset;
+ OffsetHigh = OpInfo;
+
+ FrameOffset = NativeReader.ReadUInt16(image, ref offset);
+ }
+ }
+
+ struct UnwindInfo : BaseUnwindInfo
+ {
+ private const int _sizeofUnwindCode = 2;
+ private const int _offsetofUnwindCode = 4;
+
+ public byte Version { get; } //3 bits
+ public byte Flags { get; } //5 bits
+ public byte SizeOfProlog { get; }
+ public byte CountOfUnwindCodes { get; }
+ public Amd64Registers FrameRegister { get; } //4 bits
+ public byte FrameOffset { get; } //4 bits
+ public UnwindCode[] UnwindCode { get; }
+ public uint PersonalityRoutineRVA { get; }
+ public int Size { get; }
+
+ public UnwindInfo(byte[] image, int offset)
+ {
+ byte versionAndFlags = NativeReader.ReadByte(image, ref offset);
+ Version = (byte)(versionAndFlags & 7);
+ Flags = (byte)(versionAndFlags >> 3);
+ SizeOfProlog = NativeReader.ReadByte(image, ref offset);
+ CountOfUnwindCodes = NativeReader.ReadByte(image, ref offset);
+ byte frameRegisterAndOffset = NativeReader.ReadByte(image, ref offset);
+ FrameRegister = (Amd64Registers)(frameRegisterAndOffset & 15);
+ FrameOffset = (byte)(frameRegisterAndOffset >> 4);
+
+ UnwindCode = new UnwindCode[CountOfUnwindCodes];
+ for (int i = 0; i < CountOfUnwindCodes; i++)
+ {
+ UnwindCode[i] = new UnwindCode(image, ref offset);
+ }
+
+ PersonalityRoutineRVA = NativeReader.ReadUInt32(image, ref offset);
+
+ Size = _offsetofUnwindCode + CountOfUnwindCodes * _sizeofUnwindCode;
+ int alignmentPad = ((Size + sizeof(int) - 1) & ~(sizeof(int) - 1)) - Size;
+ Size += (alignmentPad + sizeof(uint));
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.AppendLine($"\tVersion: {Version}");
+ sb.AppendLine($"\tFlags: 0x{Flags:X8}");
+ sb.AppendLine($"\tSizeOfProlog: {SizeOfProlog}");
+ sb.AppendLine($"\tCountOfUnwindCodes: {CountOfUnwindCodes}");
+ sb.AppendLine($"\tFrameRegister: {FrameRegister}");
+ sb.AppendLine($"\tFrameOffset: {FrameOffset}");
+ sb.AppendLine($"\tUnwind Codes:");
+ sb.AppendLine($"\t\t------------------");
+ for (int i = 0; i < CountOfUnwindCodes; i++)
+ {
+ sb.Append(GetUnwindCode(ref i));
+ sb.AppendLine($"\t\t------------------");
+ }
+ sb.AppendLine($"\tPersonalityRoutineRVA: 0x{PersonalityRoutineRVA:X8}");
+ sb.AppendLine($"\tSize: {Size} bytes");
+
+ return sb.ToString();
+ }
+
+ private string GetUnwindCode(ref int i)
+ {
+ StringBuilder sb = new StringBuilder();
+ string tab2 = new string(' ', 8);
+
+ sb.AppendLine($"{tab2}CodeOffset: 0x{UnwindCode[i].CodeOffset:X2}");
+ sb.AppendLine($"{tab2}UnwindOp: {UnwindCode[i].UnwindOp}({(byte)UnwindCode[i].UnwindOp})");
+
+ switch (UnwindCode[i].UnwindOp)
+ {
+ case UnwindOpCodes.UWOP_PUSH_NONVOL:
+ sb.AppendLine($"{tab2}OpInfo: {(Amd64Registers)UnwindCode[i].OpInfo}({UnwindCode[i].OpInfo})");
+ break;
+ case UnwindOpCodes.UWOP_ALLOC_LARGE:
+ sb.Append($"{tab2}OpInfo: {UnwindCode[i].OpInfo} - ");
+ if (UnwindCode[i].OpInfo == 0)
+ {
+ i++;
+ sb.AppendLine("Scaled small");
+ uint frameOffset = UnwindCode[i].FrameOffset * 8;
+ sb.AppendLine($"{tab2}FrameOffset: {UnwindCode[i].FrameOffset} * 8 = {frameOffset} = 0x{frameOffset:X5})");
+ }
+ else if (UnwindCode[i].OpInfo == 1)
+ {
+ i++;
+ sb.AppendLine("Unscaled large");
+ uint offset = UnwindCode[i].FrameOffset;
+ i++;
+ offset = ((UnwindCode[i].FrameOffset << 16) | offset);
+ sb.AppendLine($"{tab2}FrameOffset: 0x{offset:X8})");
+ }
+ else
+ {
+ sb.AppendLine("Unknown");
+ }
+ break;
+ case UnwindOpCodes.UWOP_ALLOC_SMALL:
+ int opInfo = UnwindCode[i].OpInfo * 8 + 8;
+ sb.AppendLine($"{tab2}OpInfo: {UnwindCode[i].OpInfo} * 8 + 8 = {opInfo} = 0x{opInfo:X2}");
+ break;
+ case UnwindOpCodes.UWOP_SET_FPREG:
+ sb.AppendLine($"{tab2}OpInfo: Unused({UnwindCode[i].OpInfo})");
+ break;
+ case UnwindOpCodes.UWOP_SET_FPREG_LARGE:
+ {
+ sb.AppendLine($"{tab2}OpInfo: Unused({UnwindCode[i].OpInfo})");
+ i++;
+ uint offset = UnwindCode[i].FrameOffset;
+ i++;
+ offset = ((UnwindCode[i].FrameOffset << 16) | offset);
+ sb.AppendLine($"{tab2}Scaled Offset: {offset} * 16 = {offset * 16} = 0x{(offset * 16):X8}");
+ if ((UnwindCode[i].FrameOffset & 0xF0000000) != 0)
+ {
+ R2RDump.WriteWarning("Illegal unwindInfo unscaled offset: too large");
+ }
+ }
+ break;
+ case UnwindOpCodes.UWOP_SAVE_NONVOL:
+ {
+ sb.AppendLine($"{tab2}OpInfo: {(Amd64Registers)UnwindCode[i].OpInfo}({UnwindCode[i].OpInfo})");
+ i++;
+ uint offset = UnwindCode[i].FrameOffset * 8;
+ sb.AppendLine($"{tab2}Scaled Offset: {UnwindCode[i].FrameOffset} * 8 = {offset} = 0x{offset:X5}");
+ }
+ break;
+ case UnwindOpCodes.UWOP_SAVE_NONVOL_FAR:
+ {
+ sb.AppendLine($"{tab2}OpInfo: {(Amd64Registers)UnwindCode[i].OpInfo}({UnwindCode[i].OpInfo})");
+ i++;
+ uint offset = UnwindCode[i].FrameOffset;
+ i++;
+ offset = ((UnwindCode[i].FrameOffset << 16) | offset);
+ sb.AppendLine($"{tab2}Unscaled Large Offset: 0x{offset:X8}");
+ }
+ break;
+ case UnwindOpCodes.UWOP_SAVE_XMM128:
+ {
+ sb.AppendLine($"{tab2}OpInfo: XMM{UnwindCode[i].OpInfo}({UnwindCode[i].OpInfo})");
+ i++;
+ uint offset = UnwindCode[i].FrameOffset * 16;
+ sb.AppendLine($"{tab2}Scaled Offset: {UnwindCode[i].FrameOffset} * 16 = {offset} = 0x{offset:X5}");
+ }
+ break;
+
+ case UnwindOpCodes.UWOP_SAVE_XMM128_FAR:
+ {
+ sb.AppendLine($"{tab2}OpInfo: XMM{UnwindCode[i].OpInfo}({UnwindCode[i].OpInfo})");
+ i++;
+ uint offset = UnwindCode[i].FrameOffset;
+ i++;
+ offset = ((UnwindCode[i].FrameOffset << 16) | offset);
+ sb.AppendLine($"{tab2}Unscaled Large Offset: 0x{offset:X8}");
+ }
+ break;
+ case UnwindOpCodes.UWOP_EPILOG:
+ case UnwindOpCodes.UWOP_SPARE_CODE:
+ case UnwindOpCodes.UWOP_PUSH_MACHFRAME:
+ default:
+ sb.AppendLine($"{tab2}OpInfo: {UnwindCode[i].OpInfo}");
+ sb.AppendLine();
+ sb.AppendLine($"{tab2}OffsetLow: {UnwindCode[i].OffsetLow}");
+ sb.AppendLine($"{tab2}OffsetHigh: {UnwindCode[i].OffsetHigh}");
+ sb.AppendLine();
+ sb.AppendLine($"{tab2}FrameOffset: {FrameOffset}");
+ break;
+ }
+ return sb.ToString();
+ }
+ }
+}
diff --git a/src/tools/r2rdump/R2RDump.cs b/src/tools/r2rdump/R2RDump.cs
index ccc736af7c..b909c1389a 100644
--- a/src/tools/r2rdump/R2RDump.cs
+++ b/src/tools/r2rdump/R2RDump.cs
@@ -203,7 +203,7 @@ namespace R2RDump
_writer.Write(rtf.UnwindInfo);
if (_raw)
{
- DumpBytes(r2r, rtf.UnwindRVA, (uint)rtf.UnwindInfo.Size);
+ DumpBytes(r2r, rtf.UnwindRVA, (uint)((Amd64.UnwindInfo)rtf.UnwindInfo).Size);
}
}
_writer.WriteLine();
diff --git a/src/tools/r2rdump/R2RMethod.cs b/src/tools/r2rdump/R2RMethod.cs
index 78e90af9c3..448b5b73e8 100644
--- a/src/tools/r2rdump/R2RMethod.cs
+++ b/src/tools/r2rdump/R2RMethod.cs
@@ -12,6 +12,11 @@ using System.Text;
namespace R2RDump
{
+ interface BaseUnwindInfo
+ {
+
+ }
+
class RuntimeFunction
{
/// <summary>
@@ -45,9 +50,9 @@ namespace R2RDump
/// </summary>
public R2RMethod Method { get; }
- public UnwindInfo UnwindInfo { get; }
+ public BaseUnwindInfo UnwindInfo { get; }
- public RuntimeFunction(int id, int startRva, int endRva, int unwindRva, int codeOffset, R2RMethod method, UnwindInfo unwindInfo, GcInfo gcInfo)
+ public RuntimeFunction(int id, int startRva, int endRva, int unwindRva, int codeOffset, R2RMethod method, BaseUnwindInfo unwindInfo, GcInfo gcInfo)
{
Id = id;
StartAddress = startRva;
diff --git a/src/tools/r2rdump/R2RReader.cs b/src/tools/r2rdump/R2RReader.cs
index aa28b78aa8..b5d150b597 100644
--- a/src/tools/r2rdump/R2RReader.cs
+++ b/src/tools/r2rdump/R2RReader.cs
@@ -262,10 +262,14 @@ namespace R2RDump
int unwindRva = NativeReader.ReadInt32(Image, ref curOffset);
int unwindOffset = GetOffset(unwindRva);
- UnwindInfo unwindInfo = new UnwindInfo(Image, unwindOffset);
- if (isEntryPoint[runtimeFunctionId])
+ BaseUnwindInfo unwindInfo = null;
+ if (Machine == Machine.Amd64)
{
- gcInfo = new GcInfo(Image, unwindOffset + unwindInfo.Size, Machine, R2RHeader.MajorVersion);
+ unwindInfo = new Amd64.UnwindInfo(Image, unwindOffset);
+ if (isEntryPoint[runtimeFunctionId])
+ {
+ gcInfo = new GcInfo(Image, unwindOffset + ((Amd64.UnwindInfo)unwindInfo).Size, Machine, R2RHeader.MajorVersion);
+ }
}
RuntimeFunction rtf = new RuntimeFunction(runtimeFunctionId, startRva, endRva, unwindRva, codeOffset, method, unwindInfo, gcInfo);
diff --git a/src/tools/r2rdump/UnwindInfo.cs b/src/tools/r2rdump/UnwindInfo.cs
deleted file mode 100644
index c7f60a52a0..0000000000
--- a/src/tools/r2rdump/UnwindInfo.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// 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.Text;
-
-namespace R2RDump
-{
- struct UnwindCode
- {
- public byte CodeOffset { get; }
- public byte UnwindOp { get; } //4 bits
- public byte OpInfo { get; } //4 bits
-
- public byte OffsetLow { get; }
- public byte OffsetHigh { get; } //4 bits
-
- public ushort FrameOffset { get; }
-
- public UnwindCode(byte[] image, ref int offset)
- {
- int off = offset;
- CodeOffset = NativeReader.ReadByte(image, ref off);
- byte op = NativeReader.ReadByte(image, ref off);
- UnwindOp = (byte)(op & 15);
- OpInfo = (byte)(op >> 4);
-
- OffsetLow = CodeOffset;
- OffsetHigh = OpInfo;
-
- FrameOffset = NativeReader.ReadUInt16(image, ref offset);
- }
-
- public override string ToString()
- {
- StringBuilder sb = new StringBuilder();
-
- sb.AppendLine($"\t\tCodeOffset: {CodeOffset}");
- sb.AppendLine($"\t\tUnwindOp: {UnwindOp}");
- sb.AppendLine($"\t\tOpInfo: {OpInfo}");
- sb.AppendLine();
- sb.AppendLine($"\t\tOffsetLow: {OffsetLow}");
- sb.AppendLine($"\t\tUnwindOp: {UnwindOp}");
- sb.AppendLine($"\t\tOffsetHigh: {OffsetHigh}");
- sb.AppendLine();
- sb.AppendLine($"\t\tFrameOffset: {FrameOffset}");
- sb.AppendLine($"\t\t--------------------");
-
- return sb.ToString();
- }
- }
-
- struct UnwindInfo
- {
- private const int _sizeofUnwindCode = 2;
- private const int _offsetofUnwindCode = 4;
-
- public byte Version { get; } //3 bits
- public byte Flags { get; } //5 bits
- public byte SizeOfProlog { get; }
- public byte CountOfUnwindCodes { get; }
- public byte FrameRegister { get; } //4 bits
- public byte FrameOffset { get; } //4 bits
- public UnwindCode[] UnwindCode { get; }
- public uint PersonalityRoutineRVA { get; }
- public int Size { get; }
-
- public UnwindInfo(byte[] image, int offset)
- {
- byte versionAndFlags = NativeReader.ReadByte(image, ref offset);
- Version = (byte)(versionAndFlags & 7);
- Flags = (byte)(versionAndFlags >> 3);
- SizeOfProlog = NativeReader.ReadByte(image, ref offset);
- CountOfUnwindCodes = NativeReader.ReadByte(image, ref offset);
- byte frameRegisterAndOffset = NativeReader.ReadByte(image, ref offset);
- FrameRegister = (byte)(frameRegisterAndOffset & 15);
- FrameOffset = (byte)(frameRegisterAndOffset >> 4);
-
- UnwindCode = new UnwindCode[CountOfUnwindCodes];
- for (int i = 0; i < CountOfUnwindCodes; i++)
- {
- UnwindCode[i] = new UnwindCode(image, ref offset);
- }
-
- PersonalityRoutineRVA = NativeReader.ReadUInt32(image, ref offset);
-
- Size = _offsetofUnwindCode + CountOfUnwindCodes * _sizeofUnwindCode;
- int alignmentPad = ((Size + sizeof(int) - 1) & ~(sizeof(int) - 1)) - Size;
- Size += (alignmentPad + sizeof(uint));
- }
-
- public override string ToString()
- {
- StringBuilder sb = new StringBuilder();
-
- sb.AppendLine($"\tVersion: {Version}");
- sb.AppendLine($"\tFlags: 0x{Flags:X8}");
- sb.AppendLine($"\tSizeOfProlog: {SizeOfProlog}");
- sb.AppendLine($"\tCountOfUnwindCodes: {CountOfUnwindCodes}");
- sb.AppendLine($"\tFrameRegister: {FrameRegister}");
- sb.AppendLine($"\tFrameOffset: {FrameOffset}");
- sb.AppendLine($"\tUnwind Codes:");
- sb.AppendLine($"\t\t------------------");
- for (int i = 0; i < CountOfUnwindCodes; i++)
- {
- sb.Append(UnwindCode[i].ToString());
- }
- sb.AppendLine($"\tPersonalityRoutineRVA: 0x{PersonalityRoutineRVA:X8}");
- sb.AppendLine($"\tSize: {Size} bytes");
-
- return sb.ToString();
- }
- }
-}