[llvm] [llvm] Win x64 Unwind V2 2/n: Support dumping UOP_Epilog (PR #110338)
Daniel Paoliello via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 2 11:30:41 PDT 2024
https://github.com/dpaoliello updated https://github.com/llvm/llvm-project/pull/110338
>From 385d529794ce4f0fd72771d539b79b0138327a7d Mon Sep 17 00:00:00 2001
From: Daniel Paoliello <danpao at microsoft.com>
Date: Fri, 27 Sep 2024 16:05:35 -0700
Subject: [PATCH] [llvm] Win x64 Unwind V2 2/n: Support dumping UOP_Epilog
---
.../llvm-objdump/COFF/win64-unwindv2.yaml | 175 ++++++++++++++++++
.../COFF/unwind-x86_64-image.yaml | 67 ++++---
llvm/tools/llvm-objdump/COFFDump.cpp | 25 ++-
llvm/tools/llvm-readobj/Win64EHDumper.cpp | 27 ++-
llvm/tools/llvm-readobj/Win64EHDumper.h | 3 +-
5 files changed, 268 insertions(+), 29 deletions(-)
create mode 100644 llvm/test/tools/llvm-objdump/COFF/win64-unwindv2.yaml
diff --git a/llvm/test/tools/llvm-objdump/COFF/win64-unwindv2.yaml b/llvm/test/tools/llvm-objdump/COFF/win64-unwindv2.yaml
new file mode 100644
index 00000000000000..e2cdef19870c05
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/COFF/win64-unwindv2.yaml
@@ -0,0 +1,175 @@
+# RUN: yaml2obj %s -o %t.exe
+# RUN: llvm-objdump --unwind-info %t.exe | FileCheck %s
+
+# CHECK-LABEL: Unwind info:
+# CHECK-EMPTY:
+# CHECK-NEXT: Function Table:
+# CHECK-NEXT: Start Address: 0x1010
+# CHECK-NEXT: End Address: 0x1017
+# CHECK-NEXT: Unwind Info Address: 0x2000
+# CHECK-NEXT: Version: 2
+# CHECK-NEXT: Flags: 0
+# CHECK-NEXT: Size of prolog: 4
+# CHECK-NEXT: Number of Codes: 3
+# CHECK-NEXT: No frame pointer used
+# CHECK-NEXT: Unwind Codes:
+# CHECK-NEXT: 0x01: UOP_Epilog atend=yes, length=0x1
+# CHECK-NEXT: 0x0b: UOP_Epilog offset=0xB
+# CHECK-NEXT: 0x04: UOP_AllocSmall 72
+# CHECK-EMPTY:
+# CHECK-NEXT: Function Table:
+# CHECK-NEXT: Start Address: 0x1020
+# CHECK-NEXT: End Address: 0x105c
+# CHECK-NEXT: Unwind Info Address: 0x200c
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Flags: 3 UNW_ExceptionHandler UNW_TerminateHandler
+# CHECK-NEXT: Size of prolog: 4
+# CHECK-NEXT: Number of Codes: 1
+# CHECK-NEXT: No frame pointer used
+# CHECK-NEXT: Unwind Codes:
+# CHECK-NEXT: 0x04: UOP_AllocSmall 56
+
+--- !COFF
+OptionalHeader:
+ AddressOfEntryPoint: 4128
+ ImageBase: 5368709120
+ SectionAlignment: 4096
+ FileAlignment: 512
+ MajorOperatingSystemVersion: 6
+ MinorOperatingSystemVersion: 0
+ MajorImageVersion: 0
+ MinorImageVersion: 0
+ MajorSubsystemVersion: 6
+ MinorSubsystemVersion: 0
+ Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
+ DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE ]
+ SizeOfStackReserve: 1048576
+ SizeOfStackCommit: 4096
+ SizeOfHeapReserve: 1048576
+ SizeOfHeapCommit: 4096
+ ExportTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ImportTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ResourceTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ExceptionTable:
+ RelativeVirtualAddress: 12288
+ Size: 24
+ CertificateTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ BaseRelocationTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ Debug:
+ RelativeVirtualAddress: 0
+ Size: 0
+ Architecture:
+ RelativeVirtualAddress: 0
+ Size: 0
+ GlobalPtr:
+ RelativeVirtualAddress: 0
+ Size: 0
+ TlsTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ LoadConfigTable:
+ RelativeVirtualAddress: 0
+ Size: 0
+ BoundImport:
+ RelativeVirtualAddress: 0
+ Size: 0
+ IAT:
+ RelativeVirtualAddress: 0
+ Size: 0
+ DelayImportDescriptor:
+ RelativeVirtualAddress: 0
+ Size: 0
+ ClrRuntimeHeader:
+ RelativeVirtualAddress: 0
+ Size: 0
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 4096
+ VirtualSize: 113
+ SectionData: C3662E0F1F8400000000000F1F4400005048890C2458C3660F1F8400000000004883EC38E8D7FFFFFFE900000000488D4C2430E8D8FFFFFF904883C438C3488944242889542424488D4C2430E8BFFFFFFF488B4C2428E805000000CC0F1F4000C3662E0F1F8400000000000F1F440000C3
+ - Name: .xdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 8192
+ VirtualSize: 40
+ SectionData: 0204030001160B0604820000190401000462000070100000FFFF010804051E0009330000
+ - Name: .pdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 12288
+ VirtualSize: 24
+ SectionData: 101000001710000000200000201000005C1000000C200000
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .xdata
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .pdata
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: other
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _ZN4RAIID2Ev
+ Value: 16
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: entry
+ Value: 32
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _ZN4RAIID1Ev
+ Value: 16
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _Unwind_Resume
+ Value: 96
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __gxx_personality_seh0
+ Value: 112
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: GCC_except_table2
+ Value: 20
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+...
diff --git a/llvm/test/tools/llvm-readobj/COFF/unwind-x86_64-image.yaml b/llvm/test/tools/llvm-readobj/COFF/unwind-x86_64-image.yaml
index 5780cf7a0467b7..48a636514b77f2 100644
--- a/llvm/test/tools/llvm-readobj/COFF/unwind-x86_64-image.yaml
+++ b/llvm/test/tools/llvm-readobj/COFF/unwind-x86_64-image.yaml
@@ -1,26 +1,47 @@
# RUN: yaml2obj %s -o %t.exe
# RUN: llvm-readobj --unwind %t.exe | FileCheck %s
-# CHECK: RuntimeFunction {
-# CHECK: StartAddress: entry (0x140001020)
-# CHECK-NEXT: EndAddress: (0x14000105C)
-# CHECK-NEXT: UnwindInfoAddress: (0x140002008)
-# CHECK-NEXT: UnwindInfo {
-# CHECK-NEXT: Version: 1
-# CHECK-NEXT: Flags [ (0x3)
-# CHECK-NEXT: ExceptionHandler (0x1)
-# CHECK-NEXT: TerminateHandler (0x2)
-# CHECK-NEXT: ]
-# CHECK-NEXT: PrologSize: 4
-# CHECK-NEXT: FrameRegister: -
-# CHECK-NEXT: FrameOffset: -
-# CHECK-NEXT: UnwindCodeCount: 1
-# CHECK-NEXT: UnwindCodes [
-# CHECK-NEXT: 0x04: ALLOC_SMALL size=56
-# CHECK-NEXT: ]
-# CHECK-NEXT: Handler: __gxx_personality_seh0 (0x140001070)
+# CHECK-LABEL: UnwindInformation [
+# CHECK-NEXT: RuntimeFunction {
+# CHECK-NEXT: StartAddress: _ZN4RAIID2Ev (0x140001010)
+# CHECK-NEXT: EndAddress: (0x140001017)
+# CHECK-NEXT: UnwindInfoAddress: .xdata (0x140002000)
+# CHECK-NEXT: UnwindInfo {
+# CHECK-NEXT: Version: 2
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: PrologSize: 4
+# CHECK-NEXT: FrameRegister: -
+# CHECK-NEXT: FrameOffset: -
+# CHECK-NEXT: UnwindCodeCount: 3
+# CHECK-NEXT: UnwindCodes [
+# CHECK-NEXT: 0x01: EPILOG atend=yes, length=0x1
+# CHECK-NEXT: 0x0B: EPILOG offset=0xB
+# CHECK-NEXT: 0x04: ALLOC_SMALL size=72
+# CHECK-NEXT: ]
+# CHECK-NEXT: }
# CHECK-NEXT: }
-# CHECK-NEXT: }
+# CHECK-NEXT: RuntimeFunction {
+# CHECK-NEXT: StartAddress: entry (0x140001020)
+# CHECK-NEXT: EndAddress: (0x14000105C)
+# CHECK-NEXT: UnwindInfoAddress: (0x14000200C)
+# CHECK-NEXT: UnwindInfo {
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Flags [ (0x3)
+# CHECK-NEXT: ExceptionHandler (0x1)
+# CHECK-NEXT: TerminateHandler (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: PrologSize: 4
+# CHECK-NEXT: FrameRegister: -
+# CHECK-NEXT: FrameOffset: -
+# CHECK-NEXT: UnwindCodeCount: 1
+# CHECK-NEXT: UnwindCodes [
+# CHECK-NEXT: 0x04: ALLOC_SMALL size=56
+# CHECK-NEXT: ]
+# CHECK-NEXT: Handler: __gxx_personality_seh0 (0x140001070)
+# CHECK-NEXT: }
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
--- !COFF
OptionalHeader:
@@ -94,16 +115,16 @@ sections:
VirtualAddress: 4096
VirtualSize: 113
SectionData: C3662E0F1F8400000000000F1F4400005048890C2458C3660F1F8400000000004883EC38E8D7FFFFFFE900000000488D4C2430E8D8FFFFFF904883C438C3488944242889542424488D4C2430E8BFFFFFFF488B4C2428E805000000CC0F1F4000C3662E0F1F8400000000000F1F440000C3
- - Name: .rdata
+ - Name: .xdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
VirtualAddress: 8192
- VirtualSize: 32
- SectionData: 0101010001020000190401000462000070100000FFFF010804051E0009330000
+ VirtualSize: 40
+ SectionData: 0204030001160B0604820000190401000462000070100000FFFF010804051E0009330000
- Name: .pdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
VirtualAddress: 12288
VirtualSize: 24
- SectionData: 101000001710000000200000201000005C10000008200000
+ SectionData: 101000001710000000200000201000005C1000000C200000
symbols:
- Name: .text
Value: 0
diff --git a/llvm/tools/llvm-objdump/COFFDump.cpp b/llvm/tools/llvm-objdump/COFFDump.cpp
index 71697fa01e627d..97901ebf9851d8 100644
--- a/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -240,10 +240,10 @@ static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
case UOP_AllocSmall:
case UOP_SetFPReg:
case UOP_PushMachFrame:
+ case UOP_Epilog:
return 1;
case UOP_SaveNonVol:
case UOP_SaveXMM128:
- case UOP_Epilog:
return 2;
case UOP_SaveNonVolBig:
case UOP_SaveXMM128Big:
@@ -257,7 +257,7 @@ static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
// Prints one unwind code. Because an unwind code can occupy up to 3 slots in
// the unwind codes array, this function requires that the correct number of
// slots is provided.
-static void printUnwindCode(ArrayRef<UnwindCode> UCs) {
+static void printUnwindCode(ArrayRef<UnwindCode> UCs, bool &SeenFirstEpilog) {
assert(UCs.size() >= getNumUsedSlots(UCs[0]));
outs() << format(" 0x%02x: ", unsigned(UCs[0].u.CodeOffset))
<< getUnwindCodeTypeName(UCs[0].getUnwindOp());
@@ -301,11 +301,30 @@ static void printUnwindCode(ArrayRef<UnwindCode> UCs) {
outs() << " " << (UCs[0].getOpInfo() ? "w/o" : "w")
<< " error code";
break;
+
+ case UOP_Epilog:
+ if (SeenFirstEpilog) {
+ uint32_t Offset = (UCs[0].getOpInfo() << 8) |
+ static_cast<uint32_t>(UCs[0].u.CodeOffset);
+ if (Offset == 0) {
+ outs() << " padding";
+ } else {
+ outs() << " offset=" << format("0x%X", Offset);
+ }
+ } else {
+ SeenFirstEpilog = true;
+ bool AtEnd = (UCs[0].getOpInfo() & 0x1) != 0;
+ uint32_t Length = UCs[0].u.CodeOffset;
+ outs() << " atend=" << (AtEnd ? "yes" : "no")
+ << ", length=" << format("0x%X", Length);
+ }
+ break;
}
outs() << "\n";
}
static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) {
+ bool SeenFirstEpilog = false;
for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ) {
unsigned UsedSlots = getNumUsedSlots(*I);
if (UsedSlots > UCs.size()) {
@@ -316,7 +335,7 @@ static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) {
<< " remaining in buffer";
return ;
}
- printUnwindCode(ArrayRef(I, E));
+ printUnwindCode(ArrayRef(I, E), SeenFirstEpilog);
I += UsedSlots;
}
}
diff --git a/llvm/tools/llvm-readobj/Win64EHDumper.cpp b/llvm/tools/llvm-readobj/Win64EHDumper.cpp
index e4bd772191514a..ee043c9d0d10a1 100644
--- a/llvm/tools/llvm-readobj/Win64EHDumper.cpp
+++ b/llvm/tools/llvm-readobj/Win64EHDumper.cpp
@@ -65,6 +65,8 @@ static StringRef getUnwindCodeTypeName(uint8_t Code) {
case UOP_SaveXMM128: return "SAVE_XMM128";
case UOP_SaveXMM128Big: return "SAVE_XMM128_FAR";
case UOP_PushMachFrame: return "PUSH_MACHFRAME";
+ case UOP_Epilog:
+ return "EPILOG";
}
}
@@ -99,6 +101,7 @@ static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
case UOP_AllocSmall:
case UOP_SetFPReg:
case UOP_PushMachFrame:
+ case UOP_Epilog:
return 1;
case UOP_SaveNonVol:
case UOP_SaveXMM128:
@@ -254,7 +257,8 @@ void Dumper::printRuntimeFunctionEntry(const Context &Ctx,
// Prints one unwind code. Because an unwind code can occupy up to 3 slots in
// the unwind codes array, this function requires that the correct number of
// slots is provided.
-void Dumper::printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC) {
+void Dumper::printUnwindCode(const UnwindInfo &UI, ArrayRef<UnwindCode> UC,
+ bool &SeenFirstEpilog) {
assert(UC.size() >= getNumUsedSlots(UC[0]));
SW.startLine() << format("0x%02X: ", unsigned(UC[0].u.CodeOffset))
@@ -306,6 +310,24 @@ void Dumper::printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC) {
case UOP_PushMachFrame:
OS << " errcode=" << (UC[0].getOpInfo() == 0 ? "no" : "yes");
break;
+
+ case UOP_Epilog:
+ if (SeenFirstEpilog) {
+ uint32_t Offset =
+ (UC[0].getOpInfo() << 8) | static_cast<uint32_t>(UC[0].u.CodeOffset);
+ if (Offset == 0) {
+ OS << " padding";
+ } else {
+ OS << " offset=" << format("0x%X", Offset);
+ }
+ } else {
+ SeenFirstEpilog = true;
+ bool AtEnd = (UC[0].getOpInfo() & 0x1) != 0;
+ uint32_t Length = UC[0].u.CodeOffset;
+ OS << " atend=" << (AtEnd ? "yes" : "no")
+ << ", length=" << format("0x%X", Length);
+ }
+ break;
}
OS << "\n";
@@ -330,6 +352,7 @@ void Dumper::printUnwindInfo(const Context &Ctx, const coff_section *Section,
{
ListScope UCS(SW, "UnwindCodes");
ArrayRef<UnwindCode> UC(&UI.UnwindCodes[0], UI.NumCodes);
+ bool SeenFirstEpilog = false;
for (const UnwindCode *UCI = UC.begin(), *UCE = UC.end(); UCI < UCE; ++UCI) {
unsigned UsedSlots = getNumUsedSlots(*UCI);
if (UsedSlots > UC.size()) {
@@ -337,7 +360,7 @@ void Dumper::printUnwindInfo(const Context &Ctx, const coff_section *Section,
return;
}
- printUnwindCode(UI, ArrayRef(UCI, UCE));
+ printUnwindCode(UI, ArrayRef(UCI, UCE), SeenFirstEpilog);
UCI = UCI + UsedSlots - 1;
}
}
diff --git a/llvm/tools/llvm-readobj/Win64EHDumper.h b/llvm/tools/llvm-readobj/Win64EHDumper.h
index 97458c916bec6f..a23d30be7a113d 100644
--- a/llvm/tools/llvm-readobj/Win64EHDumper.h
+++ b/llvm/tools/llvm-readobj/Win64EHDumper.h
@@ -44,7 +44,8 @@ class Dumper {
const object::coff_section *Section,
uint64_t SectionOffset,
const RuntimeFunction &RF);
- void printUnwindCode(const UnwindInfo& UI, ArrayRef<UnwindCode> UC);
+ void printUnwindCode(const UnwindInfo &UI, ArrayRef<UnwindCode> UC,
+ bool &SeenFirstEpilog);
void printUnwindInfo(const Context &Ctx, const object::coff_section *Section,
off_t Offset, const UnwindInfo &UI);
void printRuntimeFunction(const Context &Ctx,
More information about the llvm-commits
mailing list