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
2014-07-03 14:14:34 -06:00
|
|
|
// Copyright 2014 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.
|
|
|
|
|
[dev.cc] runtime: convert assembly files for C to Go transition
The main change is that #include "zasm_GOOS_GOARCH.h"
is now #include "go_asm.h" and/or #include "go_tls.h".
Also, because C StackGuard is now Go _StackGuard,
the assembly name changes from const_StackGuard to
const__StackGuard.
In asm_$GOARCH.s, add new function getg, formerly
implemented in C.
The renamed atomics now have Go wrappers, to get
escape analysis annotations right. Those wrappers
are in CL 174860043.
LGTM=r, aram
R=r, aram
CC=austin, dvyukov, golang-codereviews, iant, khr
https://golang.org/cl/168510043
2014-11-11 15:06:22 -07:00
|
|
|
#include "go_asm.h"
|
|
|
|
#include "go_tls.h"
|
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
2014-07-03 14:14:34 -06:00
|
|
|
#include "funcdata.h"
|
2014-09-04 21:05:18 -06:00
|
|
|
#include "textflag.h"
|
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
2014-07-03 14:14:34 -06:00
|
|
|
|
|
|
|
// We have to resort to TLS variable to save g(R10).
|
|
|
|
// One reason is that external code might trigger
|
|
|
|
// SIGSEGV, and our runtime.sigtramp don't even know we
|
|
|
|
// are in external code, and will continue to use R10,
|
|
|
|
// this might as well result in another SIGSEGV.
|
|
|
|
// Note: both functions will clobber R0 and R11 and
|
|
|
|
// can be called from 5c ABI code.
|
|
|
|
|
2015-09-01 16:35:54 -06:00
|
|
|
// On android and darwin, runtime.tls_g is a normal variable.
|
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
2014-07-03 14:14:34 -06:00
|
|
|
// TLS offset is computed in x_cgo_inittls.
|
2014-12-25 22:48:33 -07:00
|
|
|
#ifdef GOOS_android
|
|
|
|
#define TLSG_IS_VARIABLE
|
|
|
|
#endif
|
2014-12-25 23:07:10 -07:00
|
|
|
#ifdef GOOS_darwin
|
|
|
|
#define TLSG_IS_VARIABLE
|
|
|
|
#endif
|
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
2014-07-03 14:14:34 -06:00
|
|
|
|
|
|
|
// save_g saves the g register into pthread-provided
|
|
|
|
// thread-local memory, so that we can call externally compiled
|
|
|
|
// ARM code that will overwrite those registers.
|
|
|
|
// NOTE: runtime.gogo assumes that R1 is preserved by this function.
|
|
|
|
// runtime.mcall assumes this function only clobbers R0 and R11.
|
runtime: save g to TLS more aggressively
This is one of those "how did this ever work?" bugs.
The current build failures are happening because
a fault comes up while executing on m->curg on a
system-created thread using an m obtained from needm,
but TLS is set to m->g0, not m->curg. On fault,
sigtramp starts executing, assumes r10 (g) might be
incorrect, reloads it from TLS, and gets m->g0, not
m->curg. Then sighandler dutifully pushes a call to
sigpanic onto the stack and returns to it.
We're now executing on the m->curg stack but with
g=m->g0. Sigpanic does a stack split check, sees that
the SP is not in range (50% chance depending on relative
ordering of m->g0's and m->curg's stacks), and then
calls morestack. Morestack sees that g=m->g0 and
crashes the program.
The fix is to replace every change of g in asm_arm.s
with a call to a function that both updates g and
saves the updated g to TLS.
Why did it start happening? That's unclear.
Unfortunately there were other bugs in the initial
checkin that mask exactly which of a sequence of
CLs started the behavior where sigpanic would end
up tripping the stack split.
Fixes arm build.
Fixes #8675.
LGTM=iant
R=golang-codereviews, iant
CC=dave, golang-codereviews, khr, minux, r
https://golang.org/cl/135570043
2014-09-07 17:47:40 -06:00
|
|
|
// Returns with g in R0.
|
|
|
|
TEXT runtime·save_g(SB),NOSPLIT,$-4
|
2014-07-10 13:14:49 -06:00
|
|
|
#ifdef GOOS_nacl
|
|
|
|
// nothing to do as nacl/arm does not use TLS at all.
|
runtime: save g to TLS more aggressively
This is one of those "how did this ever work?" bugs.
The current build failures are happening because
a fault comes up while executing on m->curg on a
system-created thread using an m obtained from needm,
but TLS is set to m->g0, not m->curg. On fault,
sigtramp starts executing, assumes r10 (g) might be
incorrect, reloads it from TLS, and gets m->g0, not
m->curg. Then sighandler dutifully pushes a call to
sigpanic onto the stack and returns to it.
We're now executing on the m->curg stack but with
g=m->g0. Sigpanic does a stack split check, sees that
the SP is not in range (50% chance depending on relative
ordering of m->g0's and m->curg's stacks), and then
calls morestack. Morestack sees that g=m->g0 and
crashes the program.
The fix is to replace every change of g in asm_arm.s
with a call to a function that both updates g and
saves the updated g to TLS.
Why did it start happening? That's unclear.
Unfortunately there were other bugs in the initial
checkin that mask exactly which of a sequence of
CLs started the behavior where sigpanic would end
up tripping the stack split.
Fixes arm build.
Fixes #8675.
LGTM=iant
R=golang-codereviews, iant
CC=dave, golang-codereviews, khr, minux, r
https://golang.org/cl/135570043
2014-09-07 17:47:40 -06:00
|
|
|
MOVW g, R0 // preserve R0 across call to setg<>
|
2014-07-10 13:14:49 -06:00
|
|
|
RET
|
|
|
|
#endif
|
2014-09-18 20:02:21 -06:00
|
|
|
// If the host does not support MRC the linker will replace it with
|
|
|
|
// a call to runtime.read_tls_fallback which jumps to __kuser_get_tls.
|
2014-09-29 18:03:10 -06:00
|
|
|
// The replacement function saves LR in R11 over the call to read_tls_fallback.
|
runtime: save g to TLS more aggressively
This is one of those "how did this ever work?" bugs.
The current build failures are happening because
a fault comes up while executing on m->curg on a
system-created thread using an m obtained from needm,
but TLS is set to m->g0, not m->curg. On fault,
sigtramp starts executing, assumes r10 (g) might be
incorrect, reloads it from TLS, and gets m->g0, not
m->curg. Then sighandler dutifully pushes a call to
sigpanic onto the stack and returns to it.
We're now executing on the m->curg stack but with
g=m->g0. Sigpanic does a stack split check, sees that
the SP is not in range (50% chance depending on relative
ordering of m->g0's and m->curg's stacks), and then
calls morestack. Morestack sees that g=m->g0 and
crashes the program.
The fix is to replace every change of g in asm_arm.s
with a call to a function that both updates g and
saves the updated g to TLS.
Why did it start happening? That's unclear.
Unfortunately there were other bugs in the initial
checkin that mask exactly which of a sequence of
CLs started the behavior where sigpanic would end
up tripping the stack split.
Fixes arm build.
Fixes #8675.
LGTM=iant
R=golang-codereviews, iant
CC=dave, golang-codereviews, khr, minux, r
https://golang.org/cl/135570043
2014-09-07 17:47:40 -06:00
|
|
|
MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
|
2014-12-25 23:07:10 -07:00
|
|
|
BIC $3, R0 // Darwin/ARM might return unaligned pointer
|
2015-09-01 16:35:54 -06:00
|
|
|
MOVW runtime·tls_g(SB), R11
|
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
2014-07-03 14:14:34 -06:00
|
|
|
ADD R11, R0
|
|
|
|
MOVW g, 0(R0)
|
runtime: save g to TLS more aggressively
This is one of those "how did this ever work?" bugs.
The current build failures are happening because
a fault comes up while executing on m->curg on a
system-created thread using an m obtained from needm,
but TLS is set to m->g0, not m->curg. On fault,
sigtramp starts executing, assumes r10 (g) might be
incorrect, reloads it from TLS, and gets m->g0, not
m->curg. Then sighandler dutifully pushes a call to
sigpanic onto the stack and returns to it.
We're now executing on the m->curg stack but with
g=m->g0. Sigpanic does a stack split check, sees that
the SP is not in range (50% chance depending on relative
ordering of m->g0's and m->curg's stacks), and then
calls morestack. Morestack sees that g=m->g0 and
crashes the program.
The fix is to replace every change of g in asm_arm.s
with a call to a function that both updates g and
saves the updated g to TLS.
Why did it start happening? That's unclear.
Unfortunately there were other bugs in the initial
checkin that mask exactly which of a sequence of
CLs started the behavior where sigpanic would end
up tripping the stack split.
Fixes arm build.
Fixes #8675.
LGTM=iant
R=golang-codereviews, iant
CC=dave, golang-codereviews, khr, minux, r
https://golang.org/cl/135570043
2014-09-07 17:47:40 -06:00
|
|
|
MOVW g, R0 // preserve R0 across call to setg<>
|
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
2014-07-03 14:14:34 -06:00
|
|
|
RET
|
|
|
|
|
|
|
|
// load_g loads the g register from pthread-provided
|
|
|
|
// thread-local memory, for use after calling externally compiled
|
|
|
|
// ARM code that overwrote those registers.
|
|
|
|
TEXT runtime·load_g(SB),NOSPLIT,$0
|
2014-07-10 13:14:49 -06:00
|
|
|
#ifdef GOOS_nacl
|
|
|
|
// nothing to do as nacl/arm does not use TLS at all.
|
|
|
|
RET
|
|
|
|
#endif
|
2014-09-29 18:03:10 -06:00
|
|
|
// See save_g
|
|
|
|
MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
|
2014-12-25 23:07:10 -07:00
|
|
|
BIC $3, R0 // Darwin/ARM might return unaligned pointer
|
2015-09-01 16:35:54 -06:00
|
|
|
MOVW runtime·tls_g(SB), R11
|
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
2014-07-03 14:14:34 -06:00
|
|
|
ADD R11, R0
|
|
|
|
MOVW 0(R0), g
|
|
|
|
RET
|
2014-12-25 22:48:33 -07:00
|
|
|
|
2015-08-04 21:44:06 -06:00
|
|
|
// This is called from rt0_go, which runs on the system stack
|
|
|
|
// using the initial stack allocated by the OS.
|
|
|
|
// It calls back into standard C using the BL (R4) below.
|
|
|
|
// To do that, the stack pointer must be 8-byte-aligned
|
|
|
|
// on some systems, notably FreeBSD.
|
|
|
|
// The ARM ABI says the stack pointer must be 8-byte-aligned
|
|
|
|
// on entry to any function, but only FreeBSD's C library seems to care.
|
|
|
|
// The caller was 8-byte aligned, but we push an LR.
|
|
|
|
// Declare a dummy word ($4, not $0) to make sure the
|
|
|
|
// frame is 8 bytes and stays 8-byte-aligned.
|
|
|
|
TEXT runtime·_initcgo(SB),NOSPLIT,$4
|
2015-02-06 00:05:30 -07:00
|
|
|
#ifndef GOOS_nacl
|
|
|
|
// if there is an _cgo_init, call it.
|
|
|
|
MOVW _cgo_init(SB), R4
|
|
|
|
CMP $0, R4
|
|
|
|
B.EQ nocgo
|
|
|
|
MRC 15, 0, R0, C13, C0, 3 // load TLS base pointer
|
|
|
|
MOVW R0, R3 // arg 3: TLS base pointer
|
2015-09-01 16:35:54 -06:00
|
|
|
#ifdef TLSG_IS_VARIABLE
|
|
|
|
MOVW $runtime·tls_g(SB), R2 // arg 2: &tls_g
|
|
|
|
#else
|
|
|
|
MOVW $0, R2 // arg 2: not used when using platform tls
|
|
|
|
#endif
|
2015-02-06 00:05:30 -07:00
|
|
|
MOVW $setg_gcc<>(SB), R1 // arg 1: setg
|
|
|
|
MOVW g, R0 // arg 0: G
|
|
|
|
BL (R4) // will clobber R0-R3
|
|
|
|
#endif
|
|
|
|
nocgo:
|
|
|
|
RET
|
|
|
|
|
|
|
|
// void setg_gcc(G*); set g called from gcc.
|
|
|
|
TEXT setg_gcc<>(SB),NOSPLIT,$0
|
|
|
|
MOVW R0, g
|
|
|
|
B runtime·save_g(SB)
|
|
|
|
|
2014-12-25 22:48:33 -07:00
|
|
|
#ifdef TLSG_IS_VARIABLE
|
2015-09-01 16:35:54 -06:00
|
|
|
GLOBL runtime·tls_g+0(SB), NOPTR, $4
|
|
|
|
#else
|
|
|
|
GLOBL runtime·tls_g+0(SB), TLSBSS, $4
|
2014-12-25 22:48:33 -07:00
|
|
|
#endif
|