Bug 7208 - Glibc C++ aplications crash if they use exceptions.
Summary: Glibc C++ aplications crash if they use exceptions.
Status: RESOLVED FIXED
Alias: None
Product: buildroot
Classification: Unclassified
Component: Other (show other bugs)
Version: 2014.05
Hardware: PC Linux
: P5 critical
Target Milestone: 2014.08
Assignee: Thomas Petazzoni
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-06-15 10:29 UTC by Krzysztof Wrzalik
Modified: 2014-08-17 07:43 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:


Attachments
Buildroot configuration (36.59 KB, application/octet-stream)
2014-06-15 14:52 UTC, Krzysztof Wrzalik
Details
Buildroot configuration (40.34 KB, text/plain)
2014-07-24 15:01 UTC, David Bachelart
Details
C code using pthread_exit (306 bytes, text/plain)
2014-07-24 15:01 UTC, David Bachelart
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Krzysztof Wrzalik 2014-06-15 10:29:22 UTC
I'm using a toolchain with glibc and the following simple program crashes:

#include <cstdio>

int main() {
  try {
    throw 42;
  } catch (int x) {
    printf("catch %d\n", x);
  }
}

with the following backtrace:

#0  0xb7747a92 in ?? () from /lib/ld-linux.so.2
#1  0xb74ac6b8 in raise () from /lib/libc.so.6
#2  0xb74adbae in abort () from /lib/libc.so.6
#3  0xb763903a in ?? () from /lib/libgcc_s.so.1
#4  0xb763936b in _Unwind_RaiseException () from /lib/libgcc_s.so.1
#5  0xb76d0304 in __cxa_throw () from /usr/lib/libstdc++.so.6
#6  0x080486c1 in main ()

when run on the host with proper ld-linux.so and run paths the stack trace is as follows:

#0  0xb7fdc424 in __kernel_vsyscall ()
#1  0xb7d4073f in raise () from /opt/gnl/usr/i686-gnl-linux-gnu/sysroot/lib/libc.so.6
#2  0xb7d41c5e in abort () from /opt/gnl/usr/i686-gnl-linux-gnu/sysroot/lib/libc.so.6
#3  0xb7ecf0d9 in uw_init_context_1 (context=context@entry=0xbfffe680, outer_cfa=outer_cfa@entry=0xbfffe860, outer_ra=0xb7f66424 <__cxxabiv1::__cxa_throw(void*, std:
:type_info*, void (*)(void*))+97>) at ../../../libgcc/unwind-dw2.c:1567
#4  0xb7ecf40a in _Unwind_RaiseException (exc=0x804a048) at ../../../libgcc/unwind.inc:88
#5  0xb7f66424 in __cxxabiv1::__cxa_throw (obj=0x804a068, tinfo=0x8049e50 <_ZTIi@@CXXABI_1.3>, dest=0x0) at ../../../../libstdc++-v3/libsupc++/eh_throw.cc:82
#6  0x08048924 in main () at dupa.cpp:8


In the discussion with tom_kos and wbx on IRC we managed to pin the problem libgcc_s.so. The problem only appears when linking with dynamic libgcc_s.so. If the program is compiled with -static-libgcc it runs correctly.
Comment 1 Thomas Petazzoni 2014-06-15 10:39:13 UTC
Which gcc version was used for the test? It can be useful to be able to match libgcc/unwind-dw2.c:1567 from the backtrace with the appropriate source code.
Comment 2 Krzysztof Wrzalik 2014-06-15 10:43:08 UTC
It comes from 4.9.0.
Comment 3 Thomas De Schampheleire 2014-06-15 14:40:11 UTC
Please also provide your .config file so other people can try to look at the problem.
Comment 4 Krzysztof Wrzalik 2014-06-15 14:52:47 UTC
Created attachment 5456 [details]
Buildroot configuration
Comment 5 Krzysztof Wrzalik 2014-06-15 17:54:22 UTC
The difference between compiling with -static-libgcc seems to boil down to the following function:

_Unwind_Find_FDE

When compiled with -statlic-libgcc the function invocation ends up in glibc.
When -static-libgcc is not given, then this function is located in libgcc.
Comment 6 Krzysztof Wrzalik 2014-06-15 20:10:59 UTC
It turns out that 900-musl-support.patch breaks exceptions when using glibc:

The proper exception handling in libgcc seems to need USE_PT_GNU_EH_FRAME definition in  libgcc's unwind-dw2-fde-dip.c. However; the patch changes this file to:

+#if !defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR)
 # define USE_PT_GNU_EH_FRAME

Configure in host-gcc-final seems to be unable to locate TARGET_DL_ITERATE_PHDR:
checking dl_iterate_phdr in target C library... unknown

In such case unwind-dw2-fde-dip.c falls back to unwind-dw2-fde.c which does not do the job of finding a FDE and hence the crash.
Comment 7 Thomas Petazzoni 2014-06-15 22:55:49 UTC
Thanks a lot for the debugging! I'll have a closer look and see what is the appropriate solution to make sure that C++ exceptions work with glibc, and that we can still enable musl.
Comment 8 mail 2014-06-16 08:28:30 UTC
Hi,

there is a discussion about this problem on the musl mailing list.
Just if you are not subscribed.
Comment 9 Krzysztof Wrzalik 2014-06-16 09:05:27 UTC
IMHO a good solution would be to make patches conditional in some cases, e.g. only use 900-musl-support.patch if C library is selected to musl. I guess it would require quite amount of work thought...
Comment 10 Thomas Petazzoni 2014-06-16 09:42:21 UTC
(In reply to comment #8)

> there is a discussion about this problem on the musl mailing list.
> Just if you are not subscribed.

Right, but I don't see our specific problem being taken into account. Rich Felker concluded the thread with:

"""
Please note that these changes are not mandatory; at present,
everything works, but crtbegin.o and crtend.o are unnecessarily
bloated and this affects static binary size.
"""

Maybe we should tell him that the changes are breaking C++ exception handling for glibc, when the musl patches are applied to gcc?
Comment 11 Thomas Petazzoni 2014-06-16 09:43:40 UTC
(In reply to comment #9)
> IMHO a good solution would be to make patches conditional in some cases, e.g.
> only use 900-musl-support.patch if C library is selected to musl. I guess it
> would require quite amount of work thought...

That's certainly a solution, but I wouldn't qualify it as a good solution. We try really hard to avoid having conditional patches.

Though, as a temporary solution it would certainly be acceptable. This problem is a major bug in Buildroot 2014.05, and we have to solve it somehow.
Comment 12 bugdal 2014-06-16 14:04:29 UTC
The relevant part of the musl patch is intended to remove the hard-coding of USE_PT_GNU_EH_FRAME as glibc-specific and instead detect via configure that it should be used. My guess is that something's broken in the configure script whereby TARGET_DL_ITERATE_PHDR is not getting detected correctly; perhaps the test is not cross-compiler-compatible.

Based on the thread on the musl mailing list (http://www.openwall.com/lists/musl/2014/06/16/2), I think if this is the problem it would go undetected by musl, since when targetting musl gcc is still producing an "old-style" crtbegin/crtend that works without USE_PT_GNU_EH_FRAME. With glibc that doesn't happen because the crtstuff preprocessor conditionals are still hard-coded for glibc.

In my opinion the "right" fix is finding and fixing whatever's wrong in configure, but as a short-term solution, the conditional could be fixed to hard-code USE_PT_GNU_EH_FRAME for glibc while detecting it elsewhere, as in:

+#if (!defined(inhibit_libc) && defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR)) || defined(__gnu_linux__)
 # define USE_PT_GNU_EH_FRAME

or something closer to whatever the upstream logic is for glibc.
Comment 13 Krzysztof Wrzalik 2014-06-16 18:58:47 UTC
If I'm looking at the right place, TARGET_DL_ITERATE_PHDR is defined in output/build/host-gcc-final-4.9.0/gcc/configure.ac at line 5079. It looks like it only gets set on a variant of solaris2. So this variable looks like a quick hack to me rather than something one can depend on.
Comment 14 Sven Neumann 2014-06-23 09:32:06 UTC
We are seeing the same problem with gcc 4.8.2 on our i586 platform. Code that uses C++ exceptions and which used to work fine with the buildroot 2014.02 release now aborts when an exception is thrown.
Comment 15 Sven Neumann 2014-06-23 11:40:01 UTC
(In reply to comment #14)
> We are seeing the same problem with gcc 4.8.2 on our i586 platform. Code that
> uses C++ exceptions and which used to work fine with the buildroot 2014.02
> release now aborts when an exception is thrown.

I have now verified that the problem goes away if I revert the commit that introduces musl support to gcc 4.8.2.
Comment 16 David Bachelart 2014-07-24 15:01:19 UTC
Created attachment 5528 [details]
Buildroot configuration
Comment 17 David Bachelart 2014-07-24 15:01:57 UTC
Created attachment 5534 [details]
C code using pthread_exit
Comment 18 David Bachelart 2014-07-24 15:09:29 UTC
Hi,

The 900-musl-support.patch also breaks the pthread_exit() function in pure C-code. I enclose two files :
- basic buildroot configuration, toolchain using gcc 4.8.1 / glibc 2.18 / binutils 2.22
- basic C code creating a thread that kills itself using pthread_exit()

Using a toolchain built from master, the main process receives the SIGABRT signal.

If I remove the 900-musl-support.patch and rebuild the whole buildroot, the code exits normally.
Comment 19 Thomas De Schampheleire 2014-08-09 15:44:53 UTC
What to do with this bug? We need a proper solution for the upcoming release...
Comment 20 Thomas Petazzoni 2014-08-14 17:24:35 UTC
Re-assigning to me, I'm working on it now.
Comment 21 Peter Korsgaard 2014-08-17 07:43:23 UTC
The patch series fixing this has now been applied:

http://git.buildroot.net/buildroot/commit/?id=fea35ce67317aa0eee678fb9440814d1346fb2fb