}
}
+var isAndroid = (obj.Getgoos() == "android")
+
func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int {
if a.Reg < REG_CS && a.Index < REG_CS { // fast path
return 0
log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype))
case obj.Hlinux:
+ if isAndroid {
+ return 0x64 // FS
+ }
+
if ctxt.Flag_shared != 0 {
log.Fatalf("unknown TLS base register for linux with -shared")
} else {
)
func canuse1insntls(ctxt *obj.Link) bool {
+ if isAndroid {
+ // For android, we use a disgusting hack that assumes
+ // the thread-local storage slot for g is allocated
+ // using pthread_key_create with a fixed offset
+ // (see src/runtime/cgo/gcc_android_amd64.c).
+ // This makes access to the TLS storage (for g) doable
+ // with 1 instruction.
+ return true
+ }
+
if ctxt.Arch.Regsize == 4 {
switch ctxt.Headtype {
case obj.Hlinux,
}
case obj.R_TLS_LE:
- if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
+ isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8')
+
+ if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 {
r.Done = 0
if r.Sym == nil {
r.Sym = Ctxt.Tlsg
// related to the fact that our own TLS storage happens
// to take up 8 bytes.
o = 8 + r.Sym.Value
- } else if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin {
+ } else if Iself || Ctxt.Headtype == obj.Hplan9 || Ctxt.Headtype == obj.Hdarwin || isAndroidX86 {
o = int64(Ctxt.Tlsoffset) + r.Add
} else if Ctxt.Headtype == obj.Hwindows {
o = r.Add
}
case obj.R_TLS_IE:
- if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd {
+ isAndroidX86 := goos == "android" && (Thearch.Thechar == '6' || Thearch.Thechar == '8')
+
+ if Linkmode == LinkExternal && Iself && HEADTYPE != obj.Hopenbsd && !isAndroidX86 {
r.Done = 0
if r.Sym == nil {
r.Sym = Ctxt.Tlsg
obj.Hopenbsd,
obj.Hdragonfly,
obj.Hsolaris:
- ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+ if obj.Getgoos() == "android" && ctxt.Arch.Thechar == '6' {
+ // Android/x86 constant - offset from 0(FS) to our
+ // TLS slot. Explained in src/runtime/cgo/gcc_android_*.c
+ ctxt.Tlsoffset = 0x1d0
+ } else {
+ ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize
+ }
case obj.Hnacl:
switch ctxt.Arch.Thechar {
/*
* OS X system constants - offset from 0(GS) to our TLS.
- * Explained in ../../runtime/cgo/gcc_darwin_*.c.
+ * Explained in src/runtime/cgo/gcc_darwin_*.c.
*/
case obj.Hdarwin:
switch ctxt.Arch.Thechar {
--- /dev/null
+// 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;
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*))
{
g->stacklo = (uintptr)&size - size + 4096;
pthread_attr_destroy(attr);
free(attr);
+
+ if (x_cgo_inittls) {
+ x_cgo_inittls();
+ }
}
static void*
threadentry(void *v)
{
+ if (x_cgo_threadentry) {
+ return x_cgo_threadentry(v);
+ }
+
ThreadStart ts;
ts = *(ThreadStart*)v;
--- /dev/null
+// 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
// 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