From 809bdca1917009d2a2a1b94d8d1dc0c954841470 Mon Sep 17 00:00:00 2001 From: Hyang-Ah Hana Kim Date: Thu, 20 Jul 2017 15:02:59 -0400 Subject: [PATCH] service/debugger: improve NomalLocationSpec.Find's heuristics (#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. --- service/debugger/locations.go | 81 ++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/service/debugger/locations.go b/service/debugger/locations.go index 3f6016a1..319babbe 100644 --- a/service/debugger/locations.go +++ b/service/debugger/locations.go @@ -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) { -- GitLab