Emulated TLS for Android
Joakim via digitalmars-d-ldc
digitalmars-d-ldc at puremagic.com
Thu Jul 6 04:13:20 PDT 2017
So I've finally spent some time looking at this, ie what work
google did to get a gcc-alike emulated TLS into llvm, since
they've ditched the gcc compiler from their Native Development
Kit (NDK):
https://reviews.llvm.org/D10522
https://bugs.llvm.org/show_bug.cgi?id=23566
https://android.googlesource.com/platform/ndk/+/ndk-r15-release/CHANGELOG.md
It simply modifies llvm to call __emutls_get_address from libgcc
(a library the NDK still supplies) anytime your code accesses a
thread-local variable, but there's no hook in
__emutls_get_address that I can use to register that data with
the D GC:
https://github.com/gcc-mirror/gcc/blob/master/libgcc/emutls.c#L127
I can compile and run much D code fine with llvm's emulated TLS-
all of druntime's tests pass- but start having problems because
it's not registered with the GC, a dozen or so Phobos modules'
tests fail or segfault in somewhat random ways.
Three ways to fix this come to mind:
1. Intercept all calls to thread-local variables at runtime and
make sure they're registered with the GC, ie by inserting some
registering function after __emutls_get_address. This would
require deeper knowledge of ldc and llvm than I have, one of you
would probably have to do it. Also, we'd now be depending on
libgcc for its emulated TLS, ie another dependency.
2. Intercept __emutls_get_address when linking and replace it
with our own implementation, rather than depending on libgcc's
version. This can be done, I tried it with an empty function. A
drawback is that it appears that you don't know how large the
emulated thread-local data section will be, which I think is why
they keep extending it in the libgcc implementation linked above.
3. Modify my llvm patch that keeps TLS data where it is in other
platforms, ie .tdata/.tbss, but removes the SHF_TLS/STT_TLS ELF
flags, adds section delimiting symbols _tlsstart and _tlsend, and
replaces the TLS relocation with a normal one (pretty much
Walter's emulated TLS for OS X:
https://gist.github.com/joakim-noah/1fb23fba1ba5b7e87e1a), so
that it is enabled for Android behind a runtime flag and apply it
to our llvm source before building it.
Initially it'd only have to be for releases, but if we get an
Android CI going, it'd have to be applied for that too. Because
_tlsstart is applied for the module with main, that object has to
be linked first.
I'm leaning towards 3., it's the easiest and I'm not too keen on
how the libgcc version works.
Since 3. will require patching our llvm, let me know what you
think we should do.
With this last change, ldc will have Android cross-compilation
support from every platform that's part of the official release.
Until we get some way to generate a cross-compiled stdlib from
the compiler and accompanying source, I can put up a tarfile with
the cross-compiled stdlib for Android, though they'll need the
NDK for their platform for its native Android libraries and
linker.
More information about the digitalmars-d-ldc
mailing list