cli: add 'jump' command

Close #2606.
This commit is contained in:
Anna Shaleva 2022-10-12 13:16:19 +03:00
parent 811e09675f
commit 884428ab93
2 changed files with 57 additions and 7 deletions

View file

@ -92,6 +92,15 @@ var commands = []cli.Command{
> break 12`, > break 12`,
Action: handleBreak, Action: handleBreak,
}, },
{
Name: "jump",
Usage: "Jump to the specified instruction (absolute IP value)",
UsageText: `jump <ip>`,
Description: `jump <ip>
<ip> is mandatory parameter, example:
> jump 12`,
Action: handleJump,
},
{ {
Name: "estack", Name: "estack",
Usage: "Show evaluation stack contents", Usage: "Show evaluation stack contents",
@ -559,21 +568,44 @@ func handleBreak(c *cli.Context) error {
if !checkVMIsReady(c.App) { if !checkVMIsReady(c.App) {
return nil return nil
} }
v := getVMFromContext(c.App) n, err := getInstructionParameter(c)
args := c.Args()
if len(args) != 1 {
return fmt.Errorf("%w: <ip>", ErrMissingParameter)
}
n, err := strconv.Atoi(args[0])
if err != nil { if err != nil {
return fmt.Errorf("%w: %s", ErrInvalidParameter, err) return err
} }
v := getVMFromContext(c.App)
v.AddBreakPoint(n) v.AddBreakPoint(n)
fmt.Fprintf(c.App.Writer, "breakpoint added at instruction %d\n", n) fmt.Fprintf(c.App.Writer, "breakpoint added at instruction %d\n", n)
return nil return nil
} }
func handleJump(c *cli.Context) error {
if !checkVMIsReady(c.App) {
return nil
}
n, err := getInstructionParameter(c)
if err != nil {
return err
}
v := getVMFromContext(c.App)
v.Context().Jump(n)
fmt.Fprintf(c.App.Writer, "jumped to instruction %d\n", n)
return nil
}
func getInstructionParameter(c *cli.Context) (int, error) {
args := c.Args()
if len(args) != 1 {
return 0, fmt.Errorf("%w: <ip>", ErrMissingParameter)
}
n, err := strconv.Atoi(args[0])
if err != nil {
return 0, fmt.Errorf("%w: %s", ErrInvalidParameter, err)
}
return n, nil
}
func handleXStack(c *cli.Context) error { func handleXStack(c *cli.Context) error {
v := getVMFromContext(c.App) v := getVMFromContext(c.App)
var stackDump string var stackDump string

View file

@ -11,6 +11,7 @@ import (
"math/big" "math/big"
"os" "os"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"sync" "sync"
"testing" "testing"
@ -1181,3 +1182,20 @@ func TestLoaddeployed(t *testing.T) {
e.checkStack(t, false) e.checkStack(t, false)
e.checkError(t, errors.New("contract hash, address or ID is mandatory argument")) e.checkError(t, errors.New("contract hash, address or ID is mandatory argument"))
} }
func TestJump(t *testing.T) {
buf := io.NewBufBinWriter()
emit.Opcodes(buf.BinWriter, opcode.PUSH1, opcode.PUSH2, opcode.ABORT) // some garbage
jmpTo := buf.Len()
emit.Opcodes(buf.BinWriter, opcode.PUSH4, opcode.PUSH5, opcode.ADD) // useful script
e := newTestVMCLI(t)
e.runProg(t,
"loadhex "+hex.EncodeToString(buf.Bytes()),
"jump "+strconv.Itoa(jmpTo),
"run",
)
e.checkNextLine(t, "READY: loaded 6 instructions")
e.checkNextLine(t, fmt.Sprintf("jumped to instruction %d", jmpTo))
e.checkStack(t, 9)
}