]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] runtime: initialize special registers before sigpanic
authorCherry Zhang <cherryyz@google.com>
Thu, 4 Feb 2021 16:41:34 +0000 (11:41 -0500)
committerCherry Zhang <cherryyz@google.com>
Mon, 8 Feb 2021 17:48:48 +0000 (17:48 +0000)
In case that we are panicking in ABI0 context or external code,
special registers are not initialized. Initialized them in
injected code before calling sigpanic.

TODO: Windows, Plan 9.

Change-Id: I0919b80e7cc55463f3dd94f1f63cba305717270a
Reviewed-on: https://go-review.googlesource.com/c/go/+/289710
Trust: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/runtime/asm.s
src/runtime/asm_amd64.s
src/runtime/signal_amd64.go
src/runtime/stubs.go

index 27d8df9e063ecf8404e5da9ffa15b88c5f4fffbc..72c744925d89aec9d1cc33a6eacf55f826866fcf 100644 (file)
@@ -11,3 +11,8 @@
 DATA runtime·no_pointers_stackmap+0x00(SB)/4, $2
 DATA runtime·no_pointers_stackmap+0x04(SB)/4, $0
 GLOBL runtime·no_pointers_stackmap(SB),RODATA, $8
+
+#ifndef GOARCH_amd64
+TEXT ·sigpanic0<ABIInternal>(SB),NOSPLIT,$0-0
+       JMP     ·sigpanic<ABIInternal>(SB)
+#endif
index 9f15990b137cdda53ffbc6d8ff4bf13c74c4527d..83c08a52f742cf60a7336e62f639d91003afd3a3 100644 (file)
@@ -1364,6 +1364,18 @@ TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
        POPQ    R15
        RET
 
+// Initialize special registers then jump to sigpanic.
+// This function is injected from the signal handler for panicking
+// signals. It is quite painful to set X15 in the signal context,
+// so we do it here.
+TEXT ·sigpanic0<ABIInternal>(SB),NOSPLIT,$0-0
+#ifdef GOEXPERIMENT_REGABI
+       get_tls(R14)
+       MOVQ    g(R14), R14
+       XORPS   X15, X15
+#endif
+       JMP     ·sigpanic<ABIInternal>(SB)
+
 // gcWriteBarrier performs a heap pointer write and informs the GC.
 //
 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
index 6ab1f758c2293542396062811536109be2964ccb..3eeb5e044ff0ff1c5cae3d43ca064dda5b37dde1 100644 (file)
@@ -65,11 +65,14 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) {
        pc := uintptr(c.rip())
        sp := uintptr(c.rsp())
 
+       // In case we are panicking from external code, we need to initialize
+       // Go special registers. We inject sigpanic0 (instead of sigpanic),
+       // which takes care of that.
        if shouldPushSigpanic(gp, pc, *(*uintptr)(unsafe.Pointer(sp))) {
-               c.pushCall(funcPC(sigpanic), pc)
+               c.pushCall(funcPC(sigpanic0), pc)
        } else {
                // Not safe to push the call. Just clobber the frame.
-               c.set_rip(uint64(funcPC(sigpanic)))
+               c.set_rip(uint64(funcPC(sigpanic0)))
        }
 }
 
index 36bbc8991ac0f00799d02ca9bfe76fa94d43f93d..3d1e0c0bb4dd702ae3f0a1e91bb40ffc4f7b2225 100644 (file)
@@ -356,3 +356,7 @@ func duffcopy()
 
 // Called from linker-generated .initarray; declared for go vet; do NOT call from Go.
 func addmoduledata()
+
+// Injected by the signal handler for panicking signals. On many platforms it just
+// jumps to sigpanic.
+func sigpanic0()