Skip to content

Commit

Permalink
[release-branch.go1.18] runtime: don't jump stack if at entry of syst…
Browse files Browse the repository at this point in the history
…emstack

The traceback code has special "jump stack" logic, to trace back
stack switches through systemstack. If we're at the entry of
systemstack, the stack switch hasn't happened, so don't jump to
user stack.

The jump stack logic is only used if we're on the g0 stack. It can
happen that we're at the entry of a recursive systemstack call on
the g0 stack. In we jump stack here, there will be two problems:
1. There are frames between entering the g0 stack and this
   recursive systemstack call. Those frames will be lost.
2. Worse, we switched frame.sp but frame.fp calculation will use
   the entry SP delta (0), which will be wrong, which in turn
   leads wrong frame.lr and things will go off.

For now, don't jump stack if we're at entry of systemstack (SP
delta is 0).

Using a per-PC SPWRITE marker may be a better fix. If we haven't
written the SP, we haven't switched the stack so we can just
unwind like a normal function.

Updates #55851.
Fixes #56635.

Change-Id: I2b624c8c086b235b34d9c7d3cebd4a37264f00f8
Reviewed-on: https://go-review.googlesource.com/c/go/+/437299
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
(cherry picked from commit 500bc6b)
Reviewed-on: https://go-review.googlesource.com/c/go/+/448517
  • Loading branch information
cherrymui authored and mknyszek committed Nov 9, 2022
1 parent d2a7a18 commit a3dce12
Showing 1 changed file with 11 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/runtime/traceback.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,17 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
case funcID_systemstack:
// systemstack returns normally, so just follow the
// stack transition.
if usesLR && funcspdelta(f, frame.pc, &cache) == 0 {
// We're at the function prologue and the stack
// switch hasn't happened, or epilogue where we're
// about to return. Just unwind normally.
// Do this only on LR machines because on x86
// systemstack doesn't have an SP delta (the CALL
// instruction opens the frame), therefore no way
// to check.
flag &^= funcFlag_SPWRITE
break
}
frame.sp = gp.m.curg.sched.sp
stack = gp.m.curg.stack
cgoCtxt = gp.m.curg.cgoCtxt
Expand Down

0 comments on commit a3dce12

Please sign in to comment.