diff --git a/proc/breakpoints.go b/proc/breakpoints.go index 8bc908c8..507888b4 100644 --- a/proc/breakpoints.go +++ b/proc/breakpoints.go @@ -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 { diff --git a/proc/proc_test.go b/proc/proc_test.go index fdf90fee..633feeb2 100644 --- a/proc/proc_test.go +++ b/proc/proc_test.go @@ -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 { diff --git a/proc/stack.go b/proc/stack.go index ab88c745..94687465 100644 --- a/proc/stack.go +++ b/proc/stack.go @@ -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 + return nil, err } - locations, err := thread.dbp.stacktrace(regs.PC(), regs.SP(), depth) - if err != nil { - return nil, 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 diff --git a/service/api/conversions.go b/service/api/conversions.go index b624d2f5..c97eadae 100644 --- a/service/api/conversions.go +++ b/service/api/conversions.go @@ -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, } } diff --git a/service/api/types.go b/service/api/types.go index c617f098..e8206b39 100644 --- a/service/api/types.go +++ b/service/api/types.go @@ -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. diff --git a/service/debugger/debugger.go b/service/debugger/debugger.go index 53d4a3a5..9456e7c8 100644 --- a/service/debugger/debugger.go +++ b/service/debugger/debugger.go @@ -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])) diff --git a/service/test/integration_test.go b/service/test/integration_test.go index e005e497..7853a5dd 100644 --- a/service/test/integration_test.go +++ b/service/test/integration_test.go @@ -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++ diff --git a/terminal/command.go b/terminal/command.go index 3f03d674..d7ff1ee5 100644 --- a/terminal/command.go +++ b/terminal/command.go @@ -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
[-stack