TL;DR: I have an issue where if I have a .so linked with -static-lib* making all STL symbols private, and if I throw an exception out of that .so to be caught by the caller, then I get a SIGABRT from a gcc_assert() down in the guts of the signal handling:
#0 0x00007ffff773a428 in raise () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x00007ffff773c02a in abort () from /lib/x86_64-linux-gnu/libc.so.6 #2 0x000000000040e938 in _Unwind_SetGR (context=<optimized out>, index=<optimized out>, val=<optimized out>) at /usr/src/cc/gcc-6.2.0/libgcc/unwind-dw2.c:271 271 gcc_assert (index < (int) sizeof(dwarf_reg_size_table)); Should it be possible to do this successfully or am I doomed to failure? More details and a test case below. More detail: I'm trying to distribute a shared library built with the latest version of C++ (well, GCC 6.2 with C++14) on GNU/Linux. I compile it with an older sysroot, taken from RHEL 6.3 (glibc 2.12) so it will run on older systems. My .so is written in C++ and programs that link it will also be written in C++ although they may be compiled and linked with potentially much older versions of GCC (like, 4.9 etc.) I'm not worried about programs compiled with clang or whatever at this point. Because I want to use new C++ but want users to be able to use my .so on older systems, I link with -static-libgcc -static-libstdc++. Because I don't want to worry about security issues etc. in system libraries, I don't link anything else statically. I also use a linker script to force all symbols (even libstdc++ symbols) to be private to my shared library except the ones I want to publish. Using "nm | grep ' [A-TV-Z] '" I can see that no other symbols besides mine are public. However, if my library throws an exception which I expect to be handled by the program linking my library, then I get a SIGABRT, as above; the full backtrace is: #0 0x00007ffff773a428 in raise () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x00007ffff773c02a in abort () from /lib/x86_64-linux-gnu/libc.so.6 #2 0x000000000040e938 in _Unwind_SetGR (context=<optimized out>, index=<optimized out>, val=<optimized out>) at /usr/src/cc/gcc-6.2.0/libgcc/unwind-dw2.c:271 #3 0x00000000004012a2 in __gxx_personality_v0 () #4 0x00007ffff7feb903 in _Unwind_RaiseException_Phase2 (exc=exc@entry=0x43b890, context=context@entry=0x7fffffffe330) at /usr/src/cc/gcc-6.2.0/libgcc/unwind.inc:62 #5 0x00007ffff7febf8a in _Unwind_RaiseException (exc=0x43b890) at /usr/src/cc/gcc-6.2.0/libgcc/unwind.inc:131 #6 0x00007ffff7fde84b in __cxa_throw () from /home/psmith/src/static-eh/libmylib.so #7 0x00007ffff7fddecb in MyLib::create () at mylib.cpp:2 #8 0x0000000000400da4 in main () at myprog.cpp:2 I should note that if I use the GCC 5.4 that comes standard on my OS rather than my locally-built version I get identical behavior and backtrace (except not as much debuggability of course). So I don't think it's an incorrect build. If I don't use -static-libstdc++ with my .so then it doesn't fail. Also if I don't use a linker script to hide all the C++ symbols it doesn't fail (but of course anyone who links with my shared library will use my copy of the STL). Here's a repro case (this shows the problem on my Ubuntu GNOME 16.04 GNU/Linux system with GCC 5.4 and binutils 2.26.1): ~$ cat mylib.h class MyLib { public: static void create(); }; ~$ cat mylib.cpp #include "mylib.h" void MyLib::create() { throw 42; } ~$ cat myprog.cpp #include "mylib.h" int main() { try { MyLib::create(); } catch (...) { return 0; } return 1; } ~$ cat ver.map { global: _ZN5MyLib6createEv; local: *; }; ~$ g++ -I. -g -fPIC -static-libgcc -static-libstdc++ \ -Wl,--version-script=ver.map -Wl,-soname=libmylib.so \ -shared -o libmylib.so mylib.cpp ~$ g++ -I. -g -fPIC -L. -Wl,-rpath="\$ORIGIN" -o myprog myprog.cpp \ -lmylib ~$ ./myprog Aborted (core dumped) Now if I rebuild without the --version-script argument or without -static-libstdc++, I get success as expected: ~$ ./myprog ~$ echo $? 0