mirror of
https://github.com/go-delve/delve.git
synced 2025-10-28 12:47:22 +08:00
proc: tolerate memory read errors during stacktrace
When there's a error reading the stack trace the call stack itself could be corrupted and we should return the partial stacktrace that we have. Fixes #868
This commit is contained in:
@ -38,6 +38,8 @@ type Stackframe struct {
|
||||
Ret uint64
|
||||
// Address to the memory location containing the return address
|
||||
addrret uint64
|
||||
// Err is set if an error occoured during stacktrace
|
||||
Err error
|
||||
}
|
||||
|
||||
// Stacktrace returns the stack trace for thread.
|
||||
@ -207,7 +209,7 @@ func (it *stackIterator) newStackframe(pc uint64, cfa int64, retaddr uintptr, fd
|
||||
f, l, fn := it.bi.PCToLine(pc)
|
||||
ret, err := readUintRaw(it.mem, retaddr, int64(it.bi.Arch.PtrSize()))
|
||||
if err != nil {
|
||||
return Stackframe{}, err
|
||||
it.err = err
|
||||
}
|
||||
r := Stackframe{Current: Location{PC: pc, File: f, Line: l, Fn: fn}, CFA: cfa, FDE: fde, Ret: ret, addrret: uint64(retaddr), StackHi: it.stackhi}
|
||||
if !top {
|
||||
@ -231,7 +233,10 @@ func (it *stackIterator) stacktrace(depth int) ([]Stackframe, error) {
|
||||
}
|
||||
}
|
||||
if err := it.Err(); err != nil {
|
||||
if len(frames) == 0 {
|
||||
return nil, err
|
||||
}
|
||||
frames = append(frames, Stackframe{Err: err})
|
||||
}
|
||||
return frames, nil
|
||||
}
|
||||
|
||||
@ -1210,6 +1210,10 @@ func printStack(stack []api.Stackframe, ind string) {
|
||||
s := ind + strings.Repeat(" ", d+2+len(ind))
|
||||
|
||||
for i := range stack {
|
||||
if stack[i].Err != "" {
|
||||
fmt.Printf("%serror: %s\n", s, stack[i].Err)
|
||||
continue
|
||||
}
|
||||
name := "(nil)"
|
||||
if stack[i].Function != nil {
|
||||
name = stack[i].Function.Name
|
||||
|
||||
@ -216,7 +216,7 @@ func TestExecuteFile(t *testing.T) {
|
||||
|
||||
func TestIssue354(t *testing.T) {
|
||||
printStack([]api.Stackframe{}, "")
|
||||
printStack([]api.Stackframe{{api.Location{PC: 0, File: "irrelevant.go", Line: 10, Function: nil}, nil, nil, 0}}, "")
|
||||
printStack([]api.Stackframe{{api.Location{PC: 0, File: "irrelevant.go", Line: 10, Function: nil}, nil, nil, 0, nil}}, "")
|
||||
}
|
||||
|
||||
func TestIssue411(t *testing.T) {
|
||||
|
||||
@ -121,6 +121,7 @@ type Stackframe struct {
|
||||
Locals []Variable
|
||||
Arguments []Variable
|
||||
FrameOffset int64
|
||||
Err string
|
||||
}
|
||||
|
||||
func (frame *Stackframe) Var(name string) *Variable {
|
||||
|
||||
@ -857,6 +857,9 @@ func (d *Debugger) convertStacktrace(rawlocs []proc.Stackframe, cfg *proc.LoadCo
|
||||
Location: api.ConvertLocation(rawlocs[i].Call),
|
||||
FrameOffset: rawlocs[i].CFA - int64(rawlocs[i].StackHi),
|
||||
}
|
||||
if rawlocs[i].Err != nil {
|
||||
frame.Err = rawlocs[i].Err.Error()
|
||||
}
|
||||
if cfg != nil && rawlocs[i].Current.Fn != nil {
|
||||
var err error
|
||||
scope := proc.FrameToScope(d.target, rawlocs[i])
|
||||
|
||||
Reference in New Issue
Block a user