Skip to content

Commit c00e928

Browse files
nsrip-ddmknyszek
authored andcommitted
runtime: save frame pointer to the stack in signal handlers for arm64
When taking over the goroutine stack in the panic or preemption signal handlers on arm64, the frame pointer should be saved on the stack (like the link register) so that frame-pointer unwinding from a panic stack works properly. Otherwise, tests like TestStackWrapperStackPanic will fail with the frame pointer check in adjustframe (enabled with debugCheckBP) when checking the sigpanic frame. Updates #39524, #58432 Change-Id: I8b89e6fc4877af29b1b81e55e591e6398159855c Reviewed-on: https://go-review.googlesource.com/c/go/+/481635 Reviewed-by: Felix Geisendörfer <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Nick Ripley <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Reviewed-by: Michael Knyszek <[email protected]>
1 parent 3202daf commit c00e928

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

src/runtime/signal_arm64.go

+11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package runtime
88

99
import (
1010
"internal/abi"
11+
"internal/goarch"
1112
"runtime/internal/sys"
1213
"unsafe"
1314
)
@@ -68,6 +69,12 @@ func (c *sigctxt) preparePanic(sig uint32, gp *g) {
6869
sp := c.sp() - sys.StackAlign // needs only sizeof uint64, but must align the stack
6970
c.set_sp(sp)
7071
*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.lr()
72+
// Make sure a valid frame pointer is saved on the stack so that the
73+
// frame pointer checks in adjustframe are happy, if they're enabled.
74+
// Frame pointer unwinding won't visit the sigpanic frame, since
75+
// sigpanic will save the same frame pointer before calling into a panic
76+
// function.
77+
*(*uint64)(unsafe.Pointer(uintptr(sp - goarch.PtrSize))) = c.r29()
7178

7279
pc := gp.sigpc
7380

@@ -89,6 +96,10 @@ func (c *sigctxt) pushCall(targetPC, resumePC uintptr) {
8996
sp := c.sp() - 16 // SP needs 16-byte alignment
9097
c.set_sp(sp)
9198
*(*uint64)(unsafe.Pointer(uintptr(sp))) = c.lr()
99+
// Make sure a valid frame pointer is saved on the stack so that the
100+
// frame pointer checks in adjustframe are happy, if they're enabled.
101+
// This is not actually used for unwinding.
102+
*(*uint64)(unsafe.Pointer(uintptr(sp - goarch.PtrSize))) = c.r29()
92103
// Set up PC and LR to pretend the function being signaled
93104
// calls targetPC at resumePC.
94105
c.set_lr(uint64(resumePC))

0 commit comments

Comments
 (0)