richfelker / musl-cross-make

Simple makefile-based build for musl cross compiler
MIT License
1.29k stars 266 forks source link

undefined reference to `std::__atomic_futex_unsigned_base` #79

Open ldanko opened 4 years ago

ldanko commented 4 years ago

Hi, Not sure it this is musl-cross-make bug or gcc bug, but on arm-linux-musleabihf (I think the same is for other arm builds) at least two symbols are missing from libstdc++:

  1. undefined reference to `std::__atomic_futex_unsigned_base::_M_futex_notify_all(unsigned int*)'
  2. undefined reference to `std::__atomic_futex_unsigned_base::_M_futex_wait_until(unsigned int*, unsigned int, bool, std::chrono::duration<long long, std::ratio<1ll, 1ll> >, std::chrono::duration<long long, std::ratio<1ll, 1000000000ll> >)'

On x86_64 build both symbols are available:

$ nm x86_64-linux-musl/lib/libstdc++.so.6.0.25 | grep futex
00000000000bbf40 T _ZNSt28__atomic_futex_unsigned_base19_M_futex_notify_allEPj
00000000000bbe50 T _ZNSt28__atomic_futex_unsigned_base19_M_futex_wait_untilEPjjbNSt6chrono8durationIlSt5ratioILl1ELl1EEEENS2_IlS3_ILl1ELl1000000000EEEE

On arm:

$ nm arm-linux-musleabihf/lib/libstdc++.so.6.0.25 | grep futex

returns nothing.

richfelker commented 4 years ago

What command gave you those errors as output? Are you sure these symbols are supposed to exist?

ldanko commented 4 years ago

I was building some application based on Boost Asio.

It seems that the issue is caused by two macros _GLIBCXX_HAS_GTHREADS and _GLIBCXX_USE_C99_STDINT_TR1 (from bits/c++config.h), undefined at compile time but defined after compilation.

When building the toolchain contents of libstdc++-v3/src/c++11/futex.cc is not compiled because it's hidden behind

#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)

But when I try to use the toolchain both macros are defined and libstdc++-v3/include/bits/atomic_futex.h uses implementation which is not compiled.

See libstdc++-v3/include/bits/atomic_futex.h and libstdc++-v3/src/c++11/futex.cc for more details.

I'm not sure if those symbols are supposed to exists, but if not, both macros should be undefined.

richfelker commented 4 years ago

Can you check the config.log in the libstdc++ build dir to see if it looks like it did anything weird here?

ldanko commented 4 years ago

I don't see anything weird, but there is 12k lines of log. Both macros seems to be defined:

#define _GLIBCXX_USE_C99_STDINT_TR1 1
...
#define _GLIBCXX_HAS_GTHREADS 1

musl-cross-make/build/local/arm-linux-musleabihf/obj_gcc/arm-linux-musleabihf/libstdc++-v3/config.log

richfelker commented 4 years ago

I don't see anything wrong from config.log...

ldanko commented 4 years ago

Ahh, sorry. There are two lines of ifdefs in futex.cc.

#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)      
#if defined(_GLIBCXX_HAVE_LINUX_FUTEX) && ATOMIC_INT_LOCK_FREE > 1

The issue is with ATOMIC_INT_LOCK_FREE.

richfelker commented 4 years ago

Uhg, does it somehow not know how to do atomics on baseline arm (linux kuser_helper)?

ldanko commented 4 years ago

On Arm atomics support depends on architecture version, so for example building with -march=armv4 will set ATOMIC_INT_LOCK_FREE to 1, but building with -march=armv6 will set ATOMIC_INT_LOCK_FREE to 2.

It looks like the default is some low architecture version, so libstdc++ was build with ATOMIC_INT_LOCK_FREE. I was compiling my project with -march=armv7-a, so contents of the libstdc++-v3/include/bits/atomic_futex.h header didn't match.

ldanko commented 4 years ago

Rebuilded the toolchain with settings matching my CPU

GCC_CONFIG += --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard
GCC_CONFIG += --enable-cxx-flags='-march=armv7-a -mtune=cortex-a9 -mfloat-abi=hard -mfpu=vfpv3-d16'

Now everything works fine.

richfelker commented 4 years ago

This is a real bug in upstream GCC that we should patch. I'm not sure when I'll get to it, but here's a note to self to do it. By default GCC defines the ATOMIC_*_LOCK_FREE macros automatically based on presence of atomic insn patterns for the configured arch profile. A few archs override this correctly to indicate that libgcc necessarily provides atomic library functions if there is no insn pattern. See for example gcc/config/pa/pa-linux.h. ARM should do the same.

Rubber1Duck commented 1 year ago

Rebuilded the toolchain with settings matching my CPU

GCC_CONFIG += --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard
GCC_CONFIG += --enable-cxx-flags='-march=armv7-a -mtune=cortex-a9 -mfloat-abi=hard -mfpu=vfpv3-d16'

Now everything works fine.

@ldanko do you have a working solution for armv6 also?

ldanko commented 1 year ago

@Rubber1Duck I've never had to work on armv6.

Rubber1Duck commented 1 year ago

@Rubber1Duck I've never had to work on armv6.

thanks for your answer!