delve/pkg/dwarf/reader/variables.go
Alessandro Arzilli 7cd12c34fd
proc,dwarf: cache debug.Entry objects (#1931)
Instead of rescanning debug_info every time we want to read a function
(either to find inlined calls or its variables) cache the tree of
dwarf.Entry that we would generate and use that.

Benchmark before:

BenchmarkConditionalBreakpoints-4   	       1	5164689165 ns/op

Benchmark after:

BenchmarkConditionalBreakpoints-4   	       1	4817425836 ns/op

Updates #1549
2020-03-20 10:23:10 -07:00

42 lines
1.2 KiB
Go

package reader
import (
"debug/dwarf"
"github.com/go-delve/delve/pkg/dwarf/godwarf"
)
type Variable struct {
*godwarf.Tree
Depth int
}
// Variables returns a list of variables contained inside 'root'.
// If onlyVisible is true only variables visible at pc will be returned.
// If skipInlinedSubroutines is true inlined subroutines will be skipped
func Variables(root *godwarf.Tree, pc uint64, line int, onlyVisible, skipInlinedSubroutines bool) []Variable {
return variablesInternal(nil, root, 0, pc, line, onlyVisible, skipInlinedSubroutines)
}
func variablesInternal(v []Variable, root *godwarf.Tree, depth int, pc uint64, line int, onlyVisible, skipInlinedSubroutines bool) []Variable {
switch root.Tag {
case dwarf.TagInlinedSubroutine:
if skipInlinedSubroutines {
return v
}
fallthrough
case dwarf.TagLexDwarfBlock, dwarf.TagSubprogram:
if !onlyVisible || root.ContainsPC(pc) {
for _, child := range root.Children {
v = variablesInternal(v, child, depth+1, pc, line, onlyVisible, skipInlinedSubroutines)
}
}
return v
default:
if declLine, ok := root.Val(dwarf.AttrDeclLine).(int64); !ok || line >= int(declLine) {
return append(v, Variable{root, depth})
}
return v
}
}