From df553e646c597ab7fb26e3ffa2b730c04ab069f8 Mon Sep 17 00:00:00 2001 From: Hyang-Ah Hana Kim Date: Thu, 5 Nov 2015 16:32:27 -0500 Subject: [PATCH 1/4] cmd,runtime: TLS setup for android/386 Same ugly hack as https://go-review.googlesource.com/15991. Update golang/go#9327. Change-Id: I58284e83268a15de95eabc833c3e01bf1e3faa2e --- src/cmd/internal/obj/x86/asm6.go | 3 ++ src/cmd/link/internal/ld/sym.go | 15 +++++-- src/runtime/cgo/gcc_android_386.c | 87 +++++++++++++++++++++++++++++++++++++++ src/runtime/cgo/gcc_linux_386.c | 12 ++++++ src/runtime/rt0_android_386.s | 39 ++++++++++++++++++ src/runtime/sys_linux_386.s | 10 +++++ 6 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 src/runtime/cgo/gcc_android_386.c create mode 100644 src/runtime/rt0_android_386.s diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 919e00b..13ab240 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -1975,6 +1975,9 @@ func prefixof(ctxt *obj.Link, p *obj.Prog, a *obj.Addr) int { if p.Mode == 32 { switch ctxt.Headtype { default: + if isAndroid { + return 0x65 // GS + } log.Fatalf("unknown TLS base register for %s", obj.Headstr(ctxt.Headtype)) case obj.Hdarwin, diff --git a/src/cmd/link/internal/ld/sym.go b/src/cmd/link/internal/ld/sym.go index da5776d..d91f138 100644 --- a/src/cmd/link/internal/ld/sym.go +++ b/src/cmd/link/internal/ld/sym.go @@ -102,10 +102,17 @@ func linknew(arch *LinkArch) *Link { obj.Hopenbsd, obj.Hdragonfly, obj.Hsolaris: - 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 + if obj.Getgoos() == "android" { + switch ctxt.Arch.Thechar { + case '6': + // Android/x86 constant - offset from 0(FS) to our + // TLS slot. Explained in src/runtime/cgo/gcc_android_*.c + ctxt.Tlsoffset = 0x1d0 + case '8': + ctxt.Tlsoffset = 0xf8 + default: + ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize + } } else { ctxt.Tlsoffset = -1 * ctxt.Arch.Ptrsize } diff --git a/src/runtime/cgo/gcc_android_386.c b/src/runtime/cgo/gcc_android_386.c new file mode 100644 index 0000000..a82d7d0 --- /dev/null +++ b/src/runtime/cgo/gcc_android_386.c @@ -0,0 +1,87 @@ +// 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 /* for strerror */ +#include +#include +#include "libcgo.h" + +static void* threadentry(void*); +static pthread_key_t k1; + +#define magic1 (0x23581321U) + +static void +inittls(void) +{ + uint32 x; + pthread_key_t tofree[128], k; + int i, ntofree; + + /* + * Same logic, code as gcc_android_amd64.c:/inittls. + * Note that this is a temporary hack that should be fixed soon. + * + * TODO: fix this. + * + * The linker and runtime hard-code this constant offset + * from %gs where we expect to find g. Disgusting. + * + * Known to src/cmd/link/internal/ld/sym.go:/0xf8 + * and to src/runtime/sys_linux_386.s:/0xf8 or /GOOS_android. + * TODO(hyangah): check 0xb0 works with API23+ + * + * 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("movl %%gs:0xf8, %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; istacklo = (uintptr)&attr - size + 4096; pthread_attr_destroy(&attr); + + if (x_cgo_inittls) { + x_cgo_inittls(); + } } @@ -57,6 +65,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_386.s b/src/runtime/rt0_android_386.s new file mode 100644 index 0000000..bf44af3 --- /dev/null +++ b/src/runtime/rt0_android_386.s @@ -0,0 +1,39 @@ +// 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_386_android(SB),NOSPLIT,$8 + MOVL 8(SP), AX // argc + LEAL 12(SP), BX // argv + MOVL AX, 0(SP) + MOVL BX, 4(SP) + CALL main(SB) + INT $3 + +TEXT _rt0_386_android_lib(SB),NOSPLIT,$0 + PUSHL $_rt0_386_android_argv(SB) // argv + PUSHL $1 // argc + CALL _rt0_386_linux_lib(SB) + POPL AX + POPL AX + RET + +DATA _rt0_386_android_argv+0x00(SB)/4,$_rt0_386_android_argv0(SB) +DATA _rt0_386_android_argv+0x04(SB)/4,$0 +DATA _rt0_386_android_argv+0x08(SB)/4,$0 +DATA _rt0_386_android_argv+0x0c(SB)/4,$15 // AT_PLATFORM (auxvec.h) +DATA _rt0_386_android_argv+0x10(SB)/4,$_rt0_386_android_auxv0(SB) +DATA _rt0_386_android_argv+0x14(SB)/4,$0 +DATA _rt0_386_android_argv+0x18(SB)/4,$0 +DATA _rt0_386_android_argv+0x1c(SB)/4,$0 +GLOBL _rt0_386_android_argv(SB),NOPTR,$0x20 + +// TODO: AT_HWCAP necessary? If so, what value? + +DATA _rt0_386_android_argv0(SB)/8, $"gojni" +GLOBL _rt0_386_android_argv0(SB),RODATA,$8 + +DATA _rt0_386_android_auxv0(SB)/8, $"i386" +GLOBL _rt0_386_android_auxv0(SB),RODATA,$8 diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s index 9e0e87c..a52c4b2 100644 --- a/src/runtime/sys_linux_386.s +++ b/src/runtime/sys_linux_386.s @@ -405,6 +405,15 @@ TEXT runtime·setldt(SB),NOSPLIT,$32 MOVL entry+0(FP), BX // entry MOVL address+4(FP), CX // base address +#ifdef GOOS_android + /* + * Same as in sys_darwin_386.s:/ugliness, different constant. + * address currently holds m->tls, which must be %gs:0xf8. + * See cgo/gcc_android_386.c for the derivation of the constant. + */ + SUBL $0xf8, CX + MOVL CX, 0(CX) +#else /* * When linking against the system libraries, * we use its pthread_create and let it set up %gs @@ -420,6 +429,7 @@ TEXT runtime·setldt(SB),NOSPLIT,$32 */ ADDL $0x4, CX // address MOVL CX, 0(CX) +#endif // set up user_desc LEAL 16(SP), AX // struct user_desc -- 2.5.2