mirror of
https://github.com/go-delve/delve.git
synced 2025-10-30 10:17:03 +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
|
Bur string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func barfoo() {
|
||||||
|
a1 := "bur"
|
||||||
|
fmt.Println(a1)
|
||||||
|
}
|
||||||
|
|
||||||
func foobar(baz string) {
|
func foobar(baz string) {
|
||||||
var (
|
var (
|
||||||
a1 = "foo"
|
a1 = "foo"
|
||||||
@ -21,6 +26,7 @@ func foobar(baz string) {
|
|||||||
f32 = float32(1.2)
|
f32 = float32(1.2)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
barfoo()
|
||||||
fmt.Println(a1, a2, a3, a4, a5, a6, a7, baz, neg, i8, f32)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
reader := data.Reader()
|
||||||
|
|
||||||
allglen, err := allglenval(dbp, data)
|
allglen, err := allglenval(dbp, reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
goidoffset, err := parsegoidoffset(dbp, data)
|
goidoffset, err := parsegoidoffset(dbp, reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
schedoffset, err := parseschedoffset(dbp, data)
|
schedoffset, err := parseschedoffset(dbp, reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
allgentryaddr, err := allgentryptr(dbp, data)
|
allgentryaddr, err := allgentryptr(dbp, reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -76,8 +77,8 @@ func printGoroutineInfo(dbp *DebuggedProcess, addr uint64, goidoffset, schedoffs
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func allglenval(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
func allglenval(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||||
entry, err := findDwarfEntry("runtime.allglen", data)
|
entry, err := findDwarfEntry("runtime.allglen", reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -97,8 +98,8 @@ func allglenval(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
|||||||
return binary.LittleEndian.Uint64(val), nil
|
return binary.LittleEndian.Uint64(val), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func allgentryptr(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
func allgentryptr(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||||
entry, err := findDwarfEntry("runtime.allg", data)
|
entry, err := findDwarfEntry("runtime.allg", reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -115,8 +116,8 @@ func allgentryptr(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
|||||||
return uint64(addr), nil
|
return uint64(addr), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsegoidoffset(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
func parsegoidoffset(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||||
entry, err := findDwarfEntry("goid", data)
|
entry, err := findDwarfEntry("goid", reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -132,8 +133,8 @@ func parsegoidoffset(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
|||||||
return uint64(offset), nil
|
return uint64(offset), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseschedoffset(dbp *DebuggedProcess, data *dwarf.Data) (uint64, error) {
|
func parseschedoffset(dbp *DebuggedProcess, reader *dwarf.Reader) (uint64, error) {
|
||||||
entry, err := findDwarfEntry("sched", data)
|
entry, err := findDwarfEntry("sched", reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -156,7 +157,18 @@ func (thread *ThreadContext) EvalSymbol(name string) (*Variable, error) {
|
|||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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
|
return &Variable{Name: name, Type: t.String(), Value: val}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func findDwarfEntry(name string, data *dwarf.Data) (*dwarf.Entry, error) {
|
// findFunction is basically used to seek the dwarf.Reader to
|
||||||
reader := data.Reader()
|
// 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() {
|
for entry, err := reader.Next(); entry != nil; entry, err = reader.Next() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -24,7 +24,7 @@ func TestVariableEvaluation(t *testing.T) {
|
|||||||
{"a1", "foo", "struct string"},
|
{"a1", "foo", "struct string"},
|
||||||
{"a2", "6", "int"},
|
{"a2", "6", "int"},
|
||||||
{"a3", "7.23", "float64"},
|
{"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"},
|
{"a5", "len: 5 cap: 5 [1 2 3 4 5]", "struct []int"},
|
||||||
{"a6", "main.FooBar {Baz: 8, Bur: word}", "main.FooBar"},
|
{"a6", "main.FooBar {Baz: 8, Bur: word}", "main.FooBar"},
|
||||||
{"a7", "*main.FooBar {Baz: 5, Bur: strum}", "*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) {
|
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))
|
_, err := p.Break(uintptr(pc))
|
||||||
assertNoError(err, t, "Break() returned an error")
|
assertNoError(err, t, "Break() returned an error")
|
||||||
|
|||||||
Reference in New Issue
Block a user