Exceptions catch lead to segv when binary compile with no-pie

clang++ version :16

bolt --version output:

LLVM version 16.0.0. DEBUG build with assertions. BOLT revision 08d094a0e457360ad8b94b017d2dc277e697ca76

reproduce demo

int Foo() { throw 42; }

int main() {
  try {
    return Foo();
  } catch (...) {
    return 0;
  }
}

when compile with -no-pie,after bolt optimization, it SIGSEGV when run the main.bolted. here is the build script:

clang++ main.cc -g -Wl,–emit-relocs -stdlib=libc++ -lc++abi -pthread -no-pie -o main
llvm-bolt ./main -o main.bolted

Since programs compiled after llvm15 are compile with pie by default, here if I remove the no-pie option, the Bolt-optimized program will run without SEGV errors.
I would like to know what caused the no-pie program SEGV. Thank you for your reply

Possibly would be fixed by [BOLT] Fix LSDA section handling by yota9 · Pull Request #71821 · llvm/llvm-project · GitHub . Please try it. Probably would submit it today.
UPD No, other case here.

Somehow libc++ is not happy with the exception ranges. Looking…

Yes, if stdc++ is used, the optimized program will run normally.

I left a comment on GH ([BOLT] exceptions catch lead to segv when binary compile with no-pie · Issue #72363 · llvm/llvm-project · GitHub). TL;DR: it’s an issue with libc++/libc++abi.

In BOLT, we encode exception ranges in a way that allows us to place exception-handling code in any section or a group of sections. In practice, some exception handlers can actually be “warm”, i.e. are executed time to time. The encoding we use complies with the Itanium C++ ABI.

Unlike BOLT, LLVM backend “cheats” even under -fbasic-block-sections=all option and places all exception-handling code in the same section even when it’s comprised of multiple basic blocks. Then it uses a different encoding for LPStart member of exception ranges which libc++ has no issue with.

1 Like