mirror of
https://github.com/go-delve/delve.git
synced 2025-10-28 04:35:19 +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
|
Ret uint64
|
||||||
// Address to the memory location containing the return address
|
// Address to the memory location containing the return address
|
||||||
addrret uint64
|
addrret uint64
|
||||||
|
// Err is set if an error occoured during stacktrace
|
||||||
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stacktrace returns the stack trace for thread.
|
// 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)
|
f, l, fn := it.bi.PCToLine(pc)
|
||||||
ret, err := readUintRaw(it.mem, retaddr, int64(it.bi.Arch.PtrSize()))
|
ret, err := readUintRaw(it.mem, retaddr, int64(it.bi.Arch.PtrSize()))
|
||||||
if err != nil {
|
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}
|
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 {
|
if !top {
|
||||||
@ -231,7 +233,10 @@ func (it *stackIterator) stacktrace(depth int) ([]Stackframe, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := it.Err(); err != nil {
|
if err := it.Err(); err != nil {
|
||||||
return nil, err
|
if len(frames) == 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
frames = append(frames, Stackframe{Err: err})
|
||||||
}
|
}
|
||||||
return frames, nil
|
return frames, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1210,6 +1210,10 @@ func printStack(stack []api.Stackframe, ind string) {
|
|||||||
s := ind + strings.Repeat(" ", d+2+len(ind))
|
s := ind + strings.Repeat(" ", d+2+len(ind))
|
||||||
|
|
||||||
for i := range stack {
|
for i := range stack {
|
||||||
|
if stack[i].Err != "" {
|
||||||
|
fmt.Printf("%serror: %s\n", s, stack[i].Err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
name := "(nil)"
|
name := "(nil)"
|
||||||
if stack[i].Function != nil {
|
if stack[i].Function != nil {
|
||||||
name = stack[i].Function.Name
|
name = stack[i].Function.Name
|
||||||
|
|||||||
@ -216,7 +216,7 @@ func TestExecuteFile(t *testing.T) {
|
|||||||
|
|
||||||
func TestIssue354(t *testing.T) {
|
func TestIssue354(t *testing.T) {
|
||||||
printStack([]api.Stackframe{}, "")
|
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) {
|
func TestIssue411(t *testing.T) {
|
||||||
|
|||||||
@ -121,6 +121,7 @@ type Stackframe struct {
|
|||||||
Locals []Variable
|
Locals []Variable
|
||||||
Arguments []Variable
|
Arguments []Variable
|
||||||
FrameOffset int64
|
FrameOffset int64
|
||||||
|
Err string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (frame *Stackframe) Var(name string) *Variable {
|
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),
|
Location: api.ConvertLocation(rawlocs[i].Call),
|
||||||
FrameOffset: rawlocs[i].CFA - int64(rawlocs[i].StackHi),
|
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 {
|
if cfg != nil && rawlocs[i].Current.Fn != nil {
|
||||||
var err error
|
var err error
|
||||||
scope := proc.FrameToScope(d.target, rawlocs[i])
|
scope := proc.FrameToScope(d.target, rawlocs[i])
|
||||||
|
|||||||
Reference in New Issue
Block a user