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
parent 2f39701d76
commit d7ffa89811
3 changed files with 29 additions and 11 deletions

View file

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

View file

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

View file

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