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
}
v := getVMFromContext(c)
ip, opcode := v.Context().CurrInstr()
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)
}
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 > ")
}

View file

@ -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)

View file

@ -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.