diff options
| author | David Crawshaw <david.crawshaw@zentus.com> | 2014-07-03 16:14:34 -0400 |
|---|---|---|
| committer | David Crawshaw <david.crawshaw@zentus.com> | 2014-07-03 16:14:34 -0400 |
| commit | 12b990ba7d9969987e79d5d1e5e71e50d2cc2c06 (patch) | |
| tree | a4de0aea505bbdb57085fbe304d0f195083dd91e /src/cmd/ld | |
| parent | d3be3daafef4b614fc676c807956047976848c7e (diff) | |
| download | go-12b990ba7d9969987e79d5d1e5e71e50d2cc2c06.tar.xz | |
cmd/go, cmd/ld, runtime, os/user: TLS emulation for android
Based on cl/69170045 by Elias Naur.
There are currently several schemes for acquiring a TLS
slot to save the g register. None of them appear to work
for android. The closest are linux and darwin.
Linux uses a linker TLS relocation. This is not supported
by the android linker.
Darwin uses a fixed offset, and calls pthread_key_create
until it gets the slot it wants. As the runtime loads
late in the android process lifecycle, after an
arbitrary number of other libraries, we cannot rely on
any particular slot being available.
So we call pthread_key_create, take the first slot we are
given, and put it in runtime.tlsg, which we turn into a
regular variable in cmd/ld.
Makes android/arm cgo binaries work.
LGTM=minux
R=elias.naur, minux, dave, josharian
CC=golang-codereviews
https://golang.org/cl/106380043
Diffstat (limited to 'src/cmd/ld')
| -rw-r--r-- | src/cmd/ld/data.c | 4 | ||||
| -rw-r--r-- | src/cmd/ld/elf.c | 3 | ||||
| -rw-r--r-- | src/cmd/ld/lib.c | 4 | ||||
| -rw-r--r-- | src/cmd/ld/pobj.c | 2 | ||||
| -rw-r--r-- | src/cmd/ld/symtab.c | 7 |
5 files changed, 17 insertions, 3 deletions
diff --git a/src/cmd/ld/data.c b/src/cmd/ld/data.c index 03b93c77ce..b2075f2d66 100644 --- a/src/cmd/ld/data.c +++ b/src/cmd/ld/data.c @@ -160,6 +160,10 @@ relocsym(LSym *s) if(r->sym != S && r->sym->type != STLSBSS && !r->sym->reachable) diag("unreachable sym in relocation: %s %s", s->name, r->sym->name); + // Android emulates runtime.tlsg as a regular variable. + if (r->type == R_TLS && strcmp(goos, "android") == 0) + r->type = R_ADDR; + switch(r->type) { default: o = 0; diff --git a/src/cmd/ld/elf.c b/src/cmd/ld/elf.c index 0555cf46aa..3196961f35 100644 --- a/src/cmd/ld/elf.c +++ b/src/cmd/ld/elf.c @@ -776,7 +776,8 @@ elfshbits(Section *sect) if(sect->rwx & 2) sh->flags |= SHF_WRITE; if(strcmp(sect->name, ".tbss") == 0) { - sh->flags |= SHF_TLS; + if(strcmp(goos, "android") != 0) + sh->flags |= SHF_TLS; // no TLS on android sh->type = SHT_NOBITS; } if(linkmode != LinkExternal) diff --git a/src/cmd/ld/lib.c b/src/cmd/ld/lib.c index ef638a66a6..0a5d8d99f2 100644 --- a/src/cmd/ld/lib.c +++ b/src/cmd/ld/lib.c @@ -226,6 +226,10 @@ loadlib(void) linkmode = LinkExternal; else linkmode = LinkInternal; + + // Force external linking for android. + if(strcmp(goos, "android") == 0) + linkmode = LinkExternal; } if(linkmode == LinkInternal) { diff --git a/src/cmd/ld/pobj.c b/src/cmd/ld/pobj.c index 819c37954a..d3a15a7705 100644 --- a/src/cmd/ld/pobj.c +++ b/src/cmd/ld/pobj.c @@ -139,7 +139,7 @@ main(int argc, char *argv[]) if(HEADTYPE == -1) HEADTYPE = headtype(goos); ctxt->headtype = HEADTYPE; - if (headstring == nil) + if(headstring == nil) headstring = headstr(HEADTYPE); archinit(); diff --git a/src/cmd/ld/symtab.c b/src/cmd/ld/symtab.c index 1bc384e805..1805f97d3a 100644 --- a/src/cmd/ld/symtab.c +++ b/src/cmd/ld/symtab.c @@ -204,7 +204,12 @@ asmelfsym(void) diag("missing section for %s", s->name); errorexit(); } - putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0); + if (strcmp(goos, "android") == 0) { + // Android emulates runtime.tlsg as a regular variable. + putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_OBJECT, s->sect->elfsect->shnum, 0); + } else { + putelfsyment(putelfstr(s->name), 0, s->size, (STB_LOCAL<<4)|STT_TLS, s->sect->elfsect->shnum, 0); + } s->elfsym = numelfsym++; } |
