From d7ffa89811d94c63568902bc587e609c68f30cc5 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 53d6bc8df..db3a7b894 100644 --- a/pkg/vm/cli/cli.go +++ b/pkg/vm/cli/cli.go @@ -226,8 +226,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) { @@ -341,22 +346,25 @@ func runVMWithHandling(c *ishell.Context, v *vm.VM) { err := v.Run() if err != nil { c.Err(err) - return } 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) } } @@ -419,8 +427,9 @@ func handleStepType(c *ishell.Context, stepType string) { } if err != nil { c.Err(err) + } else { + handleIP(c) } - handleIP(c) changePrompt(c, v) } @@ -435,8 +444,8 @@ func handleOps(c *ishell.Context) { } func changePrompt(c ishell.Actions, v *vm.VM) { - if v.Ready() && v.Context().IP() >= 0 { - c.SetPrompt(fmt.Sprintf("NEO-GO-VM %d > ", v.Context().IP())) + 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 85d6e2611..6cb7300a3 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -185,6 +185,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 63a020b05..c96ad4676 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -241,7 +241,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 in NEF format from the given path, ready to execute it.