mirror of
https://github.com/go-delve/delve.git
synced 2025-11-01 12:01:35 +08:00
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:
@ -65,6 +65,14 @@ func NewFrameIndex() FrameDescriptionEntries {
|
|||||||
return make(FrameDescriptionEntries, 0, 1000)
|
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.
|
// Returns the Frame Description Entry for the given PC.
|
||||||
func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
|
func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry, error) {
|
||||||
idx := sort.Search(len(fdes), func(i int) bool {
|
idx := sort.Search(len(fdes), func(i int) bool {
|
||||||
@ -77,7 +85,7 @@ func (fdes FrameDescriptionEntries) FDEForPC(pc uint64) (*FrameDescriptionEntry,
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
if idx == len(fdes) {
|
if idx == len(fdes) {
|
||||||
return nil, fmt.Errorf("could not find FDE for PC %#v", pc)
|
return nil, &NoFDEForPCError{pc}
|
||||||
}
|
}
|
||||||
return fdes[idx], nil
|
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"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/derekparker/delve/dwarf/frame"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NoReturnAddr is returned when return address
|
// 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)
|
it.frame, it.err = it.dbp.frameInfo(it.pc, it.sp, it.top)
|
||||||
if it.err != nil {
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package proc
|
|||||||
import (
|
import (
|
||||||
"debug/gosym"
|
"debug/gosym"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -353,6 +354,9 @@ func (thread *Thread) Scope() (*EvalScope, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(locations) < 1 {
|
||||||
|
return nil, errors.New("could not decode first frame")
|
||||||
|
}
|
||||||
return locations[0].Scope(thread), nil
|
return locations[0].Scope(thread), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -422,9 +422,11 @@ func (g *G) UserCurrent() Location {
|
|||||||
it := newStackIterator(g.dbp, pc, sp)
|
it := newStackIterator(g.dbp, pc, sp)
|
||||||
for it.Next() {
|
for it.Next() {
|
||||||
frame := it.Frame()
|
frame := it.Frame()
|
||||||
name := frame.Call.Fn.Name
|
if frame.Call.Fn != nil {
|
||||||
if (strings.Index(name, ".") >= 0) && (!strings.HasPrefix(name, "runtime.") || isExportedRuntime(name)) {
|
name := frame.Call.Fn.Name
|
||||||
return frame.Call
|
if (strings.Index(name, ".") >= 0) && (!strings.HasPrefix(name, "runtime.") || isExportedRuntime(name)) {
|
||||||
|
return frame.Call
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return g.CurrentLoc
|
return g.CurrentLoc
|
||||||
|
|||||||
Reference in New Issue
Block a user