Skip to content

Commit

Permalink
service/debugger: improve NomalLocationSpec.Find's heuristics (go-del…
Browse files Browse the repository at this point in the history
…ve#923)

When location spec is given and the base can be interpreted either in
source file name or function name, NomalLocationSpec searches both
the source file list and the function symbol list, and selects matching
candidates. Previously, all the matching candidates were added to one
single list regardless whether the candidate was from the source file
list or not. Then, later, Find tries to guess whether the candiate
was a function or a file based on a heuristic, i.e, whether the
candidate is an absolute file path. The heuristic is fragile - since
there is no guarantee that the included source file name is an absolute
path.

Instead, this CL preserves where the candidate was found; file list or
function symbol list. Then, use that info to determine whether the
candidate is a source file name or not.
  • Loading branch information
hyangah authored and derekparker committed Jul 20, 2017
1 parent 0cea7cc commit 809bdca
Showing 1 changed file with 42 additions and 39 deletions.
81 changes: 42 additions & 39 deletions service/debugger/locations.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,63 +327,66 @@ func (ale AmbiguousLocationError) Error() string {
}

func (loc *NormalLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) {
funcs := d.target.BinInfo().Funcs()
files := d.target.BinInfo().Sources()

candidates := []string{}
for file := range files {
limit := maxFindLocationCandidates
var candidateFiles []string
for file := range d.target.BinInfo().Sources() {
if loc.FileMatch(file) {
candidates = append(candidates, file)
if len(candidates) >= maxFindLocationCandidates {
candidateFiles = append(candidateFiles, file)
if len(candidateFiles) >= limit {
break
}
}
}

limit -= len(candidateFiles)

var candidateFuncs []string
if loc.FuncBase != nil {
for _, f := range funcs {
for _, f := range d.target.BinInfo().Funcs() {
if f.Sym == nil {
continue
}
if loc.FuncBase.Match(f.Sym) {
if loc.Base == f.Name {
// if an exact match for the function name is found use it
candidates = []string{f.Name}
break
}
if len(candidates) < maxFindLocationCandidates {
candidates = append(candidates, f.Name)
}
if !loc.FuncBase.Match(f.Sym) {
continue
}
if loc.Base == f.Name {
// if an exact match for the function name is found use it
candidateFuncs = []string{f.Name}
break
}
candidateFuncs = append(candidateFuncs, f.Name)
if len(candidateFuncs) >= limit {
break
}
}
}

switch len(candidates) {
case 1:
var addr uint64
var err error
if filepath.IsAbs(candidates[0]) {
if loc.LineOffset < 0 {
return nil, fmt.Errorf("Malformed breakpoint location, no line offset specified")
}
addr, err = proc.FindFileLocation(d.target, candidates[0], loc.LineOffset)
} else {
if loc.LineOffset < 0 {
addr, err = proc.FindFunctionLocation(d.target, candidates[0], true, 0)
} else {
addr, err = proc.FindFunctionLocation(d.target, candidates[0], false, loc.LineOffset)
}
if matching := len(candidateFiles) + len(candidateFuncs); matching == 0 {
return nil, fmt.Errorf("Location %q not found", locStr)
} else if matching > 1 {
return nil, AmbiguousLocationError{Location: locStr, CandidatesString: append(candidateFiles, candidateFuncs...)}
}

// len(candidateFiles) + len(candidateFuncs) == 1
var addr uint64
var err error
if len(candidateFiles) == 1 {
if loc.LineOffset < 0 {
return nil, fmt.Errorf("Malformed breakpoint location, no line offset specified")
}
if err != nil {
return nil, err
addr, err = proc.FindFileLocation(d.target, candidateFiles[0], loc.LineOffset)
} else { // len(candidateFUncs) == 1
if loc.LineOffset < 0 {
addr, err = proc.FindFunctionLocation(d.target, candidateFuncs[0], true, 0)
} else {
addr, err = proc.FindFunctionLocation(d.target, candidateFuncs[0], false, loc.LineOffset)
}
return []api.Location{{PC: addr}}, nil
}

case 0:
return nil, fmt.Errorf("Location \"%s\" not found", locStr)
default:
return nil, AmbiguousLocationError{Location: locStr, CandidatesString: candidates}
if err != nil {
return nil, err
}
return []api.Location{{PC: addr}}, nil
}

func (loc *OffsetLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string) ([]api.Location, error) {
Expand Down

0 comments on commit 809bdca

Please sign in to comment.