vmcli: set breakpoint before the instruction

Breakpoint should occur before actual instruction execution.
This commit is contained in:
Evgenii Stratonikov 2020-12-01 16:53:38 +03:00 committed by Roman Khimov
parent 4a8259caea
commit 5d6065c3ee
3 changed files with 29 additions and 11 deletions

View file

@ -213,8 +213,13 @@ func handleIP(c *ishell.Context) {
return return
} }
v := getVMFromContext(c) v := getVMFromContext(c)
ip, opcode := v.Context().CurrInstr() ctx := v.Context()
c.Printf("instruction pointer at %d (%s)\n", ip, opcode) 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) { func handleBreak(c *ishell.Context) {
@ -319,7 +324,6 @@ func runVMWithHandling(c *ishell.Context, v *vm.VM) {
err := v.Run() err := v.Run()
if err != nil { if err != nil {
c.Err(err) c.Err(err)
return
} }
checkAndPrintVMState(c, v) checkAndPrintVMState(c, v)
} }
@ -331,16 +335,20 @@ func checkAndPrintVMState(c *ishell.Context, v *vm.VM) {
var message string var message string
switch { switch {
case v.HasFailed(): case v.HasFailed():
message = "FAILED" message = "" // the error will be printed on return
case v.HasHalted(): case v.HasHalted():
message = v.Stack("estack") message = v.Stack("estack")
case v.AtBreakpoint(): case v.AtBreakpoint():
ctx := v.Context() ctx := v.Context()
i, op := ctx.CurrInstr() if ctx.NextIP() < ctx.LenInstr() {
message = fmt.Sprintf("at breakpoint %d (%s)\n", i, op.String()) i, op := ctx.NextInstr()
message = fmt.Sprintf("at breakpoint %d (%s)", i, op)
} else {
message = "execution has finished"
}
} }
if message != "" { if message != "" {
c.Printf(message) c.Println(message)
} }
} }
@ -412,8 +420,9 @@ func handleStepType(c *ishell.Context, stepType string) {
} }
if err != nil { if err != nil {
c.Err(err) c.Err(err)
} else {
handleIP(c)
} }
handleIP(c)
changePrompt(c, v) changePrompt(c, v)
} }
@ -426,8 +435,8 @@ func handleOps(c *ishell.Context) {
} }
func changePrompt(c ishell.Actions, v *vm.VM) { func changePrompt(c ishell.Actions, v *vm.VM) {
if v.Ready() && v.Context().IP()-1 >= 0 { if v.Ready() && v.Context().NextIP() >= 0 && v.Context().NextIP() < v.Context().LenInstr() {
c.SetPrompt(fmt.Sprintf("NEO-GO-VM %d > ", v.Context().IP()-1)) c.SetPrompt(fmt.Sprintf("NEO-GO-VM %d > ", v.Context().NextIP()))
} else { } else {
c.SetPrompt("NEO-GO-VM > ") c.SetPrompt("NEO-GO-VM > ")
} }

View file

@ -143,6 +143,15 @@ func (c *Context) CurrInstr() (int, opcode.Opcode) {
return c.ip, opcode.Opcode(c.prog[c.ip]) 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. // Copy returns an new exact copy of c.
func (c *Context) Copy() *Context { func (c *Context) Copy() *Context {
ctx := new(Context) ctx := new(Context)

View file

@ -228,7 +228,7 @@ func (v *VM) AddBreakPoint(n int) {
// instruction pointer. // instruction pointer.
func (v *VM) AddBreakPointRel(n int) { func (v *VM) AddBreakPointRel(n int) {
ctx := v.Context() 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. // LoadFile loads a program from the given path, ready to execute it.