proc: for optimized functions allow .closureptr to not exist (#3808)

* proc: flag variables correctly when range-over-func stmts are used

Argument variables of a range-over-func body closure should be returned
flagged as normal local variables, not as function arguments.

Updates #3806

* proc: for optimized functions allow .closureptr to not exist

For optimized functions .closureptr is sometimes omitted from DWARF,
allow it to be 0 and try to recover the range-over-func stack by best
effort.

Fixes #3806
This commit is contained in:
Alessandro Arzilli
2024-09-18 23:16:34 +02:00
committed by GitHub
parent b9fadbae9b
commit 582305a813
6 changed files with 143 additions and 13 deletions

View File

@ -948,6 +948,10 @@ func rangeFuncStackTrace(tgt *Target, g *G) ([]Stackframe, error) {
nonMonotonicSP := false
var closurePtr int64
optimized := func(fn *Function) bool {
return fn.cu.optimized&optimizedOptimized != 0
}
appendFrame := func(fr Stackframe) {
frames = append(frames, fr)
if fr.closurePtr != 0 {
@ -960,6 +964,9 @@ func rangeFuncStackTrace(tgt *Target, g *G) ([]Stackframe, error) {
if fr.SystemStack {
return false
}
if closurePtr == 0 && optimized(fr.Call.Fn) {
return true
}
if closurePtr < 0 {
// closure is stack allocated, check that it is on this frame
return fr.contains(closurePtr)
@ -994,12 +1001,30 @@ func rangeFuncStackTrace(tgt *Target, g *G) ([]Stackframe, error) {
frames = append(frames, fr)
}
if fr.Call.Fn == nil {
if stage == startStage {
frames = nil
addRetFrame = false
stage = doneStage
return false
} else {
return true
}
}
switch stage {
case startStage:
appendFrame(fr)
rangeParent = fr.Call.Fn.extra(tgt.BinInfo()).rangeParent
stage = normalStage
if rangeParent == nil || closurePtr == 0 {
stop := false
if rangeParent == nil {
stop = true
}
if !optimized(fr.Call.Fn) && closurePtr == 0 {
stop = true
}
if stop {
frames = nil
addRetFrame = false
stage = doneStage
@ -1011,7 +1036,7 @@ func rangeFuncStackTrace(tgt *Target, g *G) ([]Stackframe, error) {
stage = lastFrameStage
} else if fr.Call.Fn.extra(tgt.BinInfo()).rangeParent == rangeParent && closurePtrOk(&fr) {
appendFrame(fr)
if closurePtr == 0 {
if !optimized(fr.Call.Fn) && closurePtr == 0 {
frames = nil
addRetFrame = false
stage = doneStage