Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 229
unresolved_external Avatar asked Aug 03 '18 13:08

unresolved_external


People also ask

Which libc does clang use?

libc++ is LLVM's implementation of the C++ standard library, aimed at being a complete implementation of the C++ standards from C++11 onwards. You can instruct Clang to use libc++ with the -stdlib=libc++ flag.

Can GCC use libc ++?

Using libc++ with GCCYou must manually configure the compile and link commands. In particular you must tell GCC to remove the libstdc++ include directories using -nostdinc++ and to not link libstdc++.so using -nodefaultlibs.

What is libc ++ abi?

libc++abi is a new implementation of low level support for a standard C++ library. All of the code in libc++abi is dual licensed under the MIT license and the UIUC License (a BSD-like license).

What is Llvm libc ++?

libc++ is a new implementation of the C++ standard library, targeting C++11 and above. Features and Goals. Correctness as defined by the C++11 standard. Fast execution.


2 Answers

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

like image 128
Kei Avatar answered Nov 02 '22 09:11

Kei


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.

like image 44
raahlb Avatar answered Nov 02 '22 11:11

raahlb