I originally reported this here: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=215709 libc++ / FreeBSD has recently acquired it's own implementation of __cxa_thread_atexit so that thread_local storage now works. This is great, except that it breaks static linkage with GCC which now complains about double definition: cd /home/mi/h4nn3s/devel/lambda-build/pkg/src && /usr/local/bin/cmake -E cmake_link_script CMakeFiles/lambda.dir/link.txt --verbose=1 /usr/local/libexec/ccache/g++6 -fopenmp -Wno-vla -O3 -DNDEBUG -flto=8 -s -static CMakeFiles/lambda.dir/lambda.cpp.o -o ../bin/lambda -lpthread -lexecinfo -lelf -lz -lbz2 //usr/lib/libc.a(cxa_thread_atexit.o): In function `__cxa_thread_atexit': /usr/src/lib/libc/stdlib/cxa_thread_atexit.c:(.text+0x0): multiple definition of `__cxa_thread_atexit' /usr/local/lib/gcc6/gcc/x86_64-portbld-freebsd11.0/6.3.0/../../../libstdc++.a(atexit_thread.o):/wrkdirs/usr/ports/lang/gcc6/work/gcc-6.3.0/libstdc++-v3/libsupc++/atexit_thread.cc:117: first defined here collect2: error: ld returned 1 exit status The FreeBSD maintainer responded with: This is a bug in gcc. The libsupc++ configuration assumes that there are exactly two possibilities: either libc is glibc and implements __cxa_thread_atexit() using __cxa_thread_atexit_impl(), or libsupc++ must provide an implementation on its own. Right solution is to add detection of __cxa_thread_atexit() in libc, to libstdc++ configure.ac and libsupc++/atexit_thread.cc. What is your opinion on the matter? Thanks!
I agree.
Created attachment 40448 [details] Check for __cxa_thread_atexit in libc Does this fix it?
(In reply to h2+bugs from comment #0) > This is a bug in gcc. The libsupc++ configuration assumes that there are > exactly two possibilities: either libc is glibc and implements > __cxa_thread_atexit() using __cxa_thread_atexit_impl(), or libsupc++ must > provide an implementation on its own. Although this isn't quite right, there's no assumption of glibc. The two possibilities are that only __cxa_thread_atexit_impl exists, or that neither __cxa_thread_atexit_impl nor __cxa_thread_atexit exists. There's no assumption about the provenance of __cxa_thread_atexit_impl.
I wonder why FreeBSD chose to do it that way, instead of providing the _impl function, which would also work with LLVM's libcxxabi.
It seems entirely wrong for libc to be providing any __cxa entry point called by the compiler, such as __cxa_thread_atexit. It should come from the C++ runtime, such as libsupc++, or libcxxabi, or FreeBSD's libcxxrt. We can work around it, but it's still wrong.
Thanks for your quick response! To be honest, I only have a very basic understanding of the matter. The original discussion of the implementation in FreeBSD can found here: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=192320 https://reviews.freebsd.org/rS303795 If you feel that this should be solved differently on FreeBSD's end, I will re-open discussion there. If that doesn't lead anywhere a workaround in GCC would be great, but since this actually affects all currently released GCCs on FreeBSD11, I would prefer an OS solution as gcc patches would likely only land in the most recent GCC-branch(es), right?
Right. This can be worked around for any GCC releases except 5.5, 6.4 and 7.1, but anything older can't be fixed.
(In reply to Jonathan Wakely from comment #7) > Right. This can be worked around for any GCC releases except 5.5, 6.4 and > 7.1, but anything older can't be fixed. Sorry, I edited that sentence half way through writing it. I meant: Right. This can be worked around for the future GCC releases 5.5, 6.4 and 7.1, but anything older can't be fixed.
Would older gcc releases fine if FreeBSD exports __cxa_thread_atexit_impl as an alias for __cxa_thread_atexit ? Note that there were no FreeBSD release which provided __cxa_thread_atexit, although the symbol is already present on the stable/11 branch and cannot be removed due ABI compat guarantees. It is used by libc++ already, I believe. Request for __cxa_thread_atexit came directly from one of the LLVM developers, at least this is how I see the history.
(In reply to Kostik Belousov from comment #9) > Would older gcc releases fine if FreeBSD exports __cxa_thread_atexit_impl as > an alias for __cxa_thread_atexit ? I think there would still be a duplicate definition of __cxa_thread_atexit in that case. > Note that there were no FreeBSD release > which provided __cxa_thread_atexit, although the symbol is already present > on the stable/11 branch and cannot be removed due ABI compat guarantees. It > is used by libc++ already, I believe. Is that a local change in FreeBSD's copy of libc++? Because there's no reference to it in the upstream libc++ repo. > Request for __cxa_thread_atexit came directly from one of the LLVM > developers, at least this is how I see the history. I understand the desire to have __cxa_thread_atexit available. The point is that it belongs in the C++ runtime, and that at least two implementations of the C++ runtime (libsupc++ and libcxxabi) already do the same thing, defining __cxa_thread_atexit unconditionally, but making use of __cxa_thread_atexit_impl if libc provides that.
(In reply to Jonathan Wakely from comment #10) > (In reply to Kostik Belousov from comment #9) > > Would older gcc releases fine if FreeBSD exports __cxa_thread_atexit_impl as > > an alias for __cxa_thread_atexit ? > > I think there would still be a duplicate definition of __cxa_thread_atexit > in that case. Yes, but the definitions will be runtime-identical. I mean that the benefit would be that not patched gcc configure will detect presence of __cxa_thread_atexit_impl and libsupc++ only provide trivial wrapper. This means that both implementations use compatible runtime. I am still somewhat puzzled by the 'duplicate definitions' linker diagnostic. It should be satisfied by whatever implementation it finds first. In the op case, somehow a whole static library is linked in, and we do not even know is it libc or libstdc++. > > > Note that there were no FreeBSD release > > which provided __cxa_thread_atexit, although the symbol is already present > > on the stable/11 branch and cannot be removed due ABI compat guarantees. It > > is used by libc++ already, I believe. > > Is that a local change in FreeBSD's copy of libc++? Because there's no > reference to it in the upstream libc++ repo. No, there is no change in libc++. Compiler generated references to __cxa_thread_atexit() are satisfied by libc directly. This was what asked for by the LLVM dev. > > > Request for __cxa_thread_atexit came directly from one of the LLVM > > developers, at least this is how I see the history. > > I understand the desire to have __cxa_thread_atexit available. The point is > that it belongs in the C++ runtime, and that at least two implementations of > the C++ runtime (libsupc++ and libcxxabi) already do the same thing, > defining __cxa_thread_atexit unconditionally, but making use of > __cxa_thread_atexit_impl if libc provides that. BTW, it was not unnatural to provide __cxa_thread_atexit() from libc, given the precedent of __cxa_atexit(3).
Created attachment 40451 [details] intermediate for O3
Created attachment 40452 [details] intermediate for O3 -fno-printf-return-value
sorry, please ignore the attachments, bugzilla dropped me in a different issue than planned.
Author: redi Date: Wed Jan 4 15:41:19 2017 New Revision: 244057 URL: https://gcc.gnu.org/viewcvs?rev=244057&root=gcc&view=rev Log: PR78968 add configure check for __cxa_thread_atexit in libc PR libstdc++/78968 * config.h.in: Regenerate. * configure: Likewise. * configure.ac: Check for __cxa_thread_atexit. * libsupc++/atexit_thread.cc [_GLIBCXX_HAVE___CXA_THREAD_ATEXIT]: Don't define __cxa_thread_atexit if libc provides it. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/config.h.in trunk/libstdc++-v3/configure trunk/libstdc++-v3/configure.ac trunk/libstdc++-v3/libsupc++/atexit_thread.cc
Trunk no longer defines __cxa_thread_atexit if it's found in libc. We might want to backport this to the gcc-5-branch and gcc-6-branch. I will try to test this in a FreeBSD 11 VM some time soon.
Author: redi Date: Fri Jan 6 17:06:24 2017 New Revision: 244169 URL: https://gcc.gnu.org/viewcvs?rev=244169&root=gcc&view=rev Log: Check for __cxa_thread_atexit for freebsd crosses PR libstdc++/78968 * crossconfig.m4: Check for __cxa_thread_atexit on *-*-freebsd*. * configure: Regenerate. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/configure trunk/libstdc++-v3/crossconfig.m4
(In reply to Jonathan Wakely from comment #16) > Trunk no longer defines __cxa_thread_atexit if it's found in libc. We might > want to backport this to the gcc-5-branch and gcc-6-branch. > > I will try to test this in a FreeBSD 11 VM some time soon. I just built trunk gcc on FreeBSD HEAD. Indeed, the newest gcc does not export __cxa_thread_atexit from libstdc++.so.6 when configured on a FreeBSD system which provides the symbol from libc. I also added __cxa_thread_atexit_impl, which does help with older gcc versions. I verified that libstdc++.so.6 provides __cxa_thread_atexit and expectedly forwards the calls to libc:__cxa_thread_atexit_impl. https://svnweb.freebsd.org/changeset/base/311651
Jonathan: Can the bug be marked as resolved?
Yes, this was fixed, thanks!