180 lines
5.0 KiB
Diff
180 lines
5.0 KiB
Diff
From fce0a59fc370634fcd7de8f8691e918cdf122f7d Mon Sep 17 00:00:00 2001
|
|
From: Cherry Zhang <cherryyz@google.com>
|
|
Date: Thu, 31 Oct 2019 10:32:31 -0400
|
|
Subject: [PATCH 4/6] runtime: don't fetch G from signal stack when using cgo
|
|
|
|
When using cgo, we save G to TLS, and when a signal happens, we
|
|
load G from TLS in sigtramp. This should give us a valid G. Don't
|
|
try to fetch from the signal stack. In particular, C code may
|
|
change the signal stack or call our signal handler directly (e.g.
|
|
TSAN), so we are not necessarily running on the original gsignal
|
|
stack where we saved G.
|
|
|
|
Also skip saving G on the signal stack when using cgo.
|
|
|
|
Updates #35249.
|
|
|
|
Change-Id: I40749ce6682709bd4ebfdfd9f23bd0f317fc197d
|
|
Reviewed-on: https://go-review.googlesource.com/c/go/+/204519
|
|
Reviewed-by: Ian Lance Taylor <iant@golang.org>
|
|
---
|
|
src/runtime/signal_unix.go | 8 +++++---
|
|
src/runtime/sys_linux_arm.s | 30 ++++++++++++++++++++++--------
|
|
src/runtime/sys_linux_arm64.s | 26 ++++++++++++++++++++------
|
|
3 files changed, 47 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/src/runtime/signal_unix.go b/src/runtime/signal_unix.go
|
|
index 2cf1e3b..721edb5 100644
|
|
--- a/src/runtime/signal_unix.go
|
|
+++ b/src/runtime/signal_unix.go
|
|
@@ -282,9 +282,11 @@ func sigpipe() {
|
|
func sigFetchG(c *sigctxt) *g {
|
|
switch GOARCH {
|
|
case "arm", "arm64":
|
|
- if inVDSOPage(c.sigpc()) {
|
|
- // Before making a VDSO call we save the g to the bottom of the
|
|
- // signal stack. Fetch from there.
|
|
+ if !iscgo && inVDSOPage(c.sigpc()) {
|
|
+ // When using cgo, we save the g on TLS and load it from there
|
|
+ // in sigtramp. Just use that.
|
|
+ // Otherwise, before making a VDSO call we save the g to the
|
|
+ // bottom of the signal stack. Fetch from there.
|
|
// TODO: in efence mode, stack is sysAlloc'd, so this wouldn't
|
|
// work.
|
|
sp := getcallersp()
|
|
diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s
|
|
index 26e12a8..a47ac5f 100644
|
|
--- a/src/runtime/sys_linux_arm.s
|
|
+++ b/src/runtime/sys_linux_arm.s
|
|
@@ -250,21 +250,28 @@ noswitch:
|
|
// during VDSO code we can find the g.
|
|
// If we don't have a signal stack, we won't receive signal,
|
|
// so don't bother saving g.
|
|
+ // When using cgo, we already saved g on TLS, also don't save
|
|
+ // g here.
|
|
+ MOVB runtime·iscgo(SB), R6
|
|
+ CMP $0, R6
|
|
+ BNE nosaveg
|
|
MOVW m_gsignal(R5), R6 // g.m.gsignal
|
|
CMP $0, R6
|
|
- BEQ 3(PC)
|
|
+ BEQ nosaveg
|
|
MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo
|
|
MOVW g, (R6)
|
|
|
|
BL (R11)
|
|
|
|
- CMP $0, R6 // R6 is unchanged by C code
|
|
- BEQ 3(PC)
|
|
MOVW $0, R1
|
|
- MOVW R1, (R6) // clear g slot
|
|
+ MOVW R1, (R6) // clear g slot, R6 is unchanged by C code
|
|
|
|
JMP finish
|
|
|
|
+nosaveg:
|
|
+ BL (R11)
|
|
+ JMP finish
|
|
+
|
|
fallback:
|
|
MOVW $SYS_clock_gettime, R7
|
|
SWI $0
|
|
@@ -317,21 +324,28 @@ noswitch:
|
|
// during VDSO code we can find the g.
|
|
// If we don't have a signal stack, we won't receive signal,
|
|
// so don't bother saving g.
|
|
+ // When using cgo, we already saved g on TLS, also don't save
|
|
+ // g here.
|
|
+ MOVB runtime·iscgo(SB), R6
|
|
+ CMP $0, R6
|
|
+ BNE nosaveg
|
|
MOVW m_gsignal(R5), R6 // g.m.gsignal
|
|
CMP $0, R6
|
|
- BEQ 3(PC)
|
|
+ BEQ nosaveg
|
|
MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo
|
|
MOVW g, (R6)
|
|
|
|
BL (R11)
|
|
|
|
- CMP $0, R6 // R6 is unchanged by C code
|
|
- BEQ 3(PC)
|
|
MOVW $0, R1
|
|
- MOVW R1, (R6) // clear g slot
|
|
+ MOVW R1, (R6) // clear g slot, R6 is unchanged by C code
|
|
|
|
JMP finish
|
|
|
|
+nosaveg:
|
|
+ BL (R11)
|
|
+ JMP finish
|
|
+
|
|
fallback:
|
|
MOVW $SYS_clock_gettime, R7
|
|
SWI $0
|
|
diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s
|
|
index fd40bf9..94c93ca 100644
|
|
--- a/src/runtime/sys_linux_arm64.s
|
|
+++ b/src/runtime/sys_linux_arm64.s
|
|
@@ -212,18 +212,25 @@ noswitch:
|
|
// during VDSO code we can find the g.
|
|
// If we don't have a signal stack, we won't receive signal,
|
|
// so don't bother saving g.
|
|
+ // When using cgo, we already saved g on TLS, also don't save
|
|
+ // g here.
|
|
+ MOVBU runtime·iscgo(SB), R22
|
|
+ CBNZ R22, nosaveg
|
|
MOVD m_gsignal(R21), R22 // g.m.gsignal
|
|
- CBZ R22, 3(PC)
|
|
+ CBZ R22, nosaveg
|
|
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
|
|
MOVD g, (R22)
|
|
|
|
BL (R2)
|
|
|
|
- CBZ R22, 2(PC) // R22 is unchanged by C code
|
|
- MOVD ZR, (R22) // clear g slot
|
|
+ MOVD ZR, (R22) // clear g slot, R22 is unchanged by C code
|
|
|
|
B finish
|
|
|
|
+nosaveg:
|
|
+ BL (R2)
|
|
+ B finish
|
|
+
|
|
fallback:
|
|
MOVD $SYS_clock_gettime, R8
|
|
SVC
|
|
@@ -269,18 +276,25 @@ noswitch:
|
|
// during VDSO code we can find the g.
|
|
// If we don't have a signal stack, we won't receive signal,
|
|
// so don't bother saving g.
|
|
+ // When using cgo, we already saved g on TLS, also don't save
|
|
+ // g here.
|
|
+ MOVBU runtime·iscgo(SB), R22
|
|
+ CBNZ R22, nosaveg
|
|
MOVD m_gsignal(R21), R22 // g.m.gsignal
|
|
- CBZ R22, 3(PC)
|
|
+ CBZ R22, nosaveg
|
|
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
|
|
MOVD g, (R22)
|
|
|
|
BL (R2)
|
|
|
|
- CBZ R22, 2(PC) // R22 is unchanged by C code
|
|
- MOVD ZR, (R22) // clear g slot
|
|
+ MOVD ZR, (R22) // clear g slot, R22 is unchanged by C code
|
|
|
|
B finish
|
|
|
|
+nosaveg:
|
|
+ BL (R2)
|
|
+ B finish
|
|
+
|
|
fallback:
|
|
MOVD $SYS_clock_gettime, R8
|
|
SVC
|
|
--
|
|
2.17.1
|
|
|