提交 43756cd8 编写于 作者: A aarzilli 提交者: Derek Parker

proc: bugfix: Truncate stacktrace when FDE of a frame can not be found

Instead of returning an error when FDE of a frame can not be found,
just truncate the stack trace.

Fixes #462
上级 59beb7b4
......@@ -65,6 +65,14 @@ func NewFrameIndex() FrameDescriptionEntries {
return make(FrameDescriptionEntries, 0, 1000)
}
type NoFDEForPCError struct {
PC uint64
}
func (err *NoFDEForPCError) Error() string {
return fmt.Sprintf("could not find FDE for PC %#v", err.PC)
}
// Returns the Frame Description Entry for the given PC.
func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
idx := sort.Search(len(fdes), func(i int) bool {
......@@ -77,7 +85,7 @@ func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry,
return true
})
if idx == len(fdes) {
return nil, fmt.Errorf("could not find FDE for PC %#v", pc)
return nil, &NoFDEForPCError{pc}
}
return fdes[idx], nil
}
......
......@@ -1655,3 +1655,33 @@ func TestPanicBreakpoint(t *testing.T) {
}
})
}
func TestIssue462(t *testing.T) {
// Stacktrace of Goroutine 0 fails with an error
if runtime.GOOS == "windows" {
return
}
withTestProcess("testnextnethttp", t, func(p *Process, fixture protest.Fixture) {
go func() {
for !p.Running() {
time.Sleep(50 * time.Millisecond)
}
// Wait for program to start listening.
for {
conn, err := net.Dial("tcp", "localhost:9191")
if err == nil {
conn.Close()
break
}
time.Sleep(50 * time.Millisecond)
}
p.RequestManualStop()
}()
assertNoError(p.Continue(), t, "Continue()")
_, err := p.CurrentThread.Stacktrace(40)
assertNoError(err, t, "Stacktrace()")
})
}
......@@ -4,6 +4,7 @@ import (
"encoding/binary"
"errors"
"fmt"
"github.com/derekparker/delve/dwarf/frame"
)
// NoReturnAddr is returned when return address
......@@ -101,6 +102,12 @@ func (it *StackIterator) Next() bool {
}
it.frame, it.err = it.dbp.frameInfo(it.pc, it.sp, it.top)
if it.err != nil {
if _, nofde := it.err.(*frame.NoFDEForPCError); nofde && !it.top {
it.frame = Stackframe{ Current: Location{ PC: it.pc, File: "?", Line: -1 }, Call: Location{ PC: it.pc, File: "?", Line: -1 }, CFA: 0, Ret: 0 }
it.atend = true
it.err = nil
return true
}
return false
}
......
......@@ -3,6 +3,7 @@ package proc
import (
"debug/gosym"
"encoding/binary"
"errors"
"fmt"
"path/filepath"
"reflect"
......@@ -353,6 +354,9 @@ func (thread *Thread) Scope() (*EvalScope, error) {
if err != nil {
return nil, err
}
if len(locations) < 1 {
return nil, errors.New("could not decode first frame")
}
return locations[0].Scope(thread), nil
}
......
......@@ -422,9 +422,11 @@ func (g *G) UserCurrent() Location {
it := newStackIterator(g.dbp, pc, sp)
for it.Next() {
frame := it.Frame()
name := frame.Call.Fn.Name
if (strings.Index(name, ".") >= 0) && (!strings.HasPrefix(name, "runtime.") || isExportedRuntime(name)) {
return frame.Call
if frame.Call.Fn != nil {
name := frame.Call.Fn.Name
if (strings.Index(name, ".") >= 0) && (!strings.HasPrefix(name, "runtime.") || isExportedRuntime(name)) {
return frame.Call
}
}
}
return g.CurrentLoc
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册