service,terminal: support logical breakpoints (#1742)
Changes CreateBreakpoint to create a logical breakpoint when multiple addresses are specified, FindLocation and the api.Location type to return logical locations and the cli to support logical breakpoints.
This commit is contained in:
parent
222deeec36
commit
e8d4ed7ece
@ -4,6 +4,7 @@ package terminal
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/parser"
|
||||
@ -1188,6 +1189,9 @@ func clearAll(t *Term, ctx callContext, args string) error {
|
||||
}
|
||||
locPCs = make(map[uint64]struct{})
|
||||
for _, loc := range locs {
|
||||
for _, pc := range loc.PCs {
|
||||
locPCs[pc] = struct{}{}
|
||||
}
|
||||
locPCs[loc.PC] = struct{}{}
|
||||
}
|
||||
}
|
||||
@ -1297,6 +1301,7 @@ func setBreakpoint(t *Term, ctx callContext, tracepoint bool, argstr string) err
|
||||
}
|
||||
for _, loc := range locs {
|
||||
requestedBp.Addr = loc.PC
|
||||
requestedBp.Addrs = loc.PCs
|
||||
|
||||
bp, err := t.client.CreateBreakpoint(requestedBp)
|
||||
if err != nil {
|
||||
@ -2222,9 +2227,24 @@ func formatBreakpointName(bp *api.Breakpoint, upcase bool) string {
|
||||
}
|
||||
|
||||
func formatBreakpointLocation(bp *api.Breakpoint) string {
|
||||
var out bytes.Buffer
|
||||
if len(bp.Addrs) > 0 {
|
||||
for i, addr := range bp.Addrs {
|
||||
if i == 0 {
|
||||
fmt.Fprintf(&out, "%#x", addr)
|
||||
} else {
|
||||
fmt.Fprintf(&out, ",%#x", addr)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// In case we are connecting to an older version of delve that does not return the Addrs field.
|
||||
fmt.Fprintf(&out, "%#x", bp.Addr)
|
||||
}
|
||||
fmt.Fprintf(&out, " for ")
|
||||
p := ShortenFilePath(bp.File)
|
||||
if bp.FunctionName != "" {
|
||||
return fmt.Sprintf("%#v for %s() %s:%d", bp.Addr, bp.FunctionName, p, bp.Line)
|
||||
fmt.Fprintf(&out, "%s() ", bp.FunctionName)
|
||||
}
|
||||
return fmt.Sprintf("%#v for %s:%d", bp.Addr, p, bp.Line)
|
||||
fmt.Fprintf(&out, "%s:%d", p, bp.Line)
|
||||
return out.String()
|
||||
}
|
||||
|
@ -126,11 +126,16 @@ type Thread struct {
|
||||
}
|
||||
|
||||
// Location holds program location information.
|
||||
// In most cases a Location object will represent a physical location, with
|
||||
// a single PC address held in the PC field.
|
||||
// FindLocations however returns logical locations that can either have
|
||||
// multiple PC addresses each (due to inlining) or no PC address at all.
|
||||
type Location struct {
|
||||
PC uint64 `json:"pc"`
|
||||
File string `json:"file"`
|
||||
Line int `json:"line"`
|
||||
Function *Function `json:"function,omitempty"`
|
||||
PCs []uint64 `json:"pcs,omitempty"`
|
||||
}
|
||||
|
||||
// Stackframe describes one frame in a stack trace.
|
||||
|
@ -446,6 +446,8 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin
|
||||
addrs, err = proc.FindFileLocation(d.target, fileName, requestedBp.Line)
|
||||
case len(requestedBp.FunctionName) > 0:
|
||||
addrs, err = proc.FindFunctionLocation(d.target, requestedBp.FunctionName, requestedBp.Line)
|
||||
case len(requestedBp.Addrs) > 0:
|
||||
addrs = requestedBp.Addrs
|
||||
default:
|
||||
addrs = []uint64{requestedBp.Addr}
|
||||
}
|
||||
|
@ -251,8 +251,8 @@ func (loc *RegexLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr st
|
||||
r := make([]api.Location, 0, len(matches))
|
||||
for i := range matches {
|
||||
addrs, _ := proc.FindFunctionLocation(d.target, matches[i], 0)
|
||||
for _, addr := range addrs {
|
||||
r = append(r, api.Location{PC: addr})
|
||||
if len(addrs) > 0 {
|
||||
r = append(r, addressesToLocation(addrs))
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
@ -283,7 +283,7 @@ func (loc *AddrLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr str
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []api.Location{{PC: uint64(pc)}}, nil
|
||||
return []api.Location{{PC: pc}}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("wrong expression kind: %v", v.Kind)
|
||||
}
|
||||
@ -389,25 +389,21 @@ func (loc *NormalLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr s
|
||||
return []api.Location{{File: candidateFiles[0], Line: loc.LineOffset}}, nil
|
||||
}
|
||||
}
|
||||
} else { // len(candidateFUncs) == 1
|
||||
} else { // len(candidateFuncs) == 1
|
||||
addrs, err = proc.FindFunctionLocation(d.target, candidateFuncs[0], loc.LineOffset)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return addressesToLocations(addrs), nil
|
||||
return []api.Location{addressesToLocation(addrs)}, nil
|
||||
}
|
||||
|
||||
func addressesToLocations(addrs []uint64) []api.Location {
|
||||
if addrs == nil {
|
||||
return nil
|
||||
func addressesToLocation(addrs []uint64) api.Location {
|
||||
if len(addrs) <= 0 {
|
||||
return api.Location{}
|
||||
}
|
||||
r := make([]api.Location, len(addrs))
|
||||
for i := range addrs {
|
||||
r[i] = api.Location{PC: addrs[i]}
|
||||
}
|
||||
return r
|
||||
return api.Location{PC: addrs[0], PCs: addrs}
|
||||
}
|
||||
|
||||
func (loc *OffsetLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string, includeNonExecutableLines bool) ([]api.Location, error) {
|
||||
@ -427,7 +423,7 @@ func (loc *OffsetLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr s
|
||||
return []api.Location{{File: file, Line: line + loc.Offset}}, nil
|
||||
}
|
||||
}
|
||||
return addressesToLocations(addrs), err
|
||||
return []api.Location{addressesToLocation(addrs)}, err
|
||||
}
|
||||
|
||||
func (loc *LineLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr string, includeNonExecutableLines bool) ([]api.Location, error) {
|
||||
@ -444,5 +440,5 @@ func (loc *LineLocationSpec) Find(d *Debugger, scope *proc.EvalScope, locStr str
|
||||
return []api.Location{{File: file, Line: loc.Line}}, nil
|
||||
}
|
||||
}
|
||||
return addressesToLocations(addrs), err
|
||||
return []api.Location{addressesToLocation(addrs)}, err
|
||||
}
|
||||
|
@ -231,6 +231,9 @@ type CreateBreakpointOut struct {
|
||||
// the breakpoint will be created on the specified function:line
|
||||
// location.
|
||||
//
|
||||
// - If arg.Breakpoint.Addrs is filled it will create a logical breakpoint
|
||||
// corresponding to all specified addresses.
|
||||
//
|
||||
// - Otherwise the value specified by arg.Breakpoint.Addr will be used.
|
||||
func (s *RPCServer) CreateBreakpoint(arg CreateBreakpointIn, out *CreateBreakpointOut) error {
|
||||
createdbp, err := s.debugger.CreateBreakpoint(&arg.Breakpoint)
|
||||
@ -577,7 +580,7 @@ type FindLocationOut struct {
|
||||
Locations []api.Location
|
||||
}
|
||||
|
||||
// FindLocation returns concrete location information described by a location expression
|
||||
// FindLocation returns concrete location information described by a location expression.
|
||||
//
|
||||
// loc ::= <filename>:<line> | <function>[:<line>] | /<regex>/ | (+|-)<offset> | <line> | *<address>
|
||||
// * <filename> can be the full path of a file or just a suffix
|
||||
|
Loading…
Reference in New Issue
Block a user