Skip to content
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

[BUG] Segfault when using LTO and nested exception handlers #2073

Open
darcy-phipps opened this issue Sep 16, 2024 · 0 comments
Open

[BUG] Segfault when using LTO and nested exception handlers #2073

darcy-phipps opened this issue Sep 16, 2024 · 0 comments
Assignees
Labels

Comments

@darcy-phipps
Copy link

Description

LTO seems to mess up stack unwinding when exception handlers are nested across function calls. This causes a segfault while unwinding the stack. Without LTO, the stack is correctly unwound.

The following code reproduces the crash

#include <iostream>
#include <stdexcept>
#include <string>

std::string thrower() {
  throw std::out_of_range("nope");
}

std::string __attribute__((noinline)) wrapper() {
  try {
    return thrower();
  } catch (std::out_of_range&) {
    throw;
  } catch (...) {
    return "";
  }
}

int main() {
  try {
    auto s = wrapper();
    std::cout << "Wrapper returned: " << s << std::endl;
  } catch (std::out_of_range&) {
    std::cout << "Got a std::out_of_range" << std::endl;
  } catch (...) {
    std::cout << "Got some other exception" << std::endl;
  }

  return 0;
}

NOTE: The __attribute((noinline)) is required to keep the optimizer from inlining the wrapper which also makes the segfault go away. Having the nested handlers across function calls seems to be a requirement for this particular problem.

Building with ndk-27b, WITHOUT lto, and pushing to an emulator running Android 11

./android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=x86_64-none-linux-android30 --sysroot=./android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/sysroot -g -O2 -std=gnu++14 -o atest_no_lto main.cpp
adb push atest_no_lto ./android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so /data/local/tmp
adb logcat -c
adb shell "LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/atest_no_lto"

Gives the output

Got a std::out_of_range

Building with ndk-27b, WITH lto, and pushing to an emulator running Android 11

./android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=x86_64-none-linux-android30 --sysroot=./android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/sysroot -g -O2 -flto -std=gnu++14 -o atest_lto main.cpp
adb push atest_lto ./android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so /data/local/tmp
adb logcat -c
adb shell "LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/atest_lto"
adb logcat -d

Gives the output (and logcat)

Segmentation fault 
--------- beginning of crash
09-16 09:36:38.133  9973  9973 F libc    : Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 9973 (atest_lto), pid 9973 (atest_lto)
--------- beginning of main
09-16 09:36:38.142  9976  9976 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone
09-16 09:36:38.143   299   299 I tombstoned: received crash request for pid 9973
09-16 09:36:38.143  9976  9976 I crash_dump64: performing dump of process 9973 (target tid = 9973)
09-16 09:36:38.143  9976  9976 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
09-16 09:36:38.143  9976  9976 F DEBUG   : Build fingerprint: 'google/sdk_gslim_x86_64/generic_x86_64:11/RSR1.210722.030/10147527:userdebug/dev-keys'
09-16 09:36:38.143  9976  9976 F DEBUG   : Revision: '0'
09-16 09:36:38.144  9976  9976 F DEBUG   : ABI: 'x86_64'
09-16 09:36:38.144  9976  9976 F DEBUG   : Timestamp: 2024-09-16 09:36:38-0400
09-16 09:36:38.144  9976  9976 F DEBUG   : pid: 9973, tid: 9973, name: atest_lto  >>> /data/local/tmp/atest_lto <<<
09-16 09:36:38.144  9976  9976 F DEBUG   : uid: 0
09-16 09:36:38.144  9976  9976 F DEBUG   : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
09-16 09:36:38.144  9976  9976 F DEBUG   : Cause: null pointer dereference
09-16 09:36:38.144  9976  9976 F DEBUG   :     rax 00007ffe572bbdf8  rbx 00007ffe572bb910  rcx 0000784a2d780510  rdx 0000000000000001
09-16 09:36:38.144  9976  9976 F DEBUG   :     r8  00007ffe572bbd00  r9  0000000000000028  r10 00005733a90621e8  r11 00005733a9062800
09-16 09:36:38.144  9976  9976 F DEBUG   :     r12 00007ffe572bba00  r13 0000784a2d780510  r14 00007ffe572bbd00  r15 0000000000000002
09-16 09:36:38.144  9976  9976 F DEBUG   :     rdi 00007ffe572bbd00  rsi 00007ffe572bb910
09-16 09:36:38.144  9976  9976 F DEBUG   :     rbp 0000000000000002  rsp 00007ffe572bb8f8  rip 0000000000000000
09-16 09:36:38.146  9976  9976 F DEBUG   : backtrace:
09-16 09:36:38.146  9976  9976 F DEBUG   :       #00 pc 0000000000000000  <unknown>
09-16 09:36:38.146  9976  9976 F DEBUG   :       #01 pc 0000000000125fc9  /data/local/tmp/libc++_shared.so (__unw_get_proc_info+9) (BuildId: 734ab2eaa203afbb89147d313e46146617bd1a2c)
09-16 09:36:38.146  9976  9976 F DEBUG   :       #02 pc 000000000000150f  [anon:scudo:primary]
09-16 09:36:38.146  9976  9976 F DEBUG   :       #03 pc 0000000000125dcb  /data/local/tmp/libc++_shared.so (_Unwind_GetLanguageSpecificData+11) (BuildId: 734ab2eaa203afbb89147d313e46146617bd1a2c)
09-16 09:36:38.149     0     0 D logd    : logdr: UID=0 GID=0 PID=9976 n tail=50 logMask=8 pid=9973 start=0ns timeout=0ns
09-16 09:36:38.150     0     0 D logd    : logdr: UID=0 GID=0 PID=9976 n tail=50 logMask=1 pid=9973 start=0ns timeout=0ns
09-16 09:36:38.150     0     0 D logd    : logdr: UID=0 GID=0 PID=9976 n tail=0 logMask=8 pid=9973 start=0ns timeout=0ns
09-16 09:36:38.151     0     0 D logd    : logdr: UID=0 GID=0 PID=9976 n tail=0 logMask=1 pid=9973 start=0ns timeout=0ns
09-16 09:36:38.153     0     0 I init    : Untracked pid 9976 exited with status 0
09-16 09:36:38.153     0     0 I init    : Untracked pid 9978 exited with status 0
--------- beginning of system
09-16 09:36:38.154   543   813 W NativeCrashListener: Couldn't find ProcessRecord for pid 9973
09-16 09:36:38.154   299   299 E tombstoned: Tombstone written to: /data/tombstones/tombstone_44

I'm attaching the full tombstone file in case it helps.
tombstone_44.zip

This also happens with ndk-26c and clang-17, which is where I first ran into it. I tried reproducing this problem directly on ubuntu 22.04 using clang-17 but was unsuccessful.

While digging around LLVM's bugtracker I found the following issue that may be relevant: llvm/llvm-project#56825

Affected versions

r26, r27

Canary version

No response

Host OS

Linux

Host OS version

Ubuntu 22.04

Affected ABIs

x86_64

Build system

ndk-build

Other build system

No response

minSdkVersion

n/a

Device API level

30

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Awaiting triage
Status: Unconfirmed
Development

No branches or pull requests

2 participants