Skip to content

[libc++abi] Fix lpStart adjustment for exceptions table #72727

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Dec 7, 2023

Conversation

maksfb
Copy link
Contributor

@maksfb maksfb commented Nov 18, 2023

When lpStartEncoding is different from DW_EH_PE_omit, lpStart can be set to zero which is a valid base address for landing pads. Such base value is useful when landing pads are placed in different sections.

Fixes #72582.

When lpStartEncoding is different from DW_EH_PE_omit, lpStart can be set
to zero which is a valid base address for landing pads. Such base value
is useful when landing pads are placed in different sections.

Fixes llvm#72582.
@maksfb maksfb added the libc++abi libc++abi C++ Runtime Library. Not libc++. label Nov 18, 2023
@maksfb maksfb requested a review from a team as a code owner November 18, 2023 00:40
@llvmbot
Copy link
Member

llvmbot commented Nov 18, 2023

@llvm/pr-subscribers-libcxxabi

Author: Maksim Panchenko (maksfb)

Changes

When lpStartEncoding is different from DW_EH_PE_omit, lpStart can be set to zero which is a valid base address for landing pads. Such base value is useful when landing pads are placed in different sections.

Fixes #72582.


Full diff: https://github.com/llvm/llvm-project/pull/72727.diff

3 Files Affected:

  • (modified) libcxxabi/src/cxa_personality.cpp (+3-4)
  • (added) libcxxabi/test/native/x86_64-unknown-linux/lit.local.cfg (+9)
  • (added) libcxxabi/test/native/x86_64-unknown-linux/lpstart-zero.pass.sh.s (+107)
diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp
index 4570d0b5beb2e2e..4b6c4edbc266985 100644
--- a/libcxxabi/src/cxa_personality.cpp
+++ b/libcxxabi/src/cxa_personality.cpp
@@ -660,10 +660,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
     //       dwarf emission
     // Parse LSDA header.
     uint8_t lpStartEncoding = *lsda++;
-    const uint8_t* lpStart =
-        (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
-    if (lpStart == 0)
-        lpStart = (const uint8_t*)funcStart;
+    const uint8_t* lpStart = lpStartEncoding == DW_EH_PE_omit
+                                 ? (const uint8_t*)funcStart
+                                 : (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
     uint8_t ttypeEncoding = *lsda++;
     if (ttypeEncoding != DW_EH_PE_omit)
     {
diff --git a/libcxxabi/test/native/x86_64-unknown-linux/lit.local.cfg b/libcxxabi/test/native/x86_64-unknown-linux/lit.local.cfg
new file mode 100644
index 000000000000000..bf3abe0d4881d98
--- /dev/null
+++ b/libcxxabi/test/native/x86_64-unknown-linux/lit.local.cfg
@@ -0,0 +1,9 @@
+def is_x86_64_linux(triple):
+    return ("x86_64" in triple) and ("linux" in triple)
+
+
+is_native = hasattr(config.root, "target_triple") and (
+    config.root.host_triple == config.root.target_triple
+)
+if not is_native or not is_x86_64_linux(config.root.host_triple):
+    config.unsupported = True
diff --git a/libcxxabi/test/native/x86_64-unknown-linux/lpstart-zero.pass.sh.s b/libcxxabi/test/native/x86_64-unknown-linux/lpstart-zero.pass.sh.s
new file mode 100644
index 000000000000000..3fd9102b340a13b
--- /dev/null
+++ b/libcxxabi/test/native/x86_64-unknown-linux/lpstart-zero.pass.sh.s
@@ -0,0 +1,107 @@
+# RUN: %{cxx} %{flags} %{link_flags} -no-pie %s -o %t.exe
+# RUN: %t.exe
+# UNSUPPORTED: no-exceptions
+
+# PURPOSE: Check that libc++abi works correctly when LPStart address is
+# explicitly set to zero.
+
+# This file is generated from the following C++ source code.
+#
+# ```
+# int main() {
+#   try {
+#     throw 42;
+#   } catch (...) {
+#     return 0;
+#   }
+#   return 1;
+# }
+# ```
+# The exception table is modified to use udata4 encoding for LPStart and
+# sdata4 encoding for call sites.
+
+	.text
+	.globl	main                            # -- Begin function main
+	.p2align	4, 0x90
+	.type	main,@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@PLT
+	movq	%rax, %rdi
+	movl	$42, (%rdi)
+.Ltmp0:
+	movq	_ZTIi@GOTPCREL(%rip), %rsi
+	xorl	%eax, %eax
+	movl	%eax, %edx
+	callq	__cxa_throw@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@PLT
+	movl	$0, -4(%rbp)
+	callq	__cxa_end_catch@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",@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

@maksfb
Copy link
Contributor Author

maksfb commented Nov 21, 2023

There's one msan test that keeps timing out, but everything else passes.

@maksfb maksfb requested review from ldionne and MaskRay November 21, 2023 21:08
@maksfb
Copy link
Contributor Author

maksfb commented Nov 29, 2023

Ping.

@ldionne
Copy link
Member

ldionne commented Nov 29, 2023

@ojhunt Do you feel qualified to review this? I know you've been playing around this part of the code lately.

@smeenai
Copy link
Collaborator

smeenai commented Nov 30, 2023

@MaskRay is probably most familiar with this, but as far as I can tell from the DWARF spec and https://www.airs.com/blog/archives/464, this is correct (and matches libsupc++, as the issue mentions). It seems like a general deficiency of readEncodedPointer that it doesn't distinguish between DW_EH_PE_omit and an actual encoded value of zero; idk if that can affect more places as well.

@maksfb
Copy link
Contributor Author

maksfb commented Dec 5, 2023

@MaskRay, does the fix look reasonable to you?

Copy link
Member

@MaskRay MaskRay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed that lpstart-zero.pass.sh.s passes when linked against new libc++/libc++abi, like libstdc++.

@maksfb maksfb merged commit 1853025 into llvm:main Dec 7, 2023
@ldionne
Copy link
Member

ldionne commented Dec 7, 2023

I think this patch broke our Android CI: https://buildkite.com/llvm-project/libcxx-ci/builds/32080#018c4427-1b79-4812-be06-26e96121f5d8

Can you confirm and take a look? If it looks complicated to fix, we should probably consider reverting until we understand the problem since this was just introduced.

@ldionne
Copy link
Member

ldionne commented Dec 7, 2023

I am not sure why the BuildKite pre-commit CI doesn't seem to have been triggered by this patch so I think there's no way you could have seen this.

@maksfb
Copy link
Contributor Author

maksfb commented Dec 7, 2023

Let me take a look.

@maksfb
Copy link
Contributor Author

maksfb commented Dec 7, 2023

The binary created by clang cannot be located when executed. I'm not familiar with Android test system and don't have an access to x86_64 Android system to repro. Going to disable this test whenever the target triple contains "android".

maksfb added a commit to maksfb/llvm-project that referenced this pull request Dec 7, 2023
Follow up to llvm#72727. The added test could not be executed on Android.
ldionne pushed a commit that referenced this pull request Dec 13, 2023
Follow up to #72727. The added test could not be executed on Android.
@maksfb maksfb deleted the gh-cxxabi-lpstart branch January 30, 2024 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++abi libc++abi C++ Runtime Library. Not libc++.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc++abi] Incorrect adjustment of landing pad when LPStart is set to zero
5 participants