Skip to content

Commit

Permalink
runtime: save frame pointer to the stack in signal handlers for arm64
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
nsrip-dd authored and mknyszek committed Apr 5, 2023
1 parent 3202daf commit c00e928
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/runtime/signal_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package runtime

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

pc := gp.sigpc

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

0 comments on commit c00e928

Please sign in to comment.