Current clang generates references to __aeabi_read_tp for arm target under -fpie. It generates references to __tls_get_addr under -fPIC, and no special library reference under -fpie for x86 target. The reference to __aeabi_read_tp caused link time error because Android run-time library does not have this function yet. Gcc for arm target generates references to __emutls_get_address under -fpie or -fPIC. Is there any clang arm target configuration flag to generate for -fpie references to __tls_get_addr or __emutls_get_address, or no external reference at all? This will allow existing AOSP upstream projects to continue using -fpie, instead of -fPIC or waiting for an upgrade of AOSP library. The folloing is a test case reduced from Android Open Source external/fio/gettime.c It shows that reference to __aeabi_read_tp is used only for arm -fpie, not for -fPIC or x86. $ cat g.i.c struct mytimeval { int tv_sec; int tv_usec; }; struct tv_valid { struct mytimeval last_tv; int last_tv_valid; }; extern __thread struct tv_valid static_tv_valid; void fio_gettime(struct mytimeval *tp) { struct tv_valid *tv = &static_tv_valid; if (tv) { if (tv->last_tv_valid) tp->tv_sec = tv->last_tv.tv_sec; tv->last_tv_valid = 1; } } $ clang -fpie g.i.c -c -o /tmp/c.x86.pie.o $ clang -fPIC g.i.c -c -o /tmp/c.x86.PIC.o $ clang -target arm-linux-androideabi -fpie g.i.c -c -o /tmp/c.pie.o $ clang -target arm-linux-androideabi -fPIC g.i.c -c -o /tmp/c.PIC.o $ nm /tmp/c.x86.pie.o | grep -E 'aeabi_read|tls_' $ nm /tmp/c.x86.PIC.o | grep -E 'aeabi_read|tls_' U __tls_get_addr $ nm /tmp/c.pie.o | grep -E 'aeabi_read|tls_' U __aeabi_read_tp $ nm /tmp/c.PIC.o | grep -E 'aeabi_read|tls_' U __tls_get_addr
The problem with __aeabi_read_tp function is that it uses fixed offset for everything. This leads to number of problems starting with 1) It currently starts at errno slot __aeabi_read_tp() + 8 2) It does not support having thread_local variable in more than one dso (they end up sharing offsets and will overwrite each-other values) 3) It may run out of boundaries of the tls buffer, if number of thread_locals is big enough. And there is no way for libc to catch this (because of compiled in offsets which do not get passed to __aeabi_read_tp). I think the best way to solve this is to always use __tls_get_addr(), or in case of emulated tls (which llvm does not yet support afaik) - translate thread_locals to pthread_keycreate() and co calls.
To make thread local storage work with current Android run-time, llvm should do as gcc does now. Emulated tls mode is when __thread/thread_local are translated to appropriate calls to pthread_key_create/getspecific/setspecific().
First draft implementation to review at http://reviews.llvm.org/D10522 and http://reviews.llvm.org/D10524
Current llvm supports ELF TLS as described in http://www.akkadia.org/drepper/tls.pdf However, Android dynamic linker does not handle the ELF TLS models yet. Android has GCC emutls library to support the emulated TLS code generated by gcc. Before Android linker can handle the ELF TLS models and devices upgraded to a new linker, clang/llvm users would need to use compatible emutls model. The patch in http://reviews.llvm.org/D10524 adds a new flag -ftls-model=emulated in clang to generate the "emultated" TLS model attribute, and patch http://reviews.llvm.org/D10524 added to llvm to generate the compatible function calls and control variables to link with libgcc's emutls. See https://github.com/gcc-mirror/gcc/blob/master/libgcc/emutls.c
Should have been fixed with changes up to r243475.