From c00e9285eae4599f6a123d0a355633379be998e8 Mon Sep 17 00:00:00 2001 From: Nick Ripley Date: Mon, 3 Apr 2023 09:54:53 -0400 Subject: [PATCH] runtime: save frame pointer to the stack in signal handlers for arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 TryBot-Result: Gopher Robot Run-TryBot: Nick Ripley Reviewed-by: Cherry Mui Reviewed-by: Michael Knyszek --- src/runtime/signal_arm64.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/runtime/signal_arm64.go b/src/runtime/signal_arm64.go index c8b87817b435a..4a96b3c2e7068 100644 --- a/src/runtime/signal_arm64.go +++ b/src/runtime/signal_arm64.go @@ -8,6 +8,7 @@ package runtime import ( "internal/abi" + "internal/goarch" "runtime/internal/sys" "unsafe" ) @@ -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 @@ -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))