1.14.1 unresolvable R_X86_64_TPOFF32 relocation
Updating spdlog to 1.14.1, I get the following linker error:
/usr/bin/c++ -Wno-maybe-uninitialized -ggdb -O3 -DNDEBUG -pie -Wl,-z,nodlopen -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--no-copy-dt-needed-entries test/CMakeFiles/EtcdTests.dir/EtcdTests.cpp.o -o /opt/ichor/src/bin/EtcdTests /opt/ichor/src/bin/libichor.a /opt/ichor/src/bin/libCatch2Main.a -lsystemd /usr/lib/libboost_coroutine.a /usr/lib/libboost_fiber.a /usr/lib/libboost_context.a /usr/lib/libboost_filesystem.a /usr/lib/libssl.a /usr/lib/libcrypto.a -ldl -lhiredis -ldl -lrt /opt/ichor/src/bin/libCatch2.a && :
/usr/bin/ld: /opt/ichor/src/bin/libichor.a(async.cpp.o)(.text+0x266e): unresolvable R_X86_64_TPOFF32 relocation against symbol `_ZSt15__once_callable@@GLIBCXX_3.4.11'
This doesn't happen with 1.13.0, or when ftls-model=local-exec is removed from the compiler flags.
Compiler: gcc 12.3.0
Linux: Ubuntu Jammy
cxxflags: -O2 -std=c++20 -fpie -fstack-protector-strong -fcf-protection -fstack-clash-protection -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST -ftls-model=local-exec
linkflags: -ggdb -O3 -DNDEBUG -pie -Wl,-z,nodlopen -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -Wl,--no-copy-dt-needed-entries
It doesn't look like the spdlog symbol, maybe you should ask the question in the GCC or Ubuntu community.
Maybe duplicate #1405
It doesn't look like the spdlog symbol, maybe you should ask the question in the GCC or Ubuntu community.
once_callable is likely a thread_local related symbol, which glibc uses. The error shows that this happens in async.cpp, which includes a bunch of spdlog related files.
Maybe duplicate #1405
-fPIC didn't change anything, which is because I'm not creating or linking into a shared library. Instead, I'm making a PIE executable with the PIE static library. Regardless, I'll bisect it later.
-fPICdidn't change anything, which is because I'm not creating or linking into a shared library. Instead, I'm making a PIE executable with the PIE static library. Regardless, I'll bisect it later.
As far as I know, the -fPIC option causes relocation problems when using the static library: c++ - "relocation R_X86_64_32S against " linking Error - Stack Overflow
As far as I know, the
-fPICoption causes relocation problems when using the static library: c++ - "relocation R_X86_64_32S against " linking Error - Stack Overflow
Your linked stackoverflow is saying the same thing as I am. As long as the end result is a dynamic library (either directly, or by first creating a static library which is then linked into a dynamic library), -fPIC is useful. This can also be gleaned from the gcc manual:
Generate position-independent code (PIC) suitable for use in a shared library ...
However, I am not creating a shared library anywhere in my workflow. I make a static library and link it directly into an executable. Therefore, I use -fpie (since my GOT tables aren't too big to need to use -fPIE) and -fPIC has no effect on the problem at hand. I know, because I've added it to the compiler flags and it resulted in the same error I mentioned above.
I have bisected the problem to 6725584e27ca93f50527165696d7cf34e3978373. And specifically, the call to set_value() in thread_pool-inl.h:115.
promise<>::set_value() ends up calling std::call_once, which requires thread local storage and GCC requires the glibcxx once_callable symbol (which is probably some pthread_once alias). ftls-model=local-exec disables the usage of thread_local storage which has not been defined inside the executable itself. And the once_callable symbol resides in libc.so.6.
On top of that, unfortunately, gcc has had a pretty bad bug with std::call_once and exceptions since gcc 5.x, making it impossible to support handling exceptions during a std::call_once call on musl and other non-glibc, non-x86 targets. Not the case here, but certainly something to consider.
The options I see are as follows:
- Change compiler flags to
ftls-model=initial-exec, losing some performance whenever I accessthread_localvariables - Refactor the
std::promise/std::futureto astd::functionof sorts. - Patch out the specific commit in my own fork
Thanks for the accurate investigation.
I had never heard of the std::call_once bug in GCC.
It would be helpful if you could send the PR.
Sure, I'll take a stab when I have some free time. It would likely be a backwards incompatible change though. Or should I put in a #ifdef to control the function signature?
Personally, I think it is a bug and should be fixed even if it is not compatible. However, I am not this repository maintainer, so the final decision is up to @gabime.