debugger: collect breakpoint information on next/step/stepout
A next/step/stepout command could hit a normal breakpoint, decorated with a list of variables to evaluate, if that happens the variable should be evaluated just as if the breakpoint was hit by a continue.
This commit is contained in:
parent
037aa01963
commit
cbf3e1c676
@ -5,12 +5,6 @@ This project adheres to Semantic Versioning.
|
||||
|
||||
All changes mention the author, unless contributed by me (@derekparker).
|
||||
|
||||
## [RELEASE TO BE DEFINED] DATE TO BE DEFINED
|
||||
|
||||
### Fixed
|
||||
|
||||
- Data races in tests (@aarzilli)
|
||||
|
||||
## [1.0.0-rc.2] DATE TO BE DEFINED
|
||||
|
||||
### Added
|
||||
@ -23,11 +17,13 @@ All changes mention the author, unless contributed by me (@derekparker).
|
||||
- Fix behavior of next, step and stepout with recursive functions (@aarzilli)
|
||||
- Parsing of maps with zero sized values (@aarzilli)
|
||||
- Typo in the documentation of `types` command (@custa)
|
||||
- Data races in tests (@aarzilli)
|
||||
|
||||
### Changed
|
||||
|
||||
- Switched from godeps to glide (@derekparker)
|
||||
- Better performance of linux native backend (@aarzilli)
|
||||
- Collect breakpoints information if necessary after a next, step or stepout command (@aarzilli)
|
||||
|
||||
## [1.0.0-rc.1] 2017-05-05
|
||||
|
||||
|
@ -494,6 +494,8 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
|
||||
err = d.target.RequestManualStop()
|
||||
}
|
||||
|
||||
withBreakpointInfo := true
|
||||
|
||||
d.processMutex.Lock()
|
||||
defer d.processMutex.Unlock()
|
||||
|
||||
@ -501,23 +503,6 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
|
||||
case api.Continue:
|
||||
log.Print("continuing")
|
||||
err = proc.Continue(d.target)
|
||||
if err != nil {
|
||||
if exitedErr, exited := err.(proc.ProcessExitedError); exited {
|
||||
state := &api.DebuggerState{}
|
||||
state.Exited = true
|
||||
state.ExitStatus = exitedErr.Status
|
||||
state.Err = errors.New(exitedErr.Error())
|
||||
return state, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
state, stateErr := d.state()
|
||||
if stateErr != nil {
|
||||
return state, stateErr
|
||||
}
|
||||
err = d.collectBreakpointInformation(state)
|
||||
return state, err
|
||||
|
||||
case api.Rewind:
|
||||
log.Print("rewinding")
|
||||
if err := d.target.Direction(proc.Backward); err != nil {
|
||||
@ -527,23 +512,6 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
|
||||
d.target.Direction(proc.Forward)
|
||||
}()
|
||||
err = proc.Continue(d.target)
|
||||
if err != nil {
|
||||
if exitedErr, exited := err.(proc.ProcessExitedError); exited {
|
||||
state := &api.DebuggerState{}
|
||||
state.Exited = true
|
||||
state.ExitStatus = exitedErr.Status
|
||||
state.Err = errors.New(exitedErr.Error())
|
||||
return state, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
state, stateErr := d.state()
|
||||
if stateErr != nil {
|
||||
return state, stateErr
|
||||
}
|
||||
err = d.collectBreakpointInformation(state)
|
||||
return state, err
|
||||
|
||||
case api.Next:
|
||||
log.Print("nexting")
|
||||
err = proc.Next(d.target)
|
||||
@ -559,16 +527,34 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
|
||||
case api.SwitchThread:
|
||||
log.Printf("switching to thread %d", command.ThreadID)
|
||||
err = d.target.SwitchThread(command.ThreadID)
|
||||
withBreakpointInfo = false
|
||||
case api.SwitchGoroutine:
|
||||
log.Printf("switching to goroutine %d", command.GoroutineID)
|
||||
err = d.target.SwitchGoroutine(command.GoroutineID)
|
||||
withBreakpointInfo = false
|
||||
case api.Halt:
|
||||
// RequestManualStop already called
|
||||
withBreakpointInfo = false
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if exitedErr, exited := err.(proc.ProcessExitedError); withBreakpointInfo && exited {
|
||||
state := &api.DebuggerState{}
|
||||
state.Exited = true
|
||||
state.ExitStatus = exitedErr.Status
|
||||
state.Err = errors.New(exitedErr.Error())
|
||||
return state, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return d.state()
|
||||
state, stateErr := d.state()
|
||||
if stateErr != nil {
|
||||
return state, stateErr
|
||||
}
|
||||
if withBreakpointInfo {
|
||||
err = d.collectBreakpointInformation(state)
|
||||
}
|
||||
return state, err
|
||||
}
|
||||
|
||||
func (d *Debugger) collectBreakpointInformation(state *api.DebuggerState) error {
|
||||
|
@ -1333,5 +1333,38 @@ func TestClientServer_ReverseContinue(t *testing.T) {
|
||||
t.Fatalf("Expected rewind to go back to the first breakpoint: %#x", state.CurrentThread.PC)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestClientServer_collectBreakpointInfoOnNext(t *testing.T) {
|
||||
protest.AllowRecording(t)
|
||||
withTestClient2("testnextprog", t, func(c service.Client) {
|
||||
_, err := c.CreateBreakpoint(&api.Breakpoint{
|
||||
Addr: findLocationHelper(t, c, "testnextprog.go:23", false, 1, 0)[0],
|
||||
Variables: []string{"j"},
|
||||
LoadLocals: &normalLoadConfig})
|
||||
assertNoError(err, t, "CreateBreakpoint()")
|
||||
_, err = c.CreateBreakpoint(&api.Breakpoint{
|
||||
Addr: findLocationHelper(t, c, "testnextprog.go:24", false, 1, 0)[0],
|
||||
Variables: []string{"j"},
|
||||
LoadLocals: &normalLoadConfig})
|
||||
assertNoError(err, t, "CreateBreakpoint()")
|
||||
|
||||
stateBefore := <-c.Continue()
|
||||
assertNoError(stateBefore.Err, t, "Continue()")
|
||||
if stateBefore.CurrentThread.Line != 23 {
|
||||
t.Fatalf("wrong line number %s:%d, expected %d", stateBefore.CurrentThread.File, stateBefore.CurrentThread.Line, 23)
|
||||
}
|
||||
if bi := stateBefore.CurrentThread.BreakpointInfo; bi == nil || len(bi.Variables) != 1 {
|
||||
t.Fatalf("bad breakpoint info %v", bi)
|
||||
}
|
||||
|
||||
stateAfter, err := c.Next()
|
||||
assertNoError(err, t, "Next()")
|
||||
if stateAfter.CurrentThread.Line != 24 {
|
||||
t.Fatalf("wrong line number %s:%d, expected %d", stateAfter.CurrentThread.File, stateAfter.CurrentThread.Line, 24)
|
||||
}
|
||||
if bi := stateAfter.CurrentThread.BreakpointInfo; bi == nil || len(bi.Variables) != 1 {
|
||||
t.Fatalf("bad breakpoint info %v", bi)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user