Ken Cunningham via llvm-dev
2018-Dec-07 21:30 UTC
[llvm-dev] using emulated-tls on Darwin 8, 9, 10
Please excuse hobbiest-level question. Darwin 11+ enables thread_local variables using system-level supports. I have an interest in enabling TLS on darwin < 11 using emulated-tls. This can be enabled with a few modest patches: =========================--- a/include/llvm/ADT/Triple.h.orig 2018-10-02 17:38:10.000000000 -0700 +++ b/include/llvm/ADT/Triple.h 2018-10-02 17:38:58.000000000 -0700 @@ -682,7 +682,7 @@ /// Tests whether the target uses emulated TLS as default. bool hasDefaultEmulatedTLS() const { - return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment(); + return isAndroid() || isOSOpenBSD() || isWindowsCygwinEnvironment() || isMacOSXVersionLT(10, 7); } /// @} =========================--- a/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp.orig 2018-10-02 18:31:17.000000000 -0700 +++ b/tools/clang/lib/CodeGen/ItaniumCXXABI.cpp 2018-10-02 18:32:35.000000000 -0700 @@ -2255,7 +2255,7 @@ const char *Name = "__cxa_atexit"; if (TLS) { const llvm::Triple &T = CGF.getTarget().getTriple(); - Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit"; + Name = (T.isOSDarwin() && !T.isMacOSXVersionLT(10, 7)) ? "_tlv_atexit" : "__cxa_thread_atexit"; } // We're assuming that the destructor function is something we can --- a/tools/clang/lib/Basic/Targets/OSTargets.h.orig 2018-10-02 17:14:10.000000000 -0700 +++ b/tools/clang/lib/Basic/Targets/OSTargets.h 2018-10-02 17:14:41.000000000 -0700 @@ -93,7 +93,7 @@ this->TLSSupported = false; if (Triple.isMacOSX()) - this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7); + this->TLSSupported = !Triple.isMacOSXVersionLT(10, 4); else if (Triple.isiOS()) { // 64-bit iOS supported it from 8 onwards, 32-bit device from 9 onwards, // 32-bit simulator from 10 onwards. ========================= and in doing so, when clang links against newer versions of libgcc , thread_local support is available. (In MacPorts, this is done using -stdlib=macports-libstdc++, which links against a new version of libgcc from gcc8). I would like to enable this while using libc++ as well, however. To do this, libc++abi is built with cxa_thread_atexit.cpp added, and emutls.c is built and used in libclang_rt.10.4.a. However I am having an issue wherein the symbol ___emutls_get_address from lilbclang_rt_10.4.a is not visible to libc++abi.dylib at runtime. "___emutls_get_address" is built into clang_rt: $ nm /opt/local/libexec/llvm-5.0/lib/clang/5.0.1/lib/darwin/libclang_rt.10.4.a | grep emu /opt/local/libexec/llvm-5.0/lib/clang/5.0.1/lib/darwin/libclang_rt.10.4.a(emutls.c.o): 0000000000000000 T ___emutls_get_address 00000000000001a0 t _emutls_init 0000000000000210 d _emutls_init_once.once 00000000000001c0 t _emutls_key_destructor 0000000000000220 d _emutls_mutex 00000000000002f8 b _emutls_num_object 0000000000000300 b _emutls_pthread_key The objects appear to be included in the built executables (a simple example using TLS 4.cpp made into "4"), but the symbols are apparently not visible to libc++abi.dylib at runtime. $ nm 4 | grep emu 0000000100007070 t ___emutls_get_address 0000000100009480 d ___emutls_v._ZGVZL18thread_with_accessPvE23counting_function_local 0000000100009400 d ___emutls_v._ZL15counting_static 0000000100009420 d ___emutls_v._ZN12_GLOBAL__N_128counting_anonymous_namespaceE 0000000100009460 d ___emutls_v._ZZL18thread_with_accessPvE23counting_function_local 00000001000094a0 d ___emutls_v.__tls_guard 0000000100009440 d ___emutls_v.counting_extern 0000000100007200 t _emutls_init 00000001000094c0 d _emutls_init_once.once 0000000100007220 t _emutls_key_destructor 00000001000094d0 d _emutls_mutex 0000000100009538 b _emutls_num_object 0000000100009540 b _emutls_pthread_key $ ./4 info: testing pthread_create dyld: lazy symbol binding failed: Symbol not found: ___emutls_get_address Referenced from: /usr/lib/libc++abi.dylib Expected in: flat namespace dyld: Symbol not found: ___emutls_get_address Referenced from: /usr/lib/libc++abi.dylib Expected in: flat namespace Trace/BPT trap Adding -Wl,-flat_namespace does not make the symbols visible. If I try to fix it like this by forcing the symbol to be exported, I get a clue: $ clang++ -std=c++11 -stdlib=libc++ -Wl,-exported_symbol,___emutls_get_address -o 4 4.cpp ld: warning: cannot export hidden symbol ___emutls_get_address from /opt/local/libexec/llvm-5.0/lib/clang/5.0.1/lib/darwin/libclang_rt.osx.a(emutls.c.o) Things do work apparently properly however if I build emutls.c directly into libc++abi.dylib, using a slightly modified version of libcxxabi that includes the emutls.c source file in the build: $ nm libc++abi.kenspecial.20181206.dylib | grep emutls_ 0000000000020054 T ___emutls_get_address 0000000000025458 s ___emutls_t._ZN10__cxxabiv112_GLOBAL__N_15dtorsE 000000000002a270 d ___emutls_v._ZN10__cxxabiv112_GLOBAL__N_111dtors_aliveE 000000000002a290 d ___emutls_v._ZN10__cxxabiv112_GLOBAL__N_15dtorsE 000000000002a2b0 d _emutls_get_index.once 00000000000201c8 t _emutls_init 00000000000201ea t _emutls_key_destructor 000000000002a2c0 d _emutls_mutex 000000000002a360 b _emutls_num_object 000000000002a368 b _emutls_pthread_key and with this modified libc++abi.dylib, all the symbols are found, things work correctly, and all the tests that should pass in the llvm "testit" suite do pass. I presume that the visibility of ___emutls_get_address in libclang_rt.osx.a is being controlled by some mechanism (apple_versioning.c ?). I notice that the library is built with -fvisibility=hidden 1) is my approach here generally reasonable? 2) is there a toggle to allow the ___emutls_get_address symbol in libclang_rt.10.4.a to be made visible to libc++abi.dylib ? Best, Ken
Jacob Carlborg via llvm-dev
2018-Dec-08 12:26 UTC
[llvm-dev] using emulated-tls on Darwin 8, 9, 10
On 2018-12-07 22:30, Ken Cunningham via llvm-dev wrote:> Please excuse hobbiest-level question. > > Darwin 11+ enables thread_local variables using system-level supports. > > I have an interest in enabling TLS on darwin < 11 using emulated-tls.Is anyone still running macOS 10.6 or older? -- /Jacob Carlborg
Ken Cunningham via llvm-dev
2018-Dec-08 16:06 UTC
[llvm-dev] using emulated-tls on Darwin 8, 9, 10
> On 2018-12-07 22:30, Ken Cunningham via llvm-dev wrote: >> Please excuse hobbiest-level question. >> Darwin 11+ enables thread_local variables using system-level supports. >> I have an interest in enabling TLS on darwin < 11 using emulated-tls. > > Is anyone still running macOS 10.6 or older? > > -- > /Jacob Carlborg >[off topic, apologies] Yes, there remains a surprising amount of interest in these systems. MacPorts sees very frequent user tickets about them, many tickets lately about thread_local. All versions of clang/llvm run on 10.5+ Intel systems with minor tweaks, including the latest trunk versions, and this enables almost all current opensource software to be used on these systems. Software (like browsers) geared to these systems see downloads in the low thousands per release. I guess people either have a need for these systems for some software version or workflow, or have otherwise workable hardware that as been obsoleted by newer os requirements. Even PowerPC systems get frequent tickets at MacPorts, and we support them as we can. Some versions of clang will run on PowerPC Macs with workable coverage (in fact the only remaining hole is a persisting issue with a bad address for c++ exceptions being supplied). [/on topic] Making the emutls objects in libclang_rt visible to libcxxabi.dylib at runtime has been a hiccup, tho. It works but seems a shame to hack emutls.c into the libc++abi code when the objects are already sitting there in the executable, but (AFAICT) have the wrong visibility setting to allow use. At present I don't seem to know enough about the underpinnings to see how to change the visibility settings on the emutls objects from libclang_rt when placed into the executable. Appreciate any thoughts on this, thanks for your interest, and sorry for the slight divergence above. Ken (MacPorts dev)