proc: fix stacktrace frame after runtime.sigpanic (#3638)
The first frame after sigpanic didn't execute a call so we shouldn't decrement the PC address to look up its location. Fixes #3634
This commit is contained in:
parent
88380654fe
commit
4ed69d0280
8
_fixtures/panicline.go
Normal file
8
_fixtures/panicline.go
Normal file
@ -0,0 +1,8 @@
|
||||
package main
|
||||
|
||||
import "os"
|
||||
|
||||
func main() {
|
||||
fi, _ := os.Lstat("/this/path/does/not/exist")
|
||||
fi.Size()
|
||||
}
|
@ -6121,3 +6121,28 @@ func TestIssue3545(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestPanicLine(t *testing.T) {
|
||||
withTestProcess("panicline", t, func(p *proc.Target, grp *proc.TargetGroup, fixture protest.Fixture) {
|
||||
err := grp.Continue()
|
||||
if runtime.GOOS == "darwin" && err != nil && err.Error() == "bad access" {
|
||||
// not supported
|
||||
return
|
||||
}
|
||||
assertNoError(err, t, "Continue()")
|
||||
frames, err := proc.ThreadStacktrace(p, p.CurrentThread(), 20)
|
||||
assertNoError(err, t, "ThreadStacktrace")
|
||||
logStacktrace(t, p, frames)
|
||||
|
||||
found := false
|
||||
for _, frame := range frames {
|
||||
if strings.HasSuffix(frame.Call.File, "panicline.go") && frame.Call.Line == 7 {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("could not find panicline.go:6")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -180,6 +180,7 @@ type stackIterator struct {
|
||||
pc uint64
|
||||
top bool
|
||||
atend bool
|
||||
sigret bool
|
||||
frame Stackframe
|
||||
target *Target
|
||||
bi *BinaryInfo
|
||||
@ -270,6 +271,7 @@ func (it *stackIterator) Next() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
it.sigret = it.frame.Current.Fn != nil && it.frame.Current.Fn.Name == "runtime.sigpanic"
|
||||
it.top = false
|
||||
it.pc = it.frame.Ret
|
||||
it.regs = callFrameRegs
|
||||
@ -329,7 +331,7 @@ func (it *stackIterator) newStackframe(ret, retaddr uint64) Stackframe {
|
||||
r.Regs.AddReg(it.regs.PCRegNum, op.DwarfRegisterFromUint64(it.pc))
|
||||
}
|
||||
r.Call = r.Current
|
||||
if !it.top && r.Current.Fn != nil && it.pc != r.Current.Fn.Entry {
|
||||
if !it.top && r.Current.Fn != nil && it.pc != r.Current.Fn.Entry && !it.sigret {
|
||||
// if the return address is the entry point of the function that
|
||||
// contains it then this is some kind of fake return frame (for example
|
||||
// runtime.sigreturn) that didn't actually call the current frame,
|
||||
|
Loading…
Reference in New Issue
Block a user