aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/panic.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2025-11-05 18:05:42 -0800
committerDavid Chase <drchase@google.com>2025-11-06 05:00:27 -0800
commit48c7fa13c63761c8b52cbfac1f9eab062d475c0c (patch)
tree14eca1749ddb9132aa3153054841d5037154396d /src/runtime/panic.go
parent8111104a2120e14ef068b9cfbda91965473ab345 (diff)
downloadgo-48c7fa13c63761c8b52cbfac1f9eab062d475c0c.tar.xz
Revert "runtime: remove the pc field of _defer struct"
This reverts commit 361d51a6b58bccaab0559e06737c918018a7a5fa. Reason for revert: Breaks some tests inside Google (on arm64?) Change-Id: Iaea45fdcf9b4f9d36553687ca7f479750fe559da Reviewed-on: https://go-review.googlesource.com/c/go/+/718066 Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Youlin Feng <fengyoulin@live.com> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/runtime/panic.go')
-rw-r--r--src/runtime/panic.go25
1 files changed, 17 insertions, 8 deletions
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index ded85feffa..325bf74aa8 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -354,6 +354,7 @@ func deferproc(fn func()) {
d.link = gp._defer
gp._defer = d
d.fn = fn
+ d.pc = sys.GetCallerPC()
// We must not be preempted between calling GetCallerSP and
// storing it to d.sp because GetCallerSP's result is a
// uintptr stack pointer.
@@ -457,6 +458,7 @@ func deferrangefunc() any {
d := newdefer()
d.link = gp._defer
gp._defer = d
+ d.pc = sys.GetCallerPC()
// We must not be preempted between calling GetCallerSP and
// storing it to d.sp because GetCallerSP's result is a
// uintptr stack pointer.
@@ -516,6 +518,7 @@ func deferconvert(d0 *_defer) {
}
for d1 := d; ; d1 = d1.link {
d1.sp = d0.sp
+ d1.pc = d0.pc
if d1.link == nil {
d1.link = tail
break
@@ -544,6 +547,7 @@ func deferprocStack(d *_defer) {
d.heap = false
d.rangefunc = false
d.sp = sys.GetCallerSP()
+ d.pc = sys.GetCallerPC()
// The lines below implement:
// d.link = gp._defer
// d.head = nil
@@ -971,6 +975,8 @@ func (p *_panic) nextDefer() (func(), bool) {
fn := d.fn
+ p.retpc = d.pc
+
// Unlink and free.
popDefer(gp)
@@ -1010,12 +1016,6 @@ func (p *_panic) nextFrame() (ok bool) {
// it's non-zero.
if u.frame.sp == limit {
- f := u.frame.fn
- if f.deferreturn == 0 {
- throw("no deferreturn")
- }
- p.retpc = f.entry() + uintptr(f.deferreturn)
-
break // found a frame with linked defers
}
@@ -1271,6 +1271,15 @@ func recovery(gp *g) {
pc, sp, fp := p.retpc, uintptr(p.sp), uintptr(p.fp)
p0, saveOpenDeferState := p, p.deferBitsPtr != nil && *p.deferBitsPtr != 0
+ // The linker records the f-relative address of a call to deferreturn in f's funcInfo.
+ // Assuming a "normal" call to recover() inside one of f's deferred functions
+ // invoked for a panic, that is the desired PC for exiting f.
+ f := findfunc(pc)
+ if f.deferreturn == 0 {
+ throw("no deferreturn")
+ }
+ gotoPc := f.entry() + uintptr(f.deferreturn)
+
// Unwind the panic stack.
for ; p != nil && uintptr(p.startSP) < sp; p = p.link {
// Don't allow jumping past a pending Goexit.
@@ -1293,7 +1302,7 @@ func recovery(gp *g) {
// With how subtle defer handling is, this might not actually be
// worthwhile though.
if p.goexit {
- pc, sp = p.startPC, uintptr(p.startSP)
+ gotoPc, sp = p.startPC, uintptr(p.startSP)
saveOpenDeferState = false // goexit is unwinding the stack anyway
break
}
@@ -1356,7 +1365,7 @@ func recovery(gp *g) {
// branch directly to the deferreturn
gp.sched.sp = sp
- gp.sched.pc = pc
+ gp.sched.pc = gotoPc
gp.sched.lr = 0
// Restore the bp on platforms that support frame pointers.
// N.B. It's fine to not set anything for platforms that don't