[cfe-dev] ARM Linux libc++ / libunwind — Exceptions not being caught

Andrew Brownsword via cfe-dev cfe-dev at lists.llvm.org
Thu Aug 30 16:53:58 PDT 2018


Okay, we can mark this one as solved, but I’d like to generate a pair of requests/suggestions based on it.  First though, the fix...

Once I realized that the libc++ library itself seemed to not be throwing/catching properly, I went back and looked at the build log for it.  I was newly armed with the knowledge that clang and gcc generate different exception related information.  I realized that the environment I had used to build the libraries was the same one I had used to build clang from scratch… using gcc.  The $CC/$CXX env vars were unset and therefore the cmake/ninja build system picked up that gcc should be used, and as a result libc++ was being built with a compiler that generates incompatible unwind tables (or whatever the relevant data structures are called).  Once I rebuilt the libraries with clang the repro case and my project started catching exceptions thrown from libc++.

Thanks for your help, Louis and Peter.  It would have taken me a long time to figure that out without your replies.


Now, my suggestions… 

1) Clearly the situation around the creation of unwind-tables, et al. is something of a muddle.  Am I mistaken in thinking that libraries built with different compilers are going to have this problem?  Seems like a subtle change in the ABI.  Expecting that it should get fixed seems like asking for a lot, but it would be *really* nice if something in the environment could examine all of the various modules involved in launching a process, and determine if they have incompatible exception handling schemes, and emit a warning.  Ideally this would be the linker or the runtime itself.  Perhaps only in debug builds.  Using ldd to examine library dependencies is pretty common, so that would be an effective place too (but much slower to roll out).

2) Building the toolchain seems fraught with peril, and the documentation provides some guidance but with too many options and nothing definitive.  I understand that the deployment matrix for this whole ecosystem is impressively enormous, but some kind of map like Louis alluded to would be most helpful.  What he suggested was filling out the whole matrix, but I don’t think that’s necessary.  Instead, some sort of official page where known working paths to success can be recorded and maintained — ideally in the form of scripts that can be downloaded, tweaked if needed, and run.  If in the form of scripts then there is the potential to do automated testing (admittedly challenging given the purpose of covering a wide array of platforms).  Weird hacky solutions would *not* be listed there, just proper/intended uses of the toolchain build system to get to a working toolchain.  I wasted too much time on stackoverflow/etc trolling through various people’s attempts and hacks to get the last ~8 years worth of versions running.


> On Aug 30, 2018, at 2:41 PM, Andrew Brownsword <andrew.e.brownsword at gmail.com> wrote:
> 
> I already checked ldd and the paths are as I expect... but I was surprised to see gcc_s in the list.  Is that expected?
> 
> It is only the std exceptions thrown from libc++ that seem to have a problem, so doesn’t that imply that the lib is internally inconsistent (which an include path problem couldn’t cause?).
> 
>> On Aug 30, 2018, at 2:11 PM, Louis Dionne <ldionne at apple.com> wrote:
>> 
>> 
>>> On Aug 30, 2018, at 17:03, Andrew Brownsword <andrew.e.brownsword at gmail.com> wrote:
>>> 
>>> I followed these steps with a couple of caveats:
>>>   * used the (mostly) working clang toolchain I have in place (7.0.0rc2)
>>>   * removed the -mcpu options (don’t know what valid list is)
>>>   * had to prefix sub-project names with llvm/projects/*
>>>   * created build directory in llvm/ (don’t normally like to do that)
>>>   * ninja unwind (no lib prefix)
>>>   * also tried using install-* target; built test program with paths to build dir as well as to the installed locations
>>> 
>>> Still doesn’t catch the stoul exception.
>>> 
>> 
>> I would suggest that you:
>> 
>> 1. Use ldd to see exactly what shared objects are loaded by your program, and confirm that those are the ones you expect.
>> 2. Run `nm --demangle` on libc++, libc++abi, libunwind and your program and look for the typeinfo of your exception class.
>> 3. When building libcxxabi and libunwind, pass `-v` to ninja to see all the compilation commands, and then modify a command to preprocess `-E` the file instead and see exactly which headers are used to build. Confirm that you’re building libc++abi and libunwind against the correct headers.
>> 
>> Maybe you’ll find out that the exception class has typeinfo in more than one place, which could lead to the exception not being caught (if it’s thrown with a typeinfo different from the one used to catch). I’ve debugged very similar problems like that in the past. Another option is that your libunwind/libc++abi are somehow built against different headers or in a different configuration than you’re expecting, and that can lead to trouble (we’ve had one like that during the LLVM 7 release).
>> 
>> Louis
>> 
>>> 
>>>> My steps were:
>>>> 1.) Build trunk clang to use for building libc++ etc.
>>>> 2.) Using cmake
>>>> 
>>>> cmake -GNinja\
>>>>   /path/to/monorepo/llvm \
>>>>   -DLLVM_ENABLE_PROJECTS="libcxxabi;libcxx;libunwind" \
>>>>   -DCMAKE_BUILD_TYPE=Release \
>>>>   -DLLVM_ENABLE_ASSERTIONS=true\
>>>>   -DCMAKE_C_FLAGS='-mcpu=cortex-a57'\
>>>>   -DCMAKE_CXX_FLAGS='-mcpu=cortex-a57'\
>>>>   -DLLVM_TARGETS_TO_BUILD='ARM'\
>>>>   -DLIBCXXABI_USE_LLVM_UNWINDER=On
>>>> 3.) build
>>>> ninja libunwind
>>>> ninja cxxabi
>>>> ninja cxx
>>>> 
>>>> I was then able to run the example with:
>>>> clang++ --stdlib=libc++ -I ./include/c++/v1 t.cpp -o t.axf -L ./lib -v
>>>> --std=c++17
>>>> LD_LIBRARY_PATH=lib ./t.axf./t.axf
>>>> caught!
>>> 
>> 




More information about the cfe-dev mailing list