[llvm] [BOLT] Fix C++ exceptions when LPStart is specified (PR #72737)
Maksim Panchenko via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 20 10:40:42 PST 2023
https://github.com/maksfb updated https://github.com/llvm/llvm-project/pull/72737
>From 5f84266b4ba1878d373b6347f52a80a6453cd3da Mon Sep 17 00:00:00 2001
From: Maksim Panchenko <maks at fb.com>
Date: Fri, 17 Nov 2023 16:15:28 -0800
Subject: [PATCH 1/2] [BOLT] Fix C++ exceptions when LPStart is specified
Whenever LPStartEncoding was different from DW_EH_PE_omit, we used to
miscalculate LPStart. As a result, landing pads were assigned wrong
addresses. Fix that.
---
bolt/lib/Core/Exceptions.cpp | 61 +++++-----
.../runtime/X86/exceptions-lpstart-zero.s | 107 ++++++++++++++++++
2 files changed, 140 insertions(+), 28 deletions(-)
create mode 100644 bolt/test/runtime/X86/exceptions-lpstart-zero.s
diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp
index 657c3137ae9d62c..993f3a7770aa817 100644
--- a/bolt/lib/Core/Exceptions.cpp
+++ b/bolt/lib/Core/Exceptions.cpp
@@ -112,13 +112,18 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
uint64_t Offset = getLSDAAddress() - LSDASectionAddress;
assert(Data.isValidOffset(Offset) && "wrong LSDA address");
- uint8_t LPStartEncoding = Data.getU8(&Offset);
- uint64_t LPStart = 0;
- // Convert to offset if LPStartEncoding is typed absptr DW_EH_PE_absptr
- if (std::optional<uint64_t> MaybeLPStart = Data.getEncodedPointer(
- &Offset, LPStartEncoding, Offset + LSDASectionAddress))
- LPStart = (LPStartEncoding && 0xFF == 0) ? *MaybeLPStart
- : *MaybeLPStart - Address;
+ const uint8_t LPStartEncoding = Data.getU8(&Offset);
+ uint64_t LPStart = Address;
+ if (LPStartEncoding != dwarf::DW_EH_PE_omit) {
+ std::optional<uint64_t> MaybeLPStart = Data.getEncodedPointer(
+ &Offset, LPStartEncoding, Offset + LSDASectionAddress);
+ if (!MaybeLPStart) {
+ errs() << "BOLT-ERROR: unsupported LPStartEncoding: "
+ << (unsigned)LPStartEncoding << '\n';
+ exit(1);
+ }
+ LPStart = *MaybeLPStart;
+ }
const uint8_t TTypeEncoding = Data.getU8(&Offset);
LSDATypeEncoding = TTypeEncoding;
@@ -175,30 +180,13 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
uint64_t LandingPad = *Data.getEncodedPointer(
&CallSitePtr, CallSiteEncoding, CallSitePtr + LSDASectionAddress);
uint64_t ActionEntry = Data.getULEB128(&CallSitePtr);
-
- uint64_t LPOffset = LPStart + LandingPad;
- uint64_t LPAddress = Address + LPOffset;
-
- // Verify if landing pad code is located outside current function
- // Support landing pad to builtin_unreachable
- if (LPAddress < Address || LPAddress > Address + getSize()) {
- BinaryFunction *Fragment =
- BC.getBinaryFunctionContainingAddress(LPAddress);
- assert(Fragment != nullptr &&
- "BOLT-ERROR: cannot find landing pad fragment");
- BC.addInterproceduralReference(this, Fragment->getAddress());
- BC.processInterproceduralReferences();
- assert(isParentOrChildOf(*Fragment) &&
- "BOLT-ERROR: cannot have landing pads in different functions");
- setHasIndirectTargetToSplitFragment(true);
- BC.addFragmentsToSkip(this);
- return;
- }
+ if (LandingPad)
+ LandingPad += LPStart;
if (opts::PrintExceptions) {
outs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start)
<< ", 0x" << Twine::utohexstr(RangeBase + Start + Length)
- << "); landing pad: 0x" << Twine::utohexstr(LPOffset)
+ << "); landing pad: 0x" << Twine::utohexstr(LandingPad)
<< "; action entry: 0x" << Twine::utohexstr(ActionEntry) << "\n";
outs() << " current offset is " << (CallSitePtr - CallSiteTableStart)
<< '\n';
@@ -206,7 +194,24 @@ void BinaryFunction::parseLSDA(ArrayRef<uint8_t> LSDASectionData,
// Create a handler entry if necessary.
MCSymbol *LPSymbol = nullptr;
- if (LPOffset) {
+ if (LandingPad) {
+ // Verify if landing pad code is located outside current function
+ // Support landing pad to builtin_unreachable
+ if (LandingPad < Address || LandingPad > Address + getSize()) {
+ BinaryFunction *Fragment =
+ BC.getBinaryFunctionContainingAddress(LandingPad);
+ assert(Fragment != nullptr &&
+ "BOLT-ERROR: cannot find landing pad fragment");
+ BC.addInterproceduralReference(this, Fragment->getAddress());
+ BC.processInterproceduralReferences();
+ assert(isParentOrChildOf(*Fragment) &&
+ "BOLT-ERROR: cannot have landing pads in different functions");
+ setHasIndirectTargetToSplitFragment(true);
+ BC.addFragmentsToSkip(this);
+ return;
+ }
+
+ const uint64_t LPOffset = LandingPad - getAddress();
if (!getInstructionAtOffset(LPOffset)) {
if (opts::Verbosity >= 1)
errs() << "BOLT-WARNING: landing pad " << Twine::utohexstr(LPOffset)
diff --git a/bolt/test/runtime/X86/exceptions-lpstart-zero.s b/bolt/test/runtime/X86/exceptions-lpstart-zero.s
new file mode 100644
index 000000000000000..9221c4ec0db9dc8
--- /dev/null
+++ b/bolt/test/runtime/X86/exceptions-lpstart-zero.s
@@ -0,0 +1,107 @@
+# RUN: %clangxx %cflags -no-pie %s -o %t.exe -Wl,-q
+# RUN: llvm-bolt %t.exe -o %t.exe.bolt
+# RUN: %t.exe.bolt
+
+# REQUIRES: system-linux
+
+## Test that BOLT properly handles LPStart when LPStartEncoding is different
+## from DW_EH_PE_omit.
+
+# Test case compiled from:
+#
+# int main() {
+# try {
+# throw 42;
+# } catch (...) {
+# return 0;
+# }
+# return 1;
+# }
+#
+# The exception table was modified with a different LPStartEncoding and
+# CallSiteEncoding.
+
+ .text
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+ .type main, at function
+main: # @main
+.Lfunc_begin0:
+ .cfi_startproc
+ .globl __gxx_personality_v0
+ .cfi_personality 3, __gxx_personality_v0
+ .cfi_lsda 27, .Lexception0
+# %bb.0: # %entry
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+ subq $32, %rsp
+ movl $0, -4(%rbp)
+ movl $4, %edi
+ callq __cxa_allocate_exception at PLT
+ movq %rax, %rdi
+ movl $42, (%rdi)
+.Ltmp0:
+ movq _ZTIi at GOTPCREL(%rip), %rsi
+ xorl %eax, %eax
+ movl %eax, %edx
+ callq __cxa_throw at PLT
+.Ltmp1:
+ jmp .LBB0_4
+.LBB0_1: # %lpad
+.Ltmp2:
+ movq %rax, %rcx
+ movl %edx, %eax
+ movq %rcx, -16(%rbp)
+ movl %eax, -20(%rbp)
+# %bb.2: # %catch
+ movq -16(%rbp), %rdi
+ callq __cxa_begin_catch at PLT
+ movl $0, -4(%rbp)
+ callq __cxa_end_catch at PLT
+# %bb.3: # %return
+ movl -4(%rbp), %eax
+ addq $32, %rsp
+ popq %rbp
+ .cfi_def_cfa %rsp, 8
+ retq
+.LBB0_4: # %unreachable
+.Lfunc_end0:
+ .size main, .Lfunc_end0-main
+ .cfi_endproc
+ .section .gcc_except_table,"a", at progbits
+ .p2align 2, 0x0
+GCC_except_table0:
+.Lexception0:
+ .byte 3 # @LPStart Encoding = udata4
+ .long 0
+ .byte 155 # @TType Encoding = indirect pcrel sdata4
+ .uleb128 .Lttbase0-.Lttbaseref0
+.Lttbaseref0:
+ .byte 11 # Call site Encoding = udata4
+ .uleb128 .Lcst_end0-.Lcst_begin0
+.Lcst_begin0:
+ .long .Lfunc_begin0-.Lfunc_begin0 # >> Call Site 1 <<
+ .long .Ltmp0-.Lfunc_begin0 # Call between .Lfunc_begin0 and .Ltmp0
+ .long 0 # has no landing pad
+ .byte 0 # On action: cleanup
+ .long .Ltmp0-.Lfunc_begin0 # >> Call Site 2 <<
+ .long .Ltmp1-.Ltmp0 # Call between .Ltmp0 and .Ltmp1
+ .long .Ltmp2
+ .byte 1 # On action: 1
+ .long .Ltmp1-.Lfunc_begin0 # >> Call Site 3 <<
+ .long .Lfunc_end0-.Ltmp1 # Call between .Ltmp1 and .Lfunc_end0
+ .long 0 # has no landing pad
+ .byte 0 # On action: cleanup
+.Lcst_end0:
+ .byte 1 # >> Action Record 1 <<
+ # Catch TypeInfo 1
+ .byte 0 # No further actions
+ .p2align 2, 0x0
+ # >> Catch TypeInfos <<
+ .long 0 # TypeInfo 1
+.Lttbase0:
+ .p2align 2, 0x0
+ # -- End function
>From e205342b8e9b2eb7cb82ae41803534d5ee68c765 Mon Sep 17 00:00:00 2001
From: Maksim Panchenko <maks at fb.com>
Date: Mon, 20 Nov 2023 10:40:04 -0800
Subject: [PATCH 2/2] fixup! [BOLT] Fix C++ exceptions when LPStart is
specified
---
.../runtime/X86/exceptions-lpstart-zero.s | 66 +++++++------------
1 file changed, 25 insertions(+), 41 deletions(-)
diff --git a/bolt/test/runtime/X86/exceptions-lpstart-zero.s b/bolt/test/runtime/X86/exceptions-lpstart-zero.s
index 9221c4ec0db9dc8..b487ff0fa2f5911 100644
--- a/bolt/test/runtime/X86/exceptions-lpstart-zero.s
+++ b/bolt/test/runtime/X86/exceptions-lpstart-zero.s
@@ -7,7 +7,7 @@
## Test that BOLT properly handles LPStart when LPStartEncoding is different
## from DW_EH_PE_omit.
-# Test case compiled from:
+# The test case compiled with -O1 from:
#
# int main() {
# try {
@@ -18,7 +18,7 @@
# return 1;
# }
#
-# The exception table was modified with a different LPStartEncoding and
+# The exception table was modified with udata4 LPStartEncoding and sdata4
# CallSiteEncoding.
.text
@@ -28,59 +28,43 @@
main: # @main
.Lfunc_begin0:
.cfi_startproc
- .globl __gxx_personality_v0
.cfi_personality 3, __gxx_personality_v0
- .cfi_lsda 27, .Lexception0
-# %bb.0: # %entry
- pushq %rbp
+ .cfi_lsda 3, .Lexception0
+# %bb.0:
+ pushq %rax
.cfi_def_cfa_offset 16
- .cfi_offset %rbp, -16
- movq %rsp, %rbp
- .cfi_def_cfa_register %rbp
- subq $32, %rsp
- movl $0, -4(%rbp)
movl $4, %edi
- callq __cxa_allocate_exception at PLT
- movq %rax, %rdi
- movl $42, (%rdi)
+ callq __cxa_allocate_exception
+ movl $42, (%rax)
.Ltmp0:
- movq _ZTIi at GOTPCREL(%rip), %rsi
- xorl %eax, %eax
- movl %eax, %edx
- callq __cxa_throw at PLT
+ movl $_ZTIi, %esi
+ movq %rax, %rdi
+ xorl %edx, %edx
+ callq __cxa_throw
.Ltmp1:
- jmp .LBB0_4
-.LBB0_1: # %lpad
+# %bb.1:
+.LBB0_2:
.Ltmp2:
- movq %rax, %rcx
- movl %edx, %eax
- movq %rcx, -16(%rbp)
- movl %eax, -20(%rbp)
-# %bb.2: # %catch
- movq -16(%rbp), %rdi
- callq __cxa_begin_catch at PLT
- movl $0, -4(%rbp)
- callq __cxa_end_catch at PLT
-# %bb.3: # %return
- movl -4(%rbp), %eax
- addq $32, %rsp
- popq %rbp
- .cfi_def_cfa %rsp, 8
+ movq %rax, %rdi
+ callq __cxa_begin_catch
+ callq __cxa_end_catch
+ xorl %eax, %eax
+ popq %rcx
+ .cfi_def_cfa_offset 8
retq
-.LBB0_4: # %unreachable
.Lfunc_end0:
.size main, .Lfunc_end0-main
.cfi_endproc
.section .gcc_except_table,"a", at progbits
- .p2align 2, 0x0
+ .p2align 2
GCC_except_table0:
.Lexception0:
.byte 3 # @LPStart Encoding = udata4
.long 0
- .byte 155 # @TType Encoding = indirect pcrel sdata4
+ .byte 3 # @TType Encoding = udata4
.uleb128 .Lttbase0-.Lttbaseref0
.Lttbaseref0:
- .byte 11 # Call site Encoding = udata4
+ .byte 11 # Call site Encoding = sdata4
.uleb128 .Lcst_end0-.Lcst_begin0
.Lcst_begin0:
.long .Lfunc_begin0-.Lfunc_begin0 # >> Call Site 1 <<
@@ -89,7 +73,7 @@ GCC_except_table0:
.byte 0 # On action: cleanup
.long .Ltmp0-.Lfunc_begin0 # >> Call Site 2 <<
.long .Ltmp1-.Ltmp0 # Call between .Ltmp0 and .Ltmp1
- .long .Ltmp2
+ .long .Ltmp2 # jumps to .Ltmp2
.byte 1 # On action: 1
.long .Ltmp1-.Lfunc_begin0 # >> Call Site 3 <<
.long .Lfunc_end0-.Ltmp1 # Call between .Ltmp1 and .Lfunc_end0
@@ -99,9 +83,9 @@ GCC_except_table0:
.byte 1 # >> Action Record 1 <<
# Catch TypeInfo 1
.byte 0 # No further actions
- .p2align 2, 0x0
+ .p2align 2
# >> Catch TypeInfos <<
.long 0 # TypeInfo 1
.Lttbase0:
- .p2align 2, 0x0
+ .p2align 2
# -- End function
More information about the llvm-commits
mailing list