mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 23:25:22 +00:00
vm: add stepInto,stepOver,stepOut
Original C# vm debugger behavior
This commit is contained in:
parent
aab2f9a837
commit
591d5eafbe
2 changed files with 124 additions and 0 deletions
|
@ -128,6 +128,30 @@ Example:
|
|||
> step 10`,
|
||||
Func: handleStep,
|
||||
},
|
||||
{
|
||||
Name: "stepinto",
|
||||
Help: "Stepinto instruction to take in the debugger",
|
||||
LongHelp: `Usage: stepInto
|
||||
example:
|
||||
> stepinto`,
|
||||
Func: handleStepInto,
|
||||
},
|
||||
{
|
||||
Name: "stepout",
|
||||
Help: "Stepout instruction to take in the debugger",
|
||||
LongHelp: `Usage: stepOut
|
||||
example:
|
||||
> stepout`,
|
||||
Func: handleStepOut,
|
||||
},
|
||||
{
|
||||
Name: "stepover",
|
||||
Help: "Stepover instruction to take in the debugger",
|
||||
LongHelp: `Usage: stepOver
|
||||
example:
|
||||
> stepover`,
|
||||
Func: handleStepOver,
|
||||
},
|
||||
{
|
||||
Name: "ops",
|
||||
Help: "Dump opcodes of the current loaded program",
|
||||
|
@ -297,6 +321,34 @@ func handleStep(c *ishell.Context) {
|
|||
changePrompt(c, v)
|
||||
}
|
||||
|
||||
func handleStepInto(c *ishell.Context) {
|
||||
handleStepType(c, "into")
|
||||
}
|
||||
|
||||
func handleStepOut(c *ishell.Context) {
|
||||
handleStepType(c, "out")
|
||||
}
|
||||
|
||||
func handleStepOver(c *ishell.Context) {
|
||||
handleStepType(c, "over")
|
||||
}
|
||||
|
||||
func handleStepType(c *ishell.Context, stepType string) {
|
||||
if !checkVMIsReady(c) {
|
||||
return
|
||||
}
|
||||
v := getVMFromContext(c)
|
||||
switch stepType {
|
||||
case "into":
|
||||
v.StepInto()
|
||||
case "out":
|
||||
v.StepOut()
|
||||
case "over":
|
||||
v.StepOver()
|
||||
}
|
||||
changePrompt(c, v)
|
||||
}
|
||||
|
||||
func handleOps(c *ishell.Context) {
|
||||
if !checkVMIsReady(c) {
|
||||
return
|
||||
|
|
72
pkg/vm/vm.go
72
pkg/vm/vm.go
|
@ -289,12 +289,84 @@ func (v *VM) Step() {
|
|||
v.execute(ctx, op, param)
|
||||
}
|
||||
|
||||
// StepInto behaves the same as “step over” in case if the line does not contain a function it otherwise
|
||||
// the debugger will enter the called function and continue line-by-line debugging there.
|
||||
func (v *VM) StepInto() {
|
||||
ctx := v.Context()
|
||||
|
||||
if ctx == nil {
|
||||
v.state |= haltState
|
||||
}
|
||||
|
||||
if v.HasStopped() {
|
||||
return
|
||||
}
|
||||
|
||||
if ctx != nil && ctx.prog != nil {
|
||||
op, param, err := ctx.Next()
|
||||
if err != nil {
|
||||
log.Printf("error encountered at instruction %d (%s)", ctx.ip, op)
|
||||
log.Println(err)
|
||||
v.state = faultState
|
||||
}
|
||||
v.execute(ctx, op, param)
|
||||
i, op := ctx.CurrInstr()
|
||||
fmt.Printf("at breakpoint %d (%s)\n", i, op.String())
|
||||
}
|
||||
|
||||
cctx := v.Context()
|
||||
if cctx != nil && cctx.atBreakPoint() {
|
||||
v.state = breakState
|
||||
}
|
||||
}
|
||||
|
||||
// StepOut takes the debugger to the line where the current function was called.
|
||||
func (v *VM) StepOut() {
|
||||
if v.state == breakState {
|
||||
v.state = noneState
|
||||
} else {
|
||||
v.state = breakState
|
||||
}
|
||||
|
||||
expSize := v.istack.len
|
||||
for v.state.HasFlag(noneState) && v.istack.len >= expSize {
|
||||
v.StepInto()
|
||||
}
|
||||
}
|
||||
|
||||
// StepOver takes the debugger to the line that will step over a given line.
|
||||
// If the line contains a function the function will be executed and the result returned without debugging each line.
|
||||
func (v *VM) StepOver() {
|
||||
if v.HasStopped() {
|
||||
return
|
||||
}
|
||||
|
||||
if v.state == breakState {
|
||||
v.state = noneState
|
||||
} else {
|
||||
v.state = breakState
|
||||
}
|
||||
|
||||
expSize := v.istack.len
|
||||
for {
|
||||
v.StepInto()
|
||||
if !(v.state.HasFlag(noneState) && v.istack.len > expSize) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HasFailed returns whether VM is in the failed state now. Usually used to
|
||||
// check status after Run.
|
||||
func (v *VM) HasFailed() bool {
|
||||
return v.state.HasFlag(faultState)
|
||||
}
|
||||
|
||||
// HasStopped returns whether VM is in Halt or Failed state.
|
||||
func (v *VM) HasStopped() bool {
|
||||
return v.state.HasFlag(haltState) || v.state.HasFlag(faultState)
|
||||
}
|
||||
|
||||
// SetCheckedHash sets checked hash for CHECKSIG and CHECKMULTISIG instructions.
|
||||
func (v *VM) SetCheckedHash(h []byte) {
|
||||
v.checkhash = make([]byte, len(h))
|
||||
|
|
Loading…
Reference in a new issue