Project

General

Profile

Bug #912

cannot locate symbol "___tls_get_addr"

Added by Dmitry Moskalchuk over 4 years ago. Updated over 4 years ago.

Status:
Invalid
Priority:
High
Category:
-
Target version:
-
Start date:
03/22/2015
Due date:
% Done:

0%

Estimated time:
CPU Architecture:
x86, x86_64
Host OS:
Toolchain:
clang-3.4, clang-3.5
Android version:
CrystaX Version:

Description

clang-x86 don't support TLS properly, inserting non-existing symbol reference @__tls_get_addr@ into binaries

History

#1

Updated by Dmitry Moskalchuk over 4 years ago

  • Status changed from Open to In Progress

Here is corresponding upstream LLVM bug: https://llvm.org/bugs/show_bug.cgi?id=20243

#2

Updated by Dmitry Moskalchuk over 4 years ago

  • Status changed from In Progress to Invalid

Ok, after some research, here are results.

Thread-local variables require some support from runtime. "Here":http://www.akkadia.org/drepper/tls.pdf is detailed explanation. In two words, both libc and dynamic linker should know about thread-local variables. libc should provide @tls_get_addr@ helper, and dynamic linker should be able to load and properly initialize such binaries, containing thread-local variables inside. None of this is supported on Android. And even though we could workaround absense of @tls_get_addr@ function by adding it to the libcrystax, we can't modify Android dynamic linker, which is part of Android OS and can't be updated without updating of device's firmware.

Taking above into account, we have two interesting questions:

  • why then gcc-compiled binaries works fine?
  • why it only fails for clang-x86 and works fine for clang-arm?

Here are answers:

  • There is emulation of TLS-runtime in gcc, which is used in case if underlying runtime don't support it. It's done in a way not only providing equivalent of __tls_get_addr, but also not changing ELF sections - i.e. such emulation don't require extra support from dynamic linker. Of course, it has price of adding additional wrapper code to be able work with TLS-variables, but it's the only way to do that without requiring support from runtime. And, what is important in context of this issue, gcc can emulate it, but clang - no.
  • In fact, binaries with TLS-variables, compiled by clang, don't work on any Android target - on arm, x86 and mips. The only reason why Boost tests passed on arm, but fails on x86, is "Boost.Asio configuration":https://github.com/boostorg/asio/blob/develop/include/boost/asio/detail/config.hpp#L943. It just erroneously think current target support @__thread@ keyword and enable it's usage. "Here":https://github.com/boostorg/asio/pull/17 is fix for it.

After merging that fix into Boost.Asio upstream the error will gone.

Just for the reference: "here":https://llvm.org/bugs/show_bug.cgi?id=20737 is report that clang don't support emulated tls as gcc do. That ticket is closed as "WONTFIX", so this is clearly LLVM issue.

UPD: I've created another "pull request":https://github.com/chriskohlhoff/asio/pull/58 to standalone ASIO, as suggested by Niall Douglas in Boost.Dev mailing list.

Also available in: Atom PDF