diff options
| author | Hyang-Ah Hana Kim <hyangah@gmail.com> | 2015-10-16 14:04:29 -0400 |
|---|---|---|
| committer | Hyang-Ah Hana Kim <hyangah@gmail.com> | 2015-10-28 20:54:28 +0000 |
| commit | dfc8649854eeb569598cabfbc8e408c3ef07a539 (patch) | |
| tree | e6bbdf35114f9c7382e5ce005d5fb7a5367ab2bc /src/runtime | |
| parent | 80d9106487e451f5de5d4c4e5de97002c33a0363 (diff) | |
| download | go-dfc8649854eeb569598cabfbc8e408c3ef07a539.tar.xz | |
runtime, cmd: TLS setup for android/amd64.
Android linker does not handle TLS for us. We set up the TLS slot
for g, as darwin/386,amd64 handle instead. This is disgusting and
fragile. We will eventually fix this ugly hack by taking advantage
of the recent TLS IE model implementation. (Instead of referencing
an GOT entry, make the code sequence look into the TLS variable that
holds the offset.)
The TLS slot for g in android/amd64 assumes a fixed offset from %fs.
See runtime/cgo/gcc_android_amd64.c for details.
For golang/go#10743
Change-Id: I1a3fc207946c665515f79026a56ea19134ede2dd
Reviewed-on: https://go-review.googlesource.com/15991
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/cgo/gcc_android_amd64.c | 92 | ||||
| -rw-r--r-- | src/runtime/cgo/gcc_linux_amd64.c | 12 | ||||
| -rw-r--r-- | src/runtime/rt0_android_amd64.s | 33 | ||||
| -rw-r--r-- | src/runtime/sys_linux_amd64.s | 8 |
4 files changed, 144 insertions, 1 deletions
diff --git a/src/runtime/cgo/gcc_android_amd64.c b/src/runtime/cgo/gcc_android_amd64.c new file mode 100644 index 0000000000..4cea459748 --- /dev/null +++ b/src/runtime/cgo/gcc_android_amd64.c @@ -0,0 +1,92 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include <string.h> /* for strerror */ +#include <pthread.h> +#include <signal.h> +#include "libcgo.h" + +static void* threadentry(void*); +static pthread_key_t k1; + +#define magic1 (0x23581321345589ULL) + +static void +inittls(void) +{ + uint64 x; + pthread_key_t tofree[128], k; + int i, ntofree; + + /* + * Same logic, code as gcc_darwin_386.c:/inittls. + * Note that this is a temporary hack that should be fixed soon. + * Android-L and M bionic's pthread implementation differ + * significantly, and can change any time. + * https://android-review.googlesource.com/#/c/134202 + * + * We chose %fs:0x1d0 which seems to work in testing with Android + * emulators (API22, API23) but it may break any time. + * + * TODO: fix this. + * + * The linker and runtime hard-code this constant offset + * from %fs where we expect to find g. Disgusting. + * + * Known to src/cmd/link/internal/ld/sym.go:/0x1d0 + * and to src/runtime/sys_linux_amd64.s:/0x1d0 or /GOOS_android. + * + * As disgusting as on the darwin/386, darwin/amd64. + */ + ntofree = 0; + for(;;) { + if(pthread_key_create(&k, nil) < 0) { + fprintf(stderr, "runtime/cgo: pthread_key_create failed\n"); + abort(); + } + pthread_setspecific(k, (void*)magic1); + asm volatile("movq %%fs:0x1d0, %0" : "=r"(x)); + pthread_setspecific(k, 0); + if(x == magic1) { + k1 = k; + break; + } + if(ntofree >= nelem(tofree)) { + fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n"); + fprintf(stderr, "\ttried"); + for(i=0; i<ntofree; i++) + fprintf(stderr, " %#x", (unsigned)tofree[i]); + fprintf(stderr, "\n"); + abort(); + } + tofree[ntofree++] = k; + } + // TODO: output to stderr is not useful for apps. + // Can we fall back to Android's log library? + + /* + * We got the key we wanted. Free the others. + */ + for(i=0; i<ntofree; i++) { + pthread_key_delete(tofree[i]); + } +} + + +static void* +threadentry(void *v) +{ + ThreadStart ts; + + ts = *(ThreadStart*)v; + free(v); + + pthread_setspecific(k1, (void*)ts.g); + + crosscall_amd64(ts.fn); + return nil; +} + +void (*x_cgo_inittls)(void) = inittls; +void* (*x_cgo_threadentry)(void*) = threadentry; diff --git a/src/runtime/cgo/gcc_linux_amd64.c b/src/runtime/cgo/gcc_linux_amd64.c index c93cacd744..51ca6446cf 100644 --- a/src/runtime/cgo/gcc_linux_amd64.c +++ b/src/runtime/cgo/gcc_linux_amd64.c @@ -12,6 +12,10 @@ static void* threadentry(void*); static void (*setg_gcc)(void*); +// These will be set in gcc_android_amd64.c for android-specific customization. +void (*x_cgo_inittls)(void); +void* (*x_cgo_threadentry)(void*); + void x_cgo_init(G* g, void (*setg)(void*)) { @@ -43,6 +47,10 @@ x_cgo_init(G* g, void (*setg)(void*)) g->stacklo = (uintptr)&size - size + 4096; pthread_attr_destroy(attr); free(attr); + + if (x_cgo_inittls) { + x_cgo_inittls(); + } } @@ -74,6 +82,10 @@ _cgo_sys_thread_start(ThreadStart *ts) static void* threadentry(void *v) { + if (x_cgo_threadentry) { + return x_cgo_threadentry(v); + } + ThreadStart ts; ts = *(ThreadStart*)v; diff --git a/src/runtime/rt0_android_amd64.s b/src/runtime/rt0_android_amd64.s new file mode 100644 index 0000000000..9af6cab16f --- /dev/null +++ b/src/runtime/rt0_android_amd64.s @@ -0,0 +1,33 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +TEXT _rt0_amd64_android(SB),NOSPLIT,$-8 + MOVQ 0(SP), DI // argc + LEAQ 8(SP), SI // argv + MOVQ $main(SB), AX + JMP AX + +TEXT _rt0_amd64_android_lib(SB),NOSPLIT,$0 + MOVQ $1, DI // argc + MOVQ $_rt0_amd64_android_argv(SB), SI // argv + MOVQ $_rt0_amd64_linux_lib(SB), AX + JMP AX + +DATA _rt0_amd64_android_argv+0x00(SB)/8,$_rt0_amd64_android_argv0(SB) +DATA _rt0_amd64_android_argv+0x08(SB)/8,$0 +DATA _rt0_amd64_android_argv+0x10(SB)/8,$0 +DATA _rt0_amd64_android_argv+0x18(SB)/8,$15 // AT_PLATFORM +DATA _rt0_amd64_android_argv+0x20(SB)/8,$_rt0_amd64_android_auxv0(SB) +DATA _rt0_amd64_android_argv+0x28(SB)/8,$0 +GLOBL _rt0_amd64_android_argv(SB),NOPTR,$0x30 + +// TODO: AT_HWCAP necessary? If so, what value? + +DATA _rt0_amd64_android_argv0(SB)/8, $"gojni" +GLOBL _rt0_amd64_android_argv0(SB),RODATA,$8 + +DATA _rt0_amd64_android_auxv0(SB)/8, $"x86_64" +GLOBL _rt0_amd64_android_auxv0(SB),RODATA,$8 diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index df72a77afc..aed85cb0aa 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -371,8 +371,14 @@ TEXT runtimeĀ·sigaltstack(SB),NOSPLIT,$-8 // set tls base to DI TEXT runtimeĀ·settls(SB),NOSPLIT,$32 +#ifdef GOOS_android + // Same as in sys_darwin_386.s:/ugliness, different constant. + // DI currently holds m->tls, which must be fs:0x1d0. + // See cgo/gcc_android_amd64.c for the derivation of the constant. + SUBQ $0x1d0, DI // In android, the tls base +#else ADDQ $8, DI // ELF wants to use -8(FS) - +#endif MOVQ DI, SI MOVQ $0x1002, DI // ARCH_SET_FS MOVQ $158, AX // arch_prctl |
