forked from cerc-io/plugeth
Break points and debugger commands
This commit is contained in:
parent
7d0004f058
commit
50c0938226
@ -12,7 +12,7 @@ ApplicationWindow {
|
|||||||
minimumWidth: 1280
|
minimumWidth: 1280
|
||||||
minimumHeight: 700
|
minimumHeight: 700
|
||||||
width: 1290
|
width: 1290
|
||||||
height: 700
|
height: 750
|
||||||
|
|
||||||
property alias codeText: codeEditor.text
|
property alias codeText: codeEditor.text
|
||||||
property alias dataText: rawDataField.text
|
property alias dataText: rawDataField.text
|
||||||
@ -31,6 +31,12 @@ ApplicationWindow {
|
|||||||
shortcut: "Ctrl+n"
|
shortcut: "Ctrl+n"
|
||||||
onTriggered: dbg.next()
|
onTriggered: dbg.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: "Continue"
|
||||||
|
shortcut: "Ctrl+c"
|
||||||
|
onTriggered: dbg.continue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +45,7 @@ ApplicationWindow {
|
|||||||
property var asmModel: ListModel {
|
property var asmModel: ListModel {
|
||||||
id: asmModel
|
id: asmModel
|
||||||
}
|
}
|
||||||
|
|
||||||
TableView {
|
TableView {
|
||||||
id: asmTableView
|
id: asmTableView
|
||||||
width: 200
|
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 {
|
toolBar: ToolBar {
|
||||||
RowLayout {
|
RowLayout {
|
||||||
spacing: 5
|
spacing: 5
|
||||||
@ -208,11 +245,13 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
text: "Next"
|
text: "Next"
|
||||||
}
|
}
|
||||||
CheckBox {
|
|
||||||
id: breakEachLine
|
Button {
|
||||||
objectName: "breakEachLine"
|
id: debugContinueButton
|
||||||
text: "Break each instruction"
|
onClicked: {
|
||||||
checked: true
|
dbg.continue()
|
||||||
|
}
|
||||||
|
text: "Continue"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,7 +300,19 @@ ApplicationWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setLog(msg) {
|
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() {
|
function clearLog() {
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/ethereum/eth-go/ethutil"
|
"github.com/ethereum/eth-go/ethutil"
|
||||||
"github.com/go-qml/qml"
|
"github.com/go-qml/qml"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,7 +14,10 @@ type DebuggerWindow struct {
|
|||||||
win *qml.Window
|
win *qml.Window
|
||||||
engine *qml.Engine
|
engine *qml.Engine
|
||||||
lib *UiLib
|
lib *UiLib
|
||||||
Db *Debugger
|
|
||||||
|
vm *ethchain.Vm
|
||||||
|
Db *Debugger
|
||||||
|
breakPoints []int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
|
func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
|
||||||
@ -26,9 +30,9 @@ func NewDebuggerWindow(lib *UiLib) *DebuggerWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
win := component.CreateWindow(nil)
|
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() {
|
func (self *DebuggerWindow) Show() {
|
||||||
@ -59,7 +63,6 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
|||||||
if !self.Db.done {
|
if !self.Db.done {
|
||||||
self.Db.Q <- true
|
self.Db.Q <- true
|
||||||
}
|
}
|
||||||
self.Db.breakOnInstr = self.win.Root().ObjectByName("breakEachLine").Bool("checked")
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
@ -90,7 +93,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
|||||||
|
|
||||||
dis := ethchain.Disassemble(script)
|
dis := ethchain.Disassemble(script)
|
||||||
self.win.Root().Call("clearAsm")
|
self.win.Root().Call("clearAsm")
|
||||||
self.win.Root().Call("clearLog")
|
//self.win.Root().Call("clearLog")
|
||||||
|
|
||||||
for _, str := range dis {
|
for _, str := range dis {
|
||||||
self.win.Root().Call("setAsm", str)
|
self.win.Root().Call("setAsm", str)
|
||||||
@ -125,7 +128,9 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data
|
|||||||
})
|
})
|
||||||
vm.Verbose = true
|
vm.Verbose = true
|
||||||
vm.Hook = self.Db.halting
|
vm.Hook = self.Db.halting
|
||||||
|
vm.BreakPoints = self.breakPoints
|
||||||
|
|
||||||
|
self.vm = vm
|
||||||
self.Db.done = false
|
self.Db.done = false
|
||||||
self.Logf("callsize %d", len(script))
|
self.Logf("callsize %d", len(script))
|
||||||
go func() {
|
go func() {
|
||||||
@ -165,12 +170,57 @@ func (self *DebuggerWindow) Next() {
|
|||||||
self.Db.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 {
|
type Debugger struct {
|
||||||
win *qml.Window
|
win *qml.Window
|
||||||
N chan bool
|
N chan bool
|
||||||
Q chan bool
|
Q chan bool
|
||||||
done, interrupt bool
|
done, interrupt bool
|
||||||
breakOnInstr bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type storeVal struct {
|
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())})
|
d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())})
|
||||||
})
|
})
|
||||||
|
|
||||||
if d.breakOnInstr {
|
out:
|
||||||
out:
|
for {
|
||||||
for {
|
select {
|
||||||
select {
|
case <-d.N:
|
||||||
case <-d.N:
|
break out
|
||||||
break out
|
case <-d.Q:
|
||||||
case <-d.Q:
|
d.interrupt = true
|
||||||
d.interrupt = true
|
d.clearBuffers()
|
||||||
d.clearBuffers()
|
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user