Skip to content

Commit 1ea60c1

Browse files
committed
runtime: on stack copy, adjust BP
When we copy the stack, we need to adjust all BPs. We correctly adjust the ones on the stack, but we also need to adjust the one that is in g.sched.bp. Like CL 33754, no test as only kernel-gathered profiles will notice. Tests will come (in 1.9) with the implementation of #16638. The invariant should hold that every frame pointer points to somewhere within its stack. After this CL, it is mostly true, but something about cgo breaks it. The runtime checks are disabled until I figure that out. Update #16638 Fixes #18174 Change-Id: I6023ee64adc80574ee3e76491d4f0fa5ede3dbdb Reviewed-on: https://go-review.googlesource.com/33895 Reviewed-by: Austin Clements <[email protected]>
1 parent 8e0c463 commit 1ea60c1

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/runtime/asm_amd64.s

+1-1
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ havem:
742742
MOVQ (g_sched+gobuf_pc)(SI), BX
743743
MOVQ BX, -8(DI)
744744
// Compute the size of the frame, including return PC and, if
745-
// GOEXPERIMENT=framepointer, the saved based pointer
745+
// GOEXPERIMENT=framepointer, the saved base pointer
746746
MOVQ ctxt+24(FP), BX
747747
LEAQ fv+0(FP), AX
748748
SUBQ SP, AX

src/runtime/stack.go

+25
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ const (
123123
stackPoisonCopy = 0 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy
124124

125125
stackCache = 1
126+
127+
// check the BP links during traceback.
128+
debugCheckBP = false
126129
)
127130

128131
const (
@@ -688,6 +691,16 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
688691
if stackDebug >= 3 {
689692
print(" saved bp\n")
690693
}
694+
if debugCheckBP {
695+
// Frame pointers should always point to the next higher frame on
696+
// the Go stack (or be nil, for the top frame on the stack).
697+
bp := *(*uintptr)(unsafe.Pointer(frame.varp))
698+
if bp != 0 && (bp < adjinfo.old.lo || bp >= adjinfo.old.hi) {
699+
println("runtime: found invalid frame pointer")
700+
print("bp=", hex(bp), " min=", hex(adjinfo.old.lo), " max=", hex(adjinfo.old.hi), "\n")
701+
throw("bad frame pointer")
702+
}
703+
}
691704
adjustpointer(adjinfo, unsafe.Pointer(frame.varp))
692705
}
693706

@@ -719,6 +732,18 @@ func adjustframe(frame *stkframe, arg unsafe.Pointer) bool {
719732

720733
func adjustctxt(gp *g, adjinfo *adjustinfo) {
721734
adjustpointer(adjinfo, unsafe.Pointer(&gp.sched.ctxt))
735+
if !framepointer_enabled {
736+
return
737+
}
738+
if debugCheckBP {
739+
bp := gp.sched.bp
740+
if bp != 0 && (bp < adjinfo.old.lo || bp >= adjinfo.old.hi) {
741+
println("runtime: found invalid top frame pointer")
742+
print("bp=", hex(bp), " min=", hex(adjinfo.old.lo), " max=", hex(adjinfo.old.hi), "\n")
743+
throw("bad top frame pointer")
744+
}
745+
}
746+
adjustpointer(adjinfo, unsafe.Pointer(&gp.sched.bp))
722747
}
723748

724749
func adjustdefers(gp *g, adjinfo *adjustinfo) {

0 commit comments

Comments
 (0)