Skip to content

Commit

Permalink
[dev.regabi] runtime: initialize special registers before sigpanic
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
cherrymui committed Feb 8, 2021
1 parent 5d7dc53 commit 22f9e1c
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 2 deletions.
5 changes: 5 additions & 0 deletions src/runtime/asm.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 12 additions & 0 deletions src/runtime/asm_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
7 changes: 5 additions & 2 deletions src/runtime/signal_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/runtime/stubs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

0 comments on commit 22f9e1c

Please sign in to comment.