unresolved_external
unresolved_external

Reputation: 2018

Clang with libc++ exceptions

I've been experimenting with different c++ libs, and found out the following: The simple application:

#include <iostream>

int main(int argc, char* argv[])
{
    try
    {
        throw 1;
    }
    catch(...)
    {
        std::cout << "Exception is caught\n";
    }
}

When I compile it on ARM like this:

clang++ -stdlib=stdlibc++

The exception is caught as expected.

But when I change it to:

clang++ -stdlib=libc++

I am constantly getting:

terminating with uncaught exception of type int
Aborted

I've tried to turn on exception explicitly with various flags like:

-fexceptions
-fcxx-exceptions
-frtti

But none of these flags work. What is the reason of the uncaught exception? Could it be because incorrectly installed libc++?

P.S. On the PC, the same program compiled with libc++ works as expected. libc++ version is the same on both platforms - 3.7.0-1ubuntu0.1

Upvotes: 8

Views: 3083

Answers (2)

raahlb
raahlb

Reputation: 317

This is because of a bug in the compilation of libunwind. It has been fixed now: https://reviews.llvm.org/D71117

Exceptions were broken for ARM when using libc++ and libunwind. From what I can tell, it was fixed in LLVM-10.0.0.

Upvotes: 1

Kei
Kei

Reputation: 141

Yes I got exactly the same issue for PowerPC, ARM and even on the X86 Linux itself. The problem is (I traced it with PowerPC): The the throw is doing a __cxa_throw, which is calling _Unwind_RaiseException in the libunwind part of the libc++. This _Unwind_RaiseException itself is calling unw_getcontext to get all registers at this point. Now it tries to find the calling functions backwards via the ".eh_frame" in the ELF file. But as the UnwindLevel1.c is a C file, there are no .cfi_start ... information in the assembly part which are creating the .eh_frame information. Means, that the stack-traceback is directly ending on the first function (_Unwind_RaiseException) and not going further back to identfy the calling "catch" part. This can by corrected by compiling the .c parts in the libc++ with the C++ compiler (clang++ instead of clang). For this case the .cfi_start information are also generated for for the functions. Now the Stack-Trace-Back can find the first functions and also previous functions up to main (in my test case). For ARM, I'm hunting for the next problem right now, as the Stack-Trace-Back is not working. It scans the same function again and again, but not going backward (endless loop).

When compiling the .c files with clang++, you will run into an issue with not defined parts in stdlib.h, because it uses the wrong stdlib.h from libcxx/include and not from the MUSL includes. I don't have a good solution right now, except for modifying some header files by hand.

Kei

Upvotes: 9

Related Questions