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.
|
|
|
|
|
|
|
|
#include "zasm_GOOS_GOARCH.h"
|
|
|
|
#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.
|
|
|
|
|
|
|
|
// On android, runtime.tlsg is a normal variable.
|
|
|
|
// TLS offset is computed in x_cgo_inittls.
|
|
|
|
|
|
|
|
// 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
|
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
|
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
|
|
|
// $runtime.tlsg(SB) is a special linker symbol.
|
|
|
|
// It is the offset from the TLS base pointer to our
|
|
|
|
// thread-local storage for g.
|
|
|
|
#ifdef GOOS_android
|
|
|
|
MOVW runtime·tlsg(SB), R11
|
|
|
|
#else
|
|
|
|
MOVW $runtime·tlsg(SB), R11
|
|
|
|
#endif
|
|
|
|
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
|
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
|
|
|
MRC 15, 0, R0, C13, C0, 3 // fetch TLS base pointer
|
|
|
|
// $runtime.tlsg(SB) is a special linker symbol.
|
|
|
|
// It is the offset from the TLS base pointer to our
|
|
|
|
// thread-local storage for g.
|
|
|
|
#ifdef GOOS_android
|
|
|
|
MOVW runtime·tlsg(SB), R11
|
|
|
|
#else
|
|
|
|
MOVW $runtime·tlsg(SB), R11
|
|
|
|
#endif
|
|
|
|
ADD R11, R0
|
|
|
|
MOVW 0(R0), g
|
|
|
|
RET
|