Intended usage of _GLIBCXX_HAVE_TLS / emutls symbols on OSX

Dave Gittins dave.gittins@gmail.com
Wed Jan 8 20:06:00 GMT 2020


Update: I believe this is resolved by adding -lgcc_s.1 to the build
command. (gcc does this automatically)

So in case anyone else runs into this, here is my working build
command to build with clang on OSX against the gcc 7.5 std lib:

usr/local/Cellar/llvm@7/7.1.0_1/bin/clang++ -isystem
/usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0 -isystem
/usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/x86_64-apple-darwin18.7.0
-isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/backward -L
/usr/local/Cellar/gcc@7/7.5.0/lib/gcc/7 -nostdinc++ -stdlib=libstdc++
-std=c++17  -femulated-tls -lgcc_s.1 example.cpp -o example


I would still like to know whether the change to _GLIBCXX_HAVE_TLS was
intentional, though.


On Wed, 8 Jan 2020 at 01:42, Dave Gittins <dave.gittins@gmail.com> wrote:
>
> Homebrew package maintainers suggested the change for gcc 7.5.0
> originated with the gcc source. I believe they're saying that the gcc
> source will now define _GLIBCXX_HAVE_TLS to 1 by default on OSX.
> Please can anyone confirm if this is true / intended?
>
> If it *is* intended I will have to dig further into why my clang build
> against that std lib now seg faults.
>
>
> On Thu, 19 Dec 2019 at 17:25, Dave Gittins <dave.gittins@gmail.com> wrote:
> >
> > I am having a problem building on OSX with clang, against the gcc
> > standard library (there are project constraints behind why I am doing
> > this). I am using homebrew packages for both clang and gcc. This
> > pattern worked fine until a recent gcc package upgrade and I would at
> > least like to understand better what has happened. I don't believe
> > there's anything wrong in gcc - however, I was hoping someone could
> > help me understand the *intended* situation so I can decide what to
> > do...
> >
> > Here's my example.cpp:
> > #include <mutex>
> > #include <iostream>
> > int main()
> > {
> >     std::once_flag flag;
> >     std::call_once(flag, [](){ std::cout << "Foo\n"; });
> >     return 0;
> > }
> >
> > If I build and run with any of (homebrew) clang 7.1.0, gcc 7.4.0 or
> > gcc 7.5.0, it builds and runs fine:
> > > /usr/local/Cellar/llvm@7/7.1.0_1/bin/clang++ -std=c++17 example.cpp -o example
> > > /usr/local/Cellar/gcc@7/7.4.0_2/bin/g++-7 -std=c++17 example.cpp -o example
> > > /usr/local/Cellar/gcc@7/7.5.0/bin/g++-7 -std=c++17 example.cpp -o example
> >
> > If I build with clang, but link against the gcc 7.4.0 std lib, it also
> > builds and runs fine:
> > > /usr/local/Cellar/llvm@7/7.1.0_1/bin/clang++ -isystem /usr/local/Cellar/gcc@7/7.4.0_2/include/c++/7.4.0 -isystem /usr/local/Cellar/gcc@7/7.4.0_2/include/c++/7.4.0/x86_64-apple-darwin18.5.0 -isystem /usr/local/Cellar/gcc@7/7.4.0_2/include/c++/7.4.0/backward -L /usr/local/Cellar/gcc@7/7.4.0_2/lib/gcc/7 -nostdinc++ -stdlib=libstdc++ -std=c++17 example.cpp -o example
> >
> > In this case, the executable has the following undefined symbols which
> > are provided by the runtime stdc++ library:
> > > nm example | grep __once
> >                  U __ZSt14__once_functor
> >                  U ___once_proxy
> > > nm /usr/local/Cellar/gcc\@7/7.4.0_2/lib/gcc/7/libstdc++.6.dylib | grep __once
> > 0000000000139420 S __ZSt14__once_functor
> > 00000000001357c0 s
> > __ZZN12_GLOBAL__N_127__get_once_functor_lock_ptrEvE23__once_functor_lock_ptr
> > 00000000001354b0 d
> > __ZZN9__gnu_cxx18__common_pool_baseINS_6__poolELb1EE18_S_initialize_onceEvE6__once
> > 00000000000bb590 T ___once_proxy
> >
> > However, if I now upgrade my homebrew gcc package to 7.5.0, things
> > change. I see that in this new version, _GLIBCXX_HAVE_TLS is #defined
> > as 1 in c++config.h (where previously it was undefined). Building with
> > gcc, <mutex> is now using __once_call and we link to the emulated TLS
> > versions from the standard library:
> > > /usr/local/Cellar/gcc@7/7.5.0/bin/g++-7 -std=c++17 example.cpp -o example
> > > nm example | grep __once
> >                  U ___emutls_v._ZSt11__once_call
> >                  U ___emutls_v._ZSt15__once_callable
> >                  U ___once_proxy
> > > nm /usr/local/Cellar/gcc\@7/7.5.0/lib/gcc/7/libstdc++.6.dylib | grep __once
> > 0000000000135160 d
> > __ZZN9__gnu_cxx18__common_pool_baseINS_6__poolELb1EE18_S_initialize_onceEvE6__once
> > 00000000001357a0 D ___emutls_v._ZSt11__once_call
> > 0000000000135780 D ___emutls_v._ZSt15__once_callable
> > 00000000000b7f90 T ___once_proxy
> >
> >
> > However, if I build with clang, I get unresolved symbols - the
> > compiler emits an object file that depends on _ZSt11__once_call,
> > instead of ___emutls_v._ZSt11__once_call:
> > > /usr/local/Cellar/llvm@7/7.1.0_1/bin/clang++ -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0 -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/x86_64-apple-darwin18.7.0 -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/backward -L /usr/local/Cellar/gcc@7/7.5.0/lib/gcc/7 -nostdinc++ -stdlib=libstdc++ -std=c++17 example.cpp -o example
> > Undefined symbols for architecture x86_64:
> >   "std::__once_call", referenced from:
> >       void std::call_once<main::$_0>(std::once_flag&, main::$_0&&) in
> > example-cba81f.o
> >   "std::__once_callable", referenced from:
> >       void std::call_once<main::$_0>(std::once_flag&, main::$_0&&) in
> > example-cba81f.o
> >       void std::call_once<main::$_0>(std::once_flag&,
> > main::$_0&&)::'lambda0'()::operator()() const in example-cba81f.o
> > ld: symbol(s) not found for architecture x86_64
> > clang-7: error: linker command failed with exit code 1 (use -v to see
> > invocation)
> >
> > I thought maybe I could fix this by adding -femulated-tls. This seems
> > to cause the compiler to link to the correct symbol name in the
> > standard lib, but it segfaults at runtime when calling call_once:
> > > /usr/local/Cellar/llvm@7/7.1.0_1/bin/clang++ -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0 -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/x86_64-apple-darwin18.7.0 -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/backward -L /usr/local/Cellar/gcc@7/7.5.0/lib/gcc/7 -nostdinc++ -stdlib=libstdc++ -std=c++17 example.cpp -o example -femulated-tls
> > > ./example
> > Segmentation fault: 11 (core dumped)
> >
> >
> >
> > I am unclear on the following:
> > 1. Is it valid/sensible to define _GLIBCXX_HAVE_TLS for the gcc build
> > on OSX? I asked this also on the homebrew forum:
> > https://discourse.brew.sh/t/is-it-deliberate-that-the-gcc-7-7-5-formula-now-has-glibcxx-have-tls-defined/6500
> > 2. Is there any performance or functionality reason to force the
> > decision on whether this should be defined or not?
> > 3. Given that it works if I build with gcc 7.5.0 against its own std
> > lib, why does the clang build with -femulated-tls segfault?
> >
> >
> > As I said above I realise this is an issue with how these compiler
> > packages are being built and what I am trying to do with them, not a
> > gcc problem - and it may just be unsupported. However I would be very
> > appreciative of any insight on my above questions or suggestions of
> > where to go from here.
> >
> > Dave



More information about the Gcc-help mailing list