diff options
author | Amy <amycmyu@gmail.com> | 2018-06-26 15:01:14 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-26 15:01:14 -0700 |
commit | 022f14f8575a8c371e0fc4a83ab7aef01ab79d7b (patch) | |
tree | 9726c3b7ea253bb4dd6a74915fa02cc1e80b1f84 /src/tools | |
parent | 4e237f058b12403f7ee69d62fd24053081d5fe13 (diff) | |
parent | 435166408afb004a94ead8f236eb71c282bc09f3 (diff) | |
download | coreclr-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.cs | 222 | ||||
-rw-r--r-- | src/tools/r2rdump/R2RDump.cs | 2 | ||||
-rw-r--r-- | src/tools/r2rdump/R2RMethod.cs | 9 | ||||
-rw-r--r-- | src/tools/r2rdump/R2RReader.cs | 10 | ||||
-rw-r--r-- | src/tools/r2rdump/UnwindInfo.cs | 114 |
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(); - } - } -} |