parent
4aee281520
commit
c6de961be8
@ -39,6 +39,7 @@ Command | Description
|
|||||||
Command | Description
|
Command | Description
|
||||||
--------|------------
|
--------|------------
|
||||||
[args](#args) | Print function arguments.
|
[args](#args) | Print function arguments.
|
||||||
|
[display](#display) | Print value of an expression every time the program stops.
|
||||||
[examinemem](#examinemem) | Examine memory:
|
[examinemem](#examinemem) | Examine memory:
|
||||||
[locals](#locals) | Print local variables.
|
[locals](#locals) | Print local variables.
|
||||||
[print](#print) | Evaluate an expression.
|
[print](#print) | Evaluate an expression.
|
||||||
@ -225,6 +226,17 @@ If no argument is specified the function being executed in the selected stack fr
|
|||||||
|
|
||||||
Aliases: disass
|
Aliases: disass
|
||||||
|
|
||||||
|
## display
|
||||||
|
Print value of an expression every time the program stops.
|
||||||
|
|
||||||
|
display -a <expression>
|
||||||
|
display -d <number>
|
||||||
|
|
||||||
|
The '-a' option adds an expression to the list of expression printed every time the program stops. The '-d' option removes the specified expression from the list.
|
||||||
|
|
||||||
|
If display is called without arguments it will print the value of all expression in the list.
|
||||||
|
|
||||||
|
|
||||||
## down
|
## down
|
||||||
Move the current frame down.
|
Move the current frame down.
|
||||||
|
|
||||||
@ -246,7 +258,7 @@ Aliases: ed
|
|||||||
## examinemem
|
## examinemem
|
||||||
Examine memory:
|
Examine memory:
|
||||||
|
|
||||||
examinemem [-fmt <format>] [-len <length>] <address>
|
examinemem [-fmt <format>] [-len <length>] <address>
|
||||||
|
|
||||||
Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal),.
|
Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal),.
|
||||||
Length is the number of bytes (default 1) and must be less than or equal to 1000.
|
Length is the number of bytes (default 1) and must be less than or equal to 1000.
|
||||||
|
@ -375,7 +375,7 @@ If locspec is omitted edit will open the current source file in the editor, othe
|
|||||||
|
|
||||||
{aliases: []string{"examinemem", "x"}, group: dataCmds, cmdFn: examineMemoryCmd, helpMsg: `Examine memory:
|
{aliases: []string{"examinemem", "x"}, group: dataCmds, cmdFn: examineMemoryCmd, helpMsg: `Examine memory:
|
||||||
|
|
||||||
examinemem [-fmt <format>] [-len <length>] <address>
|
examinemem [-fmt <format>] [-len <length>] <address>
|
||||||
|
|
||||||
Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal),.
|
Format represents the data format and the value is one of this list (default hex): bin(binary), oct(octal), dec(decimal), hex(hexadecimal),.
|
||||||
Length is the number of bytes (default 1) and must be less than or equal to 1000.
|
Length is the number of bytes (default 1) and must be less than or equal to 1000.
|
||||||
@ -384,6 +384,15 @@ Address is the memory location of the target to examine.
|
|||||||
For example:
|
For example:
|
||||||
|
|
||||||
x -fmt hex -len 20 0xc00008af38`},
|
x -fmt hex -len 20 0xc00008af38`},
|
||||||
|
|
||||||
|
{aliases: []string{"display"}, group: dataCmds, cmdFn: display, helpMsg: `Print value of an expression every time the program stops.
|
||||||
|
|
||||||
|
display -a <expression>
|
||||||
|
display -d <number>
|
||||||
|
|
||||||
|
The '-a' option adds an expression to the list of expression printed every time the program stops. The '-d' option removes the specified expression from the list.
|
||||||
|
|
||||||
|
If display is called without arguments it will print the value of all expression in the list.`},
|
||||||
}
|
}
|
||||||
|
|
||||||
if client == nil || client.Recorded() {
|
if client == nil || client.Recorded() {
|
||||||
@ -981,6 +990,7 @@ func restartRecorded(t *Term, ctx callContext, args string) error {
|
|||||||
}
|
}
|
||||||
printcontext(t, state)
|
printcontext(t, state)
|
||||||
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
||||||
|
t.onStop()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1057,6 +1067,7 @@ func (c *Commands) cont(t *Term, ctx callContext, args string) error {
|
|||||||
if ctx.Prefix == revPrefix {
|
if ctx.Prefix == revPrefix {
|
||||||
return c.rewind(t, ctx, args)
|
return c.rewind(t, ctx, args)
|
||||||
}
|
}
|
||||||
|
defer t.onStop()
|
||||||
c.frame = 0
|
c.frame = 0
|
||||||
stateChan := t.client.Continue()
|
stateChan := t.client.Continue()
|
||||||
var state *api.DebuggerState
|
var state *api.DebuggerState
|
||||||
@ -1072,6 +1083,7 @@ func (c *Commands) cont(t *Term, ctx callContext, args string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func continueUntilCompleteNext(t *Term, state *api.DebuggerState, op string, shouldPrintFile bool) error {
|
func continueUntilCompleteNext(t *Term, state *api.DebuggerState, op string, shouldPrintFile bool) error {
|
||||||
|
defer t.onStop()
|
||||||
if !state.NextInProgress {
|
if !state.NextInProgress {
|
||||||
if shouldPrintFile {
|
if shouldPrintFile {
|
||||||
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
printfile(t, state.CurrentThread.File, state.CurrentThread.Line, true)
|
||||||
@ -1141,6 +1153,8 @@ func (c *Commands) stepInstruction(t *Term, ctx callContext, args string) error
|
|||||||
return notOnFrameZeroErr
|
return notOnFrameZeroErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer t.onStop()
|
||||||
|
|
||||||
var fn func() (*api.DebuggerState, error)
|
var fn func() (*api.DebuggerState, error)
|
||||||
if ctx.Prefix == revPrefix {
|
if ctx.Prefix == revPrefix {
|
||||||
fn = t.client.ReverseStepInstruction
|
fn = t.client.ReverseStepInstruction
|
||||||
@ -2386,6 +2400,37 @@ func clearCheckpoint(t *Term, ctx callContext, args string) error {
|
|||||||
return t.client.ClearCheckpoint(id)
|
return t.client.ClearCheckpoint(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func display(t *Term, ctx callContext, args string) error {
|
||||||
|
const (
|
||||||
|
addOption = "-a "
|
||||||
|
delOption = "-d "
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
case args == "":
|
||||||
|
t.printDisplays()
|
||||||
|
|
||||||
|
case strings.HasPrefix(args, addOption):
|
||||||
|
args = strings.TrimSpace(args[len(addOption):])
|
||||||
|
if args == "" {
|
||||||
|
return fmt.Errorf("not enough arguments")
|
||||||
|
}
|
||||||
|
t.addDisplay(args)
|
||||||
|
t.printDisplay(len(t.displays) - 1)
|
||||||
|
|
||||||
|
case strings.HasPrefix(args, delOption):
|
||||||
|
args = strings.TrimSpace(args[len(delOption):])
|
||||||
|
n, err := strconv.Atoi(args)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%q is not a number", args)
|
||||||
|
}
|
||||||
|
return t.removeDisplay(n)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("wrong arguments")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func formatBreakpointName(bp *api.Breakpoint, upcase bool) string {
|
func formatBreakpointName(bp *api.Breakpoint, upcase bool) string {
|
||||||
thing := "breakpoint"
|
thing := "breakpoint"
|
||||||
if bp.Tracepoint {
|
if bp.Tracepoint {
|
||||||
|
@ -54,6 +54,7 @@ type Term struct {
|
|||||||
dumb bool
|
dumb bool
|
||||||
stdout io.Writer
|
stdout io.Writer
|
||||||
InitFile string
|
InitFile string
|
||||||
|
displays []string
|
||||||
|
|
||||||
starlarkEnv *starbind.Env
|
starlarkEnv *starbind.Env
|
||||||
|
|
||||||
@ -432,6 +433,50 @@ func (t *Term) loadConfig() api.LoadConfig {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Term) removeDisplay(n int) error {
|
||||||
|
if n < 0 || n >= len(t.displays) {
|
||||||
|
return fmt.Errorf("%d is out of range", n)
|
||||||
|
}
|
||||||
|
t.displays[n] = ""
|
||||||
|
for i := len(t.displays) - 1; i >= 0; i-- {
|
||||||
|
if t.displays[i] != "" {
|
||||||
|
t.displays = t.displays[:i+1]
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.displays = t.displays[:0]
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Term) addDisplay(expr string) {
|
||||||
|
t.displays = append(t.displays, expr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Term) printDisplay(i int) {
|
||||||
|
expr := t.displays[i]
|
||||||
|
val, err := t.client.EvalVariable(api.EvalScope{GoroutineID: -1}, expr, ShortLoadConfig)
|
||||||
|
if err != nil {
|
||||||
|
if isErrProcessExited(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("%d: %s = error %v\n", i, expr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("%d: %s = %s\n", i, val.Name, val.SinglelineString())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Term) printDisplays() {
|
||||||
|
for i := range t.displays {
|
||||||
|
if t.displays[i] != "" {
|
||||||
|
t.printDisplay(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Term) onStop() {
|
||||||
|
t.printDisplays()
|
||||||
|
}
|
||||||
|
|
||||||
// isErrProcessExited returns true if `err` is an RPC error equivalent of proc.ErrProcessExited
|
// isErrProcessExited returns true if `err` is an RPC error equivalent of proc.ErrProcessExited
|
||||||
func isErrProcessExited(err error) bool {
|
func isErrProcessExited(err error) bool {
|
||||||
rpcError, ok := err.(rpc.ServerError)
|
rpcError, ok := err.(rpc.ServerError)
|
||||||
|
Loading…
Reference in New Issue
Block a user