提交 6b99c5f5 编写于 作者: D Derek Parker

Cleanup tracepoint commit

* Cleanup comments
* Cleanup naming in certain instances
* Modify stacktrace to return current location
上级 3a96d8ee
......@@ -18,14 +18,16 @@ type Breakpoint struct {
OriginalData []byte // If software breakpoint, the data we replace with breakpoint instruction.
ID int // Monotonically increasing ID.
Temp bool // Whether this is a temp breakpoint (for next'ing).
hardware bool // Breakpoint using CPU debug registers.
reg int // If hardware breakpoint, what debug register it belongs to.
// Breakpoint informations
Tracepoint bool // tracepoint flag
Stacktrace int // number of stack frames to retrieve
Goroutine bool // retrieve goroutine information
Symbols []string // variables to evaluate
// Breakpoint information
Tracepoint bool // Tracepoint flag
Stacktrace int // Number of stack frames to retrieve
Goroutine bool // Retrieve goroutine information
Variables []string // Variables to evaluate
hardware bool // Breakpoint using CPU debug registers.
reg int // If hardware breakpoint, what debug register it belongs to.
}
func (bp *Breakpoint) String() string {
......
......@@ -443,8 +443,8 @@ func (l1 *loc) match(l2 Location) bool {
func TestStacktrace(t *testing.T) {
stacks := [][]loc{
[]loc{{8, "main.func1"}, {16, "main.main"}},
[]loc{{8, "main.func1"}, {12, "main.func2"}, {17, "main.main"}},
[]loc{{3, "main.stacktraceme"}, {8, "main.func1"}, {16, "main.main"}},
[]loc{{3, "main.stacktraceme"}, {8, "main.func1"}, {12, "main.func2"}, {17, "main.main"}},
}
withTestProcess("stacktraceprog", t, func(p *Process, fixture protest.Fixture) {
bp, err := p.SetBreakpointByLocation("main.stacktraceme")
......@@ -452,7 +452,7 @@ func TestStacktrace(t *testing.T) {
for i := range stacks {
assertNoError(p.Continue(), t, "Continue()")
_, locations, err := p.CurrentThread.Stacktrace(40)
locations, err := p.CurrentThread.Stacktrace(40)
assertNoError(err, t, "Stacktrace()")
if len(locations) != len(stacks[i])+2 {
......@@ -484,8 +484,8 @@ func stackMatch(stack []loc, locations []Location) bool {
}
func TestStacktraceGoroutine(t *testing.T) {
mainStack := []loc{{21, "main.main"}}
agoroutineStack := []loc{{-1, "runtime.goparkunlock"}, {-1, "runtime.chansend"}, {-1, "runtime.chansend1"}, {8, "main.agoroutine"}}
mainStack := []loc{{11, "main.stacktraceme"}, {21, "main.main"}}
agoroutineStack := []loc{{-1, "runtime.gopark"}, {-1, "runtime.goparkunlock"}, {-1, "runtime.chansend"}, {-1, "runtime.chansend1"}, {8, "main.agoroutine"}}
withTestProcess("goroutinestackprog", t, func(p *Process, fixture protest.Fixture) {
bp, err := p.SetBreakpointByLocation("main.stacktraceme")
......@@ -499,8 +499,8 @@ func TestStacktraceGoroutine(t *testing.T) {
agoroutineCount := 0
mainCount := 0
for _, g := range gs {
_, locations, _ := p.GoroutineStacktrace(g, 40)
for i, g := range gs {
locations, err := p.GoroutineStacktrace(g, 40)
assertNoError(err, t, "GoroutineStacktrace()")
if stackMatch(mainStack, locations) {
......@@ -510,7 +510,7 @@ func TestStacktraceGoroutine(t *testing.T) {
if stackMatch(agoroutineStack, locations) {
agoroutineCount++
} else {
t.Logf("Non-goroutine stack: (%d)", len(locations))
t.Logf("Non-goroutine stack: %d (%d)", i, len(locations))
for i := range locations {
name := ""
if locations[i].Fn != nil {
......
......@@ -7,39 +7,31 @@ import (
// Takes an offset from RSP and returns the address of the
// instruction the currect function is going to return to.
func (thread *Thread) ReturnAddress() (uint64, error) {
_, locations, err := thread.Stacktrace(1)
locations, err := thread.Stacktrace(2)
if err != nil {
return 0, err
}
return locations[0].PC, nil
return locations[1].PC, nil
}
// Returns the stack trace for thread
// Note that it doesn't include the current frame and the locations in the array are return addresses not call addresses
func (thread *Thread) Stacktrace(depth int) (*Location, []Location, error) {
loc, err := thread.Location()
if err != nil {
return nil, nil, err
}
// Returns the stack trace for thread.
// Note the locations in the array are return addresses not call addresses.
func (thread *Thread) Stacktrace(depth int) ([]Location, error) {
regs, err := thread.Registers()
if err != nil {
return nil, nil, err
}
locations, err := thread.dbp.stacktrace(regs.PC(), regs.SP(), depth)
if err != nil {
return nil, nil, err
return nil, err
}
return loc, locations, nil
return thread.dbp.stacktrace(regs.PC(), regs.SP(), depth)
}
// Returns the stack trace for a goroutine
// Note that it doesn't include the current frame and the locations in the array are return addresses not call addresses
func (dbp *Process) GoroutineStacktrace(g *G, depth int) (*Location, []Location, error) {
// Returns the stack trace for a goroutine.
// Note the locations in the array are return addresses not call addresses.
func (dbp *Process) GoroutineStacktrace(g *G, depth int) ([]Location, error) {
if g.thread != nil {
return g.thread.Stacktrace(depth)
}
locs, err := dbp.stacktrace(g.PC, g.SP, depth)
return dbp.GoroutineLocation(g), locs, err
return locs, err
}
func (dbp *Process) GoroutineLocation(g *G) *Location {
......@@ -61,6 +53,8 @@ func (dbp *Process) stacktrace(pc, sp uint64, depth int) ([]Location, error) {
locations []Location
retaddr uintptr
)
f, l, fn := dbp.PCToLine(pc)
locations = append(locations, Location{PC: pc, File: f, Line: l, Fn: fn})
for i := int64(0); i < int64(depth); i++ {
fde, err := dbp.frameEntries.FDEForPC(ret)
if err != nil {
......@@ -79,7 +73,7 @@ func (dbp *Process) stacktrace(pc, sp uint64, depth int) ([]Location, error) {
if ret <= 0 {
break
}
f, l, fn := dbp.goSymTable.PCToLine(ret)
f, l, fn = dbp.goSymTable.PCToLine(ret)
locations = append(locations, Location{PC: ret, File: f, Line: l, Fn: fn})
if fn != nil && fn.Name == "runtime.goexit" {
break
......
......@@ -2,6 +2,7 @@ package api
import (
"debug/gosym"
"github.com/derekparker/delve/proc"
)
......@@ -16,7 +17,7 @@ func ConvertBreakpoint(bp *proc.Breakpoint) *Breakpoint {
Tracepoint: bp.Tracepoint,
Stacktrace: bp.Stacktrace,
Goroutine: bp.Goroutine,
Symbols: bp.Symbols,
Variables: bp.Variables,
}
}
......
......@@ -38,7 +38,7 @@ type Breakpoint struct {
// retrieve goroutine information
Goroutine bool `json:"goroutine"`
// variables to evaluate
Symbols []string `json:"symbols,omitempty"`
Variables []string `json:"variables,omitempty"`
}
// Thread is a thread within the debugged process.
......
......@@ -108,7 +108,7 @@ func (d *Debugger) CreateBreakpoint(requestedBp *api.Breakpoint) (*api.Breakpoin
bp.Tracepoint = requestedBp.Tracepoint
bp.Goroutine = requestedBp.Goroutine
bp.Stacktrace = requestedBp.Stacktrace
bp.Symbols = requestedBp.Symbols
bp.Variables = requestedBp.Variables
createdBp = api.ConvertBreakpoint(bp)
log.Printf("created breakpoint: %#v", createdBp)
return createdBp, nil
......@@ -178,7 +178,7 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
state, err := d.State()
if err != nil {
return state, err
return nil, err
}
err = d.collectBreakpointInformation(state)
return state, err
......@@ -222,18 +222,18 @@ func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error
}
if bp.Stacktrace > 0 {
rawloc, rawlocs, err := d.process.CurrentThread.Stacktrace(bp.Stacktrace)
rawlocs, err := d.process.CurrentThread.Stacktrace(bp.Stacktrace)
if err != nil {
return err
}
bpi.Stacktrace = convertStacktrace(rawloc, rawlocs)
bpi.Stacktrace = convertStacktrace(rawlocs)
}
if len(bp.Symbols) > 0 {
bpi.Variables = make([]api.Variable, len(bp.Symbols))
if len(bp.Variables) > 0 {
bpi.Variables = make([]api.Variable, len(bp.Variables))
}
for i := range bp.Symbols {
v, err := d.process.CurrentThread.EvalVariable(bp.Symbols[i])
for i := range bp.Variables {
v, err := d.process.CurrentThread.EvalVariable(bp.Variables[i])
if err != nil {
return err
}
......@@ -367,11 +367,10 @@ func (d *Debugger) Goroutines() ([]*api.Goroutine, error) {
func (d *Debugger) Stacktrace(goroutineId, depth int) ([]api.Location, error) {
var rawlocs []proc.Location
var rawloc *proc.Location
var err error
if goroutineId < 0 {
rawloc, rawlocs, err = d.process.CurrentThread.Stacktrace(depth)
rawlocs, err = d.process.CurrentThread.Stacktrace(depth)
if err != nil {
return nil, err
}
......@@ -382,7 +381,7 @@ func (d *Debugger) Stacktrace(goroutineId, depth int) ([]api.Location, error) {
}
for _, g := range gs {
if g.Id == goroutineId {
rawloc, rawlocs, err = d.process.GoroutineStacktrace(g, depth)
rawlocs, err = d.process.GoroutineStacktrace(g, depth)
if err != nil {
return nil, err
}
......@@ -395,13 +394,11 @@ func (d *Debugger) Stacktrace(goroutineId, depth int) ([]api.Location, error) {
}
}
return convertStacktrace(rawloc, rawlocs), nil
return convertStacktrace(rawlocs), nil
}
func convertStacktrace(rawloc *proc.Location, rawlocs []proc.Location) []api.Location {
locations := make([]api.Location, 0, len(rawlocs)+1)
locations = append(locations, api.ConvertLocation(*rawloc))
func convertStacktrace(rawlocs []proc.Location) []api.Location {
locations := make([]api.Location, 0, len(rawlocs))
for i := range rawlocs {
rawlocs[i].Line--
locations = append(locations, api.ConvertLocation(rawlocs[i]))
......
......@@ -96,8 +96,7 @@ func TestClientServer_step(t *testing.T) {
t.Fatalf("Unexpected error: %v", err)
}
statech := c.Continue()
stateBefore := <-statech
stateBefore := <-c.Continue()
if stateBefore.Err != nil {
t.Fatalf("Unexpected error: %v", stateBefore.Err)
}
......@@ -375,13 +374,13 @@ func TestClientServer_infoArgs(t *testing.T) {
func TestClientServer_traceContinue(t *testing.T) {
withTestClient("integrationprog", t, func(c service.Client) {
fp := testProgPath(t, "integrationprog")
_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 15, Tracepoint: true, Goroutine: true, Stacktrace: 5, Symbols: []string{"i"}})
_, err := c.CreateBreakpoint(&api.Breakpoint{File: fp, Line: 15, Tracepoint: true, Goroutine: true, Stacktrace: 5, Variables: []string{"i"}})
if err != nil {
t.Fatalf("Unexpected error: %v\n", err)
}
count := 0
contch := c.Continue()
for state := range contch {
contChan := c.Continue()
for state := range contChan {
if state.Breakpoint != nil {
count++
......
......@@ -47,7 +47,7 @@ func DebugCommands(client service.Client) *Commands {
c.cmds = []command{
{aliases: []string{"help"}, cmdFn: c.help, helpMsg: "Prints the help message."},
{aliases: []string{"break", "b"}, cmdFn: breakpoint, helpMsg: "break <address> [-stack <n>|-goroutine|<variable name>]*\nSet break point at the entry point of a function, or at a specific file/line.\nWhen the breakpoint is reached the value of the specified variables will be printed, if -stack is specified the stack trace of the current goroutine will be printed, if -goroutine is specified informations about the current goroutine will be printed. Example: break foo.go:13"},
{aliases: []string{"trace"}, cmdFn: tracepoint, helpMsg: "Set tracepoint, takes the same arguments as break"},
{aliases: []string{"trace", "t"}, cmdFn: tracepoint, helpMsg: "Set tracepoint, takes the same arguments as break"},
{aliases: []string{"continue", "c"}, cmdFn: cont, helpMsg: "Run until breakpoint or program termination."},
{aliases: []string{"step", "si"}, cmdFn: step, helpMsg: "Single step through program."},
{aliases: []string{"next", "n"}, cmdFn: next, helpMsg: "Step over to next source line."},
......@@ -201,8 +201,8 @@ func formatGoroutine(g *api.Goroutine) string {
}
func cont(client service.Client, args ...string) error {
statech := client.Continue()
for state := range statech {
stateChan := client.Continue()
for state := range stateChan {
if state.Err != nil {
return state.Err
}
......@@ -289,8 +289,8 @@ func breakpoints(client service.Client, args ...string) error {
if bp.Goroutine {
attrs = append(attrs, "-goroutine")
}
for i := range bp.Symbols {
attrs = append(attrs, bp.Symbols[i])
for i := range bp.Variables {
attrs = append(attrs, bp.Variables[i])
}
if len(attrs) > 0 {
......@@ -301,7 +301,7 @@ func breakpoints(client service.Client, args ...string) error {
return nil
}
func breakpointIntl(client service.Client, tracepoint bool, args ...string) error {
func setBreakpoint(client service.Client, tracepoint bool, args ...string) error {
if len(args) < 1 {
return fmt.Errorf("address required, specify either a function name or <file:line>")
}
......@@ -335,7 +335,7 @@ func breakpointIntl(client service.Client, tracepoint bool, args ...string) erro
case "-goroutine":
requestedBp.Goroutine = true
default:
requestedBp.Symbols = append(requestedBp.Symbols, args[i])
requestedBp.Variables = append(requestedBp.Variables, args[i])
}
}
......@@ -356,11 +356,11 @@ func breakpointIntl(client service.Client, tracepoint bool, args ...string) erro
}
func breakpoint(client service.Client, args ...string) error {
return breakpointIntl(client, false, args...)
return setBreakpoint(client, false, args...)
}
func tracepoint(client service.Client, args ...string) error {
return breakpointIntl(client, true, args...)
return setBreakpoint(client, true, args...)
}
func printVar(client service.Client, args ...string) error {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册