Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.14.1 unresolvable R_X86_64_TPOFF32 relocation #3221

Open
Oipo opened this issue Oct 16, 2024 · 6 comments
Open

1.14.1 unresolvable R_X86_64_TPOFF32 relocation #3221

Oipo opened this issue Oct 16, 2024 · 6 comments

Comments

@Oipo
Copy link

Oipo commented Oct 16, 2024

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

@tt4g
Copy link
Contributor

tt4g commented Oct 16, 2024

It doesn't look like the spdlog symbol, maybe you should ask the question in the GCC or Ubuntu community.

@tt4g
Copy link
Contributor

tt4g commented Oct 17, 2024

Maybe duplicate #1405

Oipo added a commit to volt-software/Ichor that referenced this issue Oct 17, 2024
@Oipo
Copy link
Author

Oipo commented Oct 17, 2024

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.

@tt4g
Copy link
Contributor

tt4g commented Oct 17, 2024

-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.

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

@Oipo
Copy link
Author

Oipo commented Oct 17, 2024

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

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 access thread_local variables
  • Refactor the std::promise/std::future to a std::function of sorts.
  • Patch out the specific commit in my own fork

@tt4g
Copy link
Contributor

tt4g commented Oct 17, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants