terminal,service: Add support for rev prefix and step-instruction (#1596)
Support for rev {next,step} is not currently implemented.
This commit is contained in:
parent
1758823429
commit
c7d1692e92
@ -32,6 +32,7 @@ Command | Description
|
||||
[print](#print) | Evaluate an expression.
|
||||
[regs](#regs) | Print contents of CPU registers.
|
||||
[restart](#restart) | Restart process from a checkpoint or event.
|
||||
[rev](#rev) | Reverses the execution of the target program for the command specified.
|
||||
[rewind](#rewind) | Run backwards until breakpoint or program termination.
|
||||
[set](#set) | Changes the value of a variable.
|
||||
[source](#source) | Executes a file containing a list of delve commands
|
||||
@ -329,6 +330,11 @@ Restart process from a checkpoint or event.
|
||||
|
||||
Aliases: r
|
||||
|
||||
## rev
|
||||
Reverses the execution of the target program for the command specified.
|
||||
Currently, only the rev step-instruction command is supported.
|
||||
|
||||
|
||||
## rewind
|
||||
Run backwards until breakpoint or program termination.
|
||||
|
||||
|
@ -34,6 +34,7 @@ const (
|
||||
noPrefix = cmdPrefix(0)
|
||||
onPrefix = cmdPrefix(1 << iota)
|
||||
deferredPrefix
|
||||
revPrefix
|
||||
)
|
||||
|
||||
type callContext struct {
|
||||
@ -136,7 +137,7 @@ the arguments. With -noargs, the process starts with an empty commandline.
|
||||
`},
|
||||
{aliases: []string{"continue", "c"}, cmdFn: c.cont, helpMsg: "Run until breakpoint or program termination."},
|
||||
{aliases: []string{"step", "s"}, cmdFn: c.step, helpMsg: "Single step through program."},
|
||||
{aliases: []string{"step-instruction", "si"}, cmdFn: c.stepInstruction, helpMsg: "Single step a single cpu instruction."},
|
||||
{aliases: []string{"step-instruction", "si"}, allowedPrefixes: revPrefix, cmdFn: c.stepInstruction, helpMsg: "Single step a single cpu instruction."},
|
||||
{aliases: []string{"next", "n"}, cmdFn: c.next, helpMsg: "Step over to next source line."},
|
||||
{aliases: []string{"stepout"}, cmdFn: c.stepout, helpMsg: "Step out of the current function."},
|
||||
{aliases: []string{"call"}, cmdFn: c.call, helpMsg: `Resumes process, injecting a function call (EXPERIMENTAL!!!)
|
||||
@ -379,6 +380,12 @@ The "note" is arbitrary text that can be used to identify the checkpoint, if it
|
||||
helpMsg: `Deletes checkpoint.
|
||||
|
||||
clear-checkpoint <id>`,
|
||||
})
|
||||
c.cmds = append(c.cmds, command{
|
||||
aliases: []string{"rev"},
|
||||
cmdFn: c.revCmd,
|
||||
helpMsg: `Reverses the execution of the target program for the command specified.
|
||||
Currently, only the rev step-instruction command is supported.`,
|
||||
})
|
||||
for i := range c.cmds {
|
||||
v := &c.cmds[i]
|
||||
@ -988,7 +995,15 @@ func (c *Commands) stepInstruction(t *Term, ctx callContext, args string) error
|
||||
if c.frame != 0 {
|
||||
return notOnFrameZeroErr
|
||||
}
|
||||
state, err := exitedToError(t.client.StepInstruction())
|
||||
|
||||
var fn func() (*api.DebuggerState, error)
|
||||
if ctx.Prefix == revPrefix {
|
||||
fn = t.client.ReverseStepInstruction
|
||||
} else {
|
||||
fn = t.client.StepInstruction
|
||||
}
|
||||
|
||||
state, err := exitedToError(fn())
|
||||
if err != nil {
|
||||
printcontextNoState(t)
|
||||
return err
|
||||
@ -998,6 +1013,18 @@ func (c *Commands) stepInstruction(t *Term, ctx callContext, args string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) revCmd(t *Term, ctx callContext, args string) error {
|
||||
if len(args) == 0 {
|
||||
return errors.New("not enough arguments")
|
||||
}
|
||||
|
||||
ctx.Prefix = revPrefix
|
||||
if err := c.CallWithContext(args, t, ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Commands) next(t *Term, ctx callContext, args string) error {
|
||||
if err := scopePrefixSwitch(t, ctx); err != nil {
|
||||
return err
|
||||
|
@ -356,6 +356,8 @@ const (
|
||||
StepOut = "stepOut"
|
||||
// StepInstruction continues for exactly 1 cpu instruction.
|
||||
StepInstruction = "stepInstruction"
|
||||
// ReverseStepInstruction reverses execution for exactly 1 cpu instruction.
|
||||
ReverseStepInstruction = "reverseStepInstruction"
|
||||
// Next continues to the next source line, not entering function calls.
|
||||
Next = "next"
|
||||
// SwitchThread switches the debugger's current thread context.
|
||||
|
@ -43,6 +43,8 @@ type Client interface {
|
||||
|
||||
// SingleStep will step a single cpu instruction.
|
||||
StepInstruction() (*api.DebuggerState, error)
|
||||
// ReverseSingleStep will reverse step a single cpu instruction.
|
||||
ReverseStepInstruction() (*api.DebuggerState, error)
|
||||
// SwitchThread switches the current thread context.
|
||||
SwitchThread(threadID int) (*api.DebuggerState, error)
|
||||
// SwitchGoroutine switches the current goroutine (and the current thread as well)
|
||||
|
@ -624,6 +624,15 @@ func (d *Debugger) Command(command *api.DebuggerCommand) (*api.DebuggerState, er
|
||||
case api.StepInstruction:
|
||||
d.log.Debug("single stepping")
|
||||
err = d.target.StepInstruction()
|
||||
case api.ReverseStepInstruction:
|
||||
d.log.Debug("reverse single stepping")
|
||||
if err := d.target.Direction(proc.Backward); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
d.target.Direction(proc.Forward)
|
||||
}()
|
||||
err = d.target.StepInstruction()
|
||||
case api.StepOut:
|
||||
d.log.Debug("step out")
|
||||
err = proc.StepOut(d.target)
|
||||
|
@ -125,6 +125,12 @@ func (c *RPCClient) StepInstruction() (*api.DebuggerState, error) {
|
||||
return state, err
|
||||
}
|
||||
|
||||
func (c *RPCClient) ReverseStepInstruction() (*api.DebuggerState, error) {
|
||||
state := new(api.DebuggerState)
|
||||
err := c.call("Command", &api.DebuggerCommand{Name: api.ReverseStepInstruction}, state)
|
||||
return state, err
|
||||
}
|
||||
|
||||
func (c *RPCClient) SwitchThread(threadID int) (*api.DebuggerState, error) {
|
||||
state := new(api.DebuggerState)
|
||||
cmd := &api.DebuggerCommand{
|
||||
|
@ -160,6 +160,12 @@ func (c *RPCClient) StepInstruction() (*api.DebuggerState, error) {
|
||||
return &out.State, err
|
||||
}
|
||||
|
||||
func (c *RPCClient) ReverseStepInstruction() (*api.DebuggerState, error) {
|
||||
var out CommandOut
|
||||
err := c.call("Command", api.DebuggerCommand{Name: api.ReverseStepInstruction}, &out)
|
||||
return &out.State, err
|
||||
}
|
||||
|
||||
func (c *RPCClient) SwitchThread(threadID int) (*api.DebuggerState, error) {
|
||||
var out CommandOut
|
||||
cmd := api.DebuggerCommand{
|
||||
|
Loading…
Reference in New Issue
Block a user