From ee0275d15b4407038d30e27c9cc313c4ef339026 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 9 Dec 2025 18:56:45 -0800 Subject: [PATCH] runtime, cmd/link: tighten search for stackObjectRecord A stackObjectRecord should always be in funcdata, between gofunc and the end of pclntab, except for the special case of methodValueCallFrameObjs, which should always be in noptrbss. Adjust the two loops that look for the moduledata corresponding to a stackObjectRecord to search more precisely, rather than relying on datap.end. Closely based on a patch by Michael Stapelberg. For #76038 Change-Id: I751801d8fd030af751825a67905b2a343280e7d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/728840 Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor Reviewed-by: Cherry Mui --- src/cmd/link/internal/ld/symtab.go | 1 + src/runtime/stack.go | 8 +++++++- src/runtime/stkframe.go | 2 +- src/runtime/symtab.go | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index dd2d74895a..67b1f11c60 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -656,6 +656,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.rodata", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go:func.*", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.epclntab", 0)) if ctxt.IsAIX() && ctxt.IsExternal() { // Add R_XCOFFREF relocation to prevent ld's garbage collection of diff --git a/src/runtime/stack.go b/src/runtime/stack.go index d1c80276a5..6f89cc142c 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1357,7 +1357,13 @@ func (r *stackObjectRecord) gcdata() (uintptr, *byte) { ptr := uintptr(unsafe.Pointer(r)) var mod *moduledata for datap := &firstmoduledata; datap != nil; datap = datap.next { - if datap.gofunc <= ptr && ptr < datap.end { + // The normal case: stackObjectRecord is in funcdata. + if datap.gofunc <= ptr && ptr < datap.epclntab { + mod = datap + break + } + // A special case: methodValueCallFrameObjs. + if datap.noptrbss <= ptr && ptr < datap.enoptrbss { mod = datap break } diff --git a/src/runtime/stkframe.go b/src/runtime/stkframe.go index 485af1e75f..b63c0b4519 100644 --- a/src/runtime/stkframe.go +++ b/src/runtime/stkframe.go @@ -269,7 +269,7 @@ func stkobjinit() { ptr := uintptr(unsafe.Pointer(&methodValueCallFrameObjs[0])) var mod *moduledata for datap := &firstmoduledata; datap != nil; datap = datap.next { - if datap.gofunc <= ptr && ptr < datap.end { + if datap.noptrbss <= ptr && ptr < datap.enoptrbss { mod = datap break } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index c1643c1b39..0581655530 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -422,6 +422,7 @@ type moduledata struct { types, etypes uintptr rodata uintptr gofunc uintptr // go.func.* + epclntab uintptr textsectmap []textsect typelinks []int32 // offsets from types -- 2.52.0