mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 01:27:16 +08:00
Improve variable evaluation scope
Properly scope variable evaluation to the function the traced process is currently stopped in.
This commit is contained in:
@ -7,6 +7,11 @@ type FooBar struct {
|
||||
Bur string
|
||||
}
|
||||
|
||||
func barfoo() {
|
||||
a1 := "bur"
|
||||
fmt.Println(a1)
|
||||
}
|
||||
|
||||
func foobar(baz string) {
|
||||
var (
|
||||
a1 = "foo"
|
||||
@ -21,6 +26,7 @@ func foobar(baz string) {
|
||||
f32 = float32(1.2)
|
||||
)
|
||||
|
||||
barfoo()
|
||||
fmt.Println(a1, a2, a3, a4, a5, a6, a7, baz, neg, i8, f32)
|
||||
}
|
||||
|
||||
|
||||
@ -24,20 +24,21 @@ func (dbp *DebuggedProcess) PrintGoroutinesInfo() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reader := data.Reader()
|
||||
|
||||
allglen, err := allglenval(dbp, data)
|
||||
allglen, err := allglenval(dbp, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
goidoffset, err := parsegoidoffset(dbp, data)
|
||||
goidoffset, err := parsegoidoffset(dbp, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
schedoffset, err := parseschedoffset(dbp, data)
|
||||
schedoffset, err := parseschedoffset(dbp, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
allgentryaddr, err := allgentryptr(dbp, data)
|
||||
allgentryaddr, err := allgentryptr(dbp, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -76,8 +77,8 @@ func printGoroutineInfo(dbp *DebuggedProcess, addr uint64, goidoffset, schedoffs
|
||||
return nil
|
||||
}
|
||||
|
||||
func allglenval(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
||||
entry, err := findDwarfEntry("runtime.allglen", data)
|
||||
func allglenval(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
entry, err := findDwarfEntry("runtime.allglen", reader)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -97,8 +98,8 @@ func allglenval(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
||||
return binary.LittleEndian.Uint64(val), nil
|
||||
}
|
||||
|
||||
func allgentryptr(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
||||
entry, err := findDwarfEntry("runtime.allg", data)
|
||||
func allgentryptr(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
entry, err := findDwarfEntry("runtime.allg", reader)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -115,8 +116,8 @@ func allgentryptr(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
||||
return uint64(addr), nil
|
||||
}
|
||||
|
||||
func parsegoidoffset(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
||||
entry, err := findDwarfEntry("goid", data)
|
||||
func parsegoidoffset(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
entry, err := findDwarfEntry("goid", reader)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -132,8 +133,8 @@ func parsegoidoffset(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
||||
return uint64(offset), nil
|
||||
}
|
||||
|
||||
func parseschedoffset(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
||||
entry, err := findDwarfEntry("sched", data)
|
||||
func parseschedoffset(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||
entry, err := findDwarfEntry("sched", reader)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -156,7 +157,18 @@ func (thread *ThreadContext) EvalSymbol(name string) (*Variable, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entry, err := findDwarfEntry(name, data)
|
||||
pc, err := thread.CurrentPC()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fn := thread.Process.GoSymTable.PCToFunc(pc)
|
||||
if fn == nil {
|
||||
return nil, fmt.Errorf("could not func function scope")
|
||||
}
|
||||
reader := data.Reader()
|
||||
err = findFunction(fn.Name, reader)
|
||||
|
||||
entry, err := findDwarfEntry(name, reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -184,9 +196,34 @@ func (thread *ThreadContext) EvalSymbol(name string) (*Variable, error) {
|
||||
return &Variable{Name: name, Type: t.String(), Value: val}, nil
|
||||
}
|
||||
|
||||
func findDwarfEntry(name string, data *dwarf.Data) (*dwarf.Entry, error) {
|
||||
reader := data.Reader()
|
||||
// findFunction is basically used to seek the dwarf.Reader to
|
||||
// the function entry that represents our current scope. From there
|
||||
// we can find the first child entry that matches the var name and
|
||||
// use it to determine the value of the variable.
|
||||
func findFunction(name string, reader *dwarf.Reader) error {
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if entry.Tag != dwarf.TagSubprogram {
|
||||
continue
|
||||
}
|
||||
|
||||
n, ok := entry.Val(dwarf.AttrName).(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if n == name {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findDwarfEntry(name string, reader *dwarf.Reader) (*dwarf.Entry, error) {
|
||||
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -24,7 +24,7 @@ func TestVariableEvaluation(t *testing.T) {
|
||||
{"a1", "foo", "struct string"},
|
||||
{"a2", "6", "int"},
|
||||
{"a3", "7.23", "float64"},
|
||||
{"a4", "[2]int [1 2]", "[97]int"},
|
||||
{"a4", "[2]int [1 2]", "[65]int"},
|
||||
{"a5", "len: 5 cap: 5 [1 2 3 4 5]", "struct []int"},
|
||||
{"a6", "main.FooBar {Baz: 8, Bur: word}", "main.FooBar"},
|
||||
{"a7", "*main.FooBar {Baz: 5, Bur: strum}", "*main.FooBar"},
|
||||
@ -35,7 +35,7 @@ func TestVariableEvaluation(t *testing.T) {
|
||||
}
|
||||
|
||||
helper.WithTestProcess(executablePath, t, func(p *proctl.DebuggedProcess) {
|
||||
pc, _, _ := p.GoSymTable.LineToPC(fp, 24)
|
||||
pc, _, _ := p.GoSymTable.LineToPC(fp, 29)
|
||||
|
||||
_, err := p.Break(uintptr(pc))
|
||||
assertNoError(err, t, "Break() returned an error")
|
||||
|
||||
Reference in New Issue
Block a user