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
This commit is contained in:
parent
59beb7b442
commit
43756cd864
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user