Break points and debugger commands
This commit is contained in:
parent
7d0004f058
commit
50c0938226
@ -12,7 +12,7 @@ ApplicationWindow {
|
||||
minimumWidth: 1280
|
||||
minimumHeight: 700
|
||||
width: 1290
|
||||
height: 700
|
||||
height: 750
|
||||
|
||||
property alias codeText: codeEditor.text
|
||||
property alias dataText: rawDataField.text
|
||||
@ -31,6 +31,12 @@ ApplicationWindow {
|
||||
shortcut: "Ctrl+n"
|
||||
onTriggered: dbg.next()
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
text: "Continue"
|
||||
shortcut: "Ctrl+c"
|
||||
onTriggered: dbg.continue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,6 +45,7 @@ ApplicationWindow {
|
||||
property var asmModel: ListModel {
|
||||
id: asmModel
|
||||
}
|
||||
|
||||
TableView {
|
||||
id: asmTableView
|
||||
width: 200
|
||||
@ -187,6 +194,36 @@ ApplicationWindow {
|
||||
}
|
||||
}
|
||||
|
||||
function exec() {
|
||||
dbg.execCommand(dbgCommand.text);
|
||||
dbgCommand.text = "";
|
||||
}
|
||||
statusBar: StatusBar {
|
||||
height: 30
|
||||
|
||||
|
||||
TextField {
|
||||
id: dbgCommand
|
||||
y: 1
|
||||
x: asmTableView.width
|
||||
width: 500
|
||||
placeholderText: "Debugger command (help for help)"
|
||||
Keys.onReturnPressed: {
|
||||
exec()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
anchors {
|
||||
left: dbgCommand.right
|
||||
}
|
||||
text: "Exec"
|
||||
onClicked: {
|
||||
exec()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toolBar: ToolBar {
|
||||
RowLayout {
|
||||
spacing: 5
|
||||
@ -208,11 +245,13 @@ ApplicationWindow {
|
||||
}
|
||||
text: "Next"
|
||||
}
|
||||
CheckBox {
|
||||
id: breakEachLine
|
||||
objectName: "breakEachLine"
|
||||
text: "Break each instruction"
|
||||
checked: true
|
||||
|
||||
Button {
|
||||
id: debugContinueButton
|
||||
onClicked: {
|
||||
dbg.continue()
|
||||
}
|
||||
text: "Continue"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -261,7 +300,19 @@ ApplicationWindow {
|
||||
}
|
||||
|
||||
function setLog(msg) {
|
||||
logModel.insert(0, {message: msg})
|
||||
// Remove first item once we've reached max log items
|
||||
if(logModel.count > 250) {
|
||||
logModel.remove(0)
|
||||
}
|
||||
|
||||
if(msg.len != 0) {
|
||||
if(logTableView.flickableItem.atYEnd) {
|
||||
logModel.append({message: msg})
|
||||
logTableView.positionViewAtRow(logTableView.rowCount - 1, ListView.Contain)
|
||||
} else {
|
||||
logModel.append({message: msg})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clearLog() {
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/ethereum/eth-go/ethutil"
|
||||
"github.com/go-qml/qml"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -13,7 +14,10 @@ type DebuggerWindow struct {
|
||||
win *qml.Window
|
||||
engine *qml.Engine
|
||||
lib *UiLib
|
||||
Db *Debugger
|
||||
|
||||
vm *ethchain.Vm
|
||||
Db *Debugger
|
||||
breakPoints []int64
|
||||
}
|
||||
|
||||
func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
|
||||
@ -26,9 +30,9 @@ func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
|
||||
}
|
||||
|
||||
win := component.CreateWindow(nil)
|
||||
db := &Debugger{win, make(chan bool), make(chan bool), true, false, true}
|
||||
db := &Debugger{win, make(chan bool), make(chan bool), true, false}
|
||||
|
||||
return &DebuggerWindow{engine: engine, win: win, lib: lib, Db: db}
|
||||
return &DebuggerWindow{engine: engine, win: win, lib: lib, Db: db, vm: ðchain.Vm{}}
|
||||
}
|
||||
|
||||
func (self *DebuggerWindow) Show() {
|
||||
@ -59,7 +63,6 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
||||
if !self.Db.done {
|
||||
self.Db.Q <- true
|
||||
}
|
||||
self.Db.breakOnInstr = self.win.Root().ObjectByName("breakEachLine").Bool("checked")
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@ -90,7 +93,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
||||
|
||||
dis := ethchain.Disassemble(script)
|
||||
self.win.Root().Call("clearAsm")
|
||||
self.win.Root().Call("clearLog")
|
||||
//self.win.Root().Call("clearLog")
|
||||
|
||||
for _, str := range dis {
|
||||
self.win.Root().Call("setAsm", str)
|
||||
@ -125,7 +128,9 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
||||
})
|
||||
vm.Verbose = true
|
||||
vm.Hook = self.Db.halting
|
||||
vm.BreakPoints = self.breakPoints
|
||||
|
||||
self.vm = vm
|
||||
self.Db.done = false
|
||||
self.Logf("callsize %d", len(script))
|
||||
go func() {
|
||||
@ -165,12 +170,57 @@ func (self *DebuggerWindow) Next() {
|
||||
self.Db.Next()
|
||||
}
|
||||
|
||||
func (self *DebuggerWindow) Continue() {
|
||||
self.vm.Stepping = false
|
||||
self.Next()
|
||||
}
|
||||
|
||||
func (self *DebuggerWindow) ExecCommand(command string) {
|
||||
if len(command) > 0 {
|
||||
cmd := strings.Split(command, " ")
|
||||
switch cmd[0] {
|
||||
case "help":
|
||||
self.Logln("Debgger commands:")
|
||||
self.Logln("break, bp Set breakpoint")
|
||||
case "break", "bp":
|
||||
if len(cmd) > 1 {
|
||||
lineNo, err := strconv.Atoi(cmd[1])
|
||||
if err != nil {
|
||||
self.Logln(err)
|
||||
break
|
||||
}
|
||||
self.breakPoints = append(self.breakPoints, int64(lineNo))
|
||||
self.vm.BreakPoints = self.breakPoints
|
||||
self.Logf("break point set on instruction %d", lineNo)
|
||||
} else {
|
||||
self.Logf("'%s' requires line number", cmd[0])
|
||||
}
|
||||
case "clear":
|
||||
if len(cmd) > 1 {
|
||||
switch cmd[1] {
|
||||
case "break", "bp":
|
||||
self.breakPoints = nil
|
||||
self.vm.BreakPoints = nil
|
||||
|
||||
self.Logln("Breakpoints cleared")
|
||||
default:
|
||||
self.Logf("clear '%s' is not valid", cmd[1])
|
||||
}
|
||||
} else {
|
||||
self.Logln("'clear' requires sub command")
|
||||
}
|
||||
|
||||
default:
|
||||
self.Logf("Unknown command %s", cmd[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Debugger struct {
|
||||
win *qml.Window
|
||||
N chan bool
|
||||
Q chan bool
|
||||
done, interrupt bool
|
||||
breakOnInstr bool
|
||||
}
|
||||
|
||||
type storeVal struct {
|
||||
@ -197,18 +247,16 @@ func (d *Debugger) halting(pc int, op ethchain.OpCode, mem *ethchain.Memory, sta
|
||||
d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())})
|
||||
})
|
||||
|
||||
if d.breakOnInstr {
|
||||
out:
|
||||
for {
|
||||
select {
|
||||
case <-d.N:
|
||||
break out
|
||||
case <-d.Q:
|
||||
d.interrupt = true
|
||||
d.clearBuffers()
|
||||
out:
|
||||
for {
|
||||
select {
|
||||
case <-d.N:
|
||||
break out
|
||||
case <-d.Q:
|
||||
d.interrupt = true
|
||||
d.clearBuffers()
|
||||
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user