提交 cbf3e1c6 编写于 作者: A aarzilli 提交者: Alessandro Arzilli

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.
上级 037aa019
......@@ -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)
}
})
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册