proc: added *BinaryInfo.AllPCsForFileLine for faster bulk queries (#1592)
Support for bulk queries makes the DWARF quality checker (github.com/dr2chase/dwarf-goodness/cmd/dwarf-goodness) run much more efficiently (replace quadratic cost with linear).
This commit is contained in:
parent
7afda8dbe0
commit
a25d2a2b24
@ -136,6 +136,36 @@ func (lineInfo *DebugLineInfo) AllPCsForFileLine(f string, l int) (pcs []uint64)
|
||||
return
|
||||
}
|
||||
|
||||
// AllPCsForFileLines Adds all PCs for a given file and set (domain of map) of lines
|
||||
// to the map value corresponding to each line.
|
||||
func (lineInfo *DebugLineInfo) AllPCsForFileLines(f string, m map[int][]uint64) {
|
||||
if lineInfo == nil {
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
lastAddr uint64
|
||||
sm = newStateMachine(lineInfo, lineInfo.Instructions)
|
||||
)
|
||||
|
||||
for {
|
||||
if err := sm.next(); err != nil {
|
||||
if lineInfo.Logf != nil {
|
||||
lineInfo.Logf("AllPCsForFileLine error: %v", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
if sm.address != lastAddr && sm.isStmt && sm.valid && sm.file == f {
|
||||
if pcs, ok := m[sm.line]; ok {
|
||||
pcs = append(pcs, sm.address)
|
||||
m[sm.line] = pcs
|
||||
lastAddr = sm.address
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var NoSourceError = errors.New("no source available")
|
||||
|
||||
// AllPCsBetween returns all PC addresses between begin and end (including both begin and end) that have the is_stmt flag set and do not belong to excludeFile:excludeLine
|
||||
|
@ -406,6 +406,20 @@ func (bi *BinaryInfo) AllPCsForFileLine(filename string, lineno int) []uint64 {
|
||||
return r
|
||||
}
|
||||
|
||||
// AllPCsForFileLines returns a map providing all PC addresses for filename and each line in linenos
|
||||
func (bi *BinaryInfo) AllPCsForFileLines(filename string, linenos []int) map[int][]uint64 {
|
||||
r := make(map[int][]uint64)
|
||||
for _, line := range linenos {
|
||||
r[line] = make([]uint64, 0, 1)
|
||||
}
|
||||
for _, cu := range bi.compileUnits {
|
||||
if cu.lineInfo.Lookup[filename] != nil {
|
||||
cu.lineInfo.AllPCsForFileLines(filename, r)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// PCToFunc returns the function containing the given PC address
|
||||
func (bi *BinaryInfo) PCToFunc(pc uint64) *Function {
|
||||
i := sort.Search(len(bi.Functions), func(i int) bool {
|
||||
|
@ -3629,6 +3629,27 @@ func checkFrame(frame proc.Stackframe, fnname, file string, line int, inlined bo
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestAllPCsForFileLines(t *testing.T) {
|
||||
if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{1, 10, -1, 0, 0, ""}) {
|
||||
// Versions of go before 1.10 do not have DWARF information for inlined calls
|
||||
t.Skip("inlining not supported")
|
||||
}
|
||||
withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining, func(p proc.Process, fixture protest.Fixture) {
|
||||
l2pcs := p.BinInfo().AllPCsForFileLines(fixture.Source, []int{7, 20})
|
||||
if len(l2pcs) != 2 {
|
||||
t.Fatalf("expected two map entries for %s:{%d,%d} (got %d: %v)", fixture.Source, 7, 20, len(l2pcs), l2pcs)
|
||||
}
|
||||
pcs := l2pcs[20]
|
||||
if len(pcs) < 1 {
|
||||
t.Fatalf("expected at least one location for %s:%d (got %d: %#x)", fixture.Source, 20, len(pcs), pcs)
|
||||
}
|
||||
pcs = l2pcs[7]
|
||||
if len(pcs) < 2 {
|
||||
t.Fatalf("expected at least two locations for %s:%d (got %d: %#x)", fixture.Source, 7, len(pcs), pcs)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestInlinedStacktraceAndVariables(t *testing.T) {
|
||||
if ver, _ := goversion.Parse(runtime.Version()); ver.Major >= 0 && !ver.AfterOrEqual(goversion.GoVersion{1, 10, -1, 0, 0, ""}) {
|
||||
// Versions of go before 1.10 do not have DWARF information for inlined calls
|
||||
@ -3680,7 +3701,7 @@ func TestInlinedStacktraceAndVariables(t *testing.T) {
|
||||
withTestProcessArgs("testinline", t, ".", []string{}, protest.EnableInlining, func(p proc.Process, fixture protest.Fixture) {
|
||||
pcs := p.BinInfo().AllPCsForFileLine(fixture.Source, 7)
|
||||
if len(pcs) < 2 {
|
||||
t.Fatalf("expected at least two locations for %s:%d (got %d: %#x)", fixture.Source, 6, len(pcs), pcs)
|
||||
t.Fatalf("expected at least two locations for %s:%d (got %d: %#x)", fixture.Source, 7, len(pcs), pcs)
|
||||
}
|
||||
for _, pc := range pcs {
|
||||
t.Logf("setting breakpoint at %#x\n", pc)
|
||||
|
Loading…
Reference in New Issue
Block a user