From 5d6065c3ee56a55e282ee5bb88bf35e204358008 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 1 Dec 2020 16:53:38 +0300 Subject: [PATCH] vmcli: set breakpoint before the instruction Breakpoint should occur before actual instruction execution. --- pkg/vm/cli/cli.go | 29 +++++++++++++++++++---------- pkg/vm/context.go | 9 +++++++++ pkg/vm/vm.go | 2 +- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/pkg/vm/cli/cli.go b/pkg/vm/cli/cli.go index 7830d1798..05b1b9d4a 100644 --- a/pkg/vm/cli/cli.go +++ b/pkg/vm/cli/cli.go @@ -213,8 +213,13 @@ func handleIP(c *ishell.Context) { return } v := getVMFromContext(c) - ip, opcode := v.Context().CurrInstr() - c.Printf("instruction pointer at %d (%s)\n", ip, opcode) + ctx := v.Context() + if ctx.NextIP() < ctx.LenInstr() { + ip, opcode := v.Context().NextInstr() + c.Printf("instruction pointer at %d (%s)\n", ip, opcode) + } else { + c.Println("execution has finished") + } } func handleBreak(c *ishell.Context) { @@ -319,7 +324,6 @@ func runVMWithHandling(c *ishell.Context, v *vm.VM) { err := v.Run() if err != nil { c.Err(err) - return } checkAndPrintVMState(c, v) } @@ -331,16 +335,20 @@ func checkAndPrintVMState(c *ishell.Context, v *vm.VM) { var message string switch { case v.HasFailed(): - message = "FAILED" + message = "" // the error will be printed on return case v.HasHalted(): message = v.Stack("estack") case v.AtBreakpoint(): ctx := v.Context() - i, op := ctx.CurrInstr() - message = fmt.Sprintf("at breakpoint %d (%s)\n", i, op.String()) + if ctx.NextIP() < ctx.LenInstr() { + i, op := ctx.NextInstr() + message = fmt.Sprintf("at breakpoint %d (%s)", i, op) + } else { + message = "execution has finished" + } } if message != "" { - c.Printf(message) + c.Println(message) } } @@ -412,8 +420,9 @@ func handleStepType(c *ishell.Context, stepType string) { } if err != nil { c.Err(err) + } else { + handleIP(c) } - handleIP(c) changePrompt(c, v) } @@ -426,8 +435,8 @@ func handleOps(c *ishell.Context) { } func changePrompt(c ishell.Actions, v *vm.VM) { - if v.Ready() && v.Context().IP()-1 >= 0 { - c.SetPrompt(fmt.Sprintf("NEO-GO-VM %d > ", v.Context().IP()-1)) + if v.Ready() && v.Context().NextIP() >= 0 && v.Context().NextIP() < v.Context().LenInstr() { + c.SetPrompt(fmt.Sprintf("NEO-GO-VM %d > ", v.Context().NextIP())) } else { c.SetPrompt("NEO-GO-VM > ") } diff --git a/pkg/vm/context.go b/pkg/vm/context.go index 041df6b8e..ee2e6d3ca 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -143,6 +143,15 @@ func (c *Context) CurrInstr() (int, opcode.Opcode) { return c.ip, opcode.Opcode(c.prog[c.ip]) } +// NextInstr returns the next instruction and opcode. +func (c *Context) NextInstr() (int, opcode.Opcode) { + op := opcode.RET + if c.nextip < len(c.prog) { + op = opcode.Opcode(c.prog[c.nextip]) + } + return c.nextip, op +} + // Copy returns an new exact copy of c. func (c *Context) Copy() *Context { ctx := new(Context) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 145ecedc1..ad4135225 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -228,7 +228,7 @@ func (v *VM) AddBreakPoint(n int) { // instruction pointer. func (v *VM) AddBreakPointRel(n int) { ctx := v.Context() - v.AddBreakPoint(ctx.ip + n) + v.AddBreakPoint(ctx.nextip + n) } // LoadFile loads a program from the given path, ready to execute it.