| 
									
										
										
										
											2015-01-06 12:13:57 +01:00
										 |  |  | /* | 
					
						
							|  |  |  | 	This file is part of go-ethereum | 
					
						
							| 
									
										
										
										
											2014-10-23 15:48:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-06 12:13:57 +01:00
										 |  |  | 	go-ethereum is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | 	it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  | 	the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | 	(at your option) any later version. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	go-ethereum is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | 	but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | 	GNU General Public License for more details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | 	along with go-ethereum.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @authors | 
					
						
							|  |  |  |  * 	Jeffrey Wilcke <i@jev.io> | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-07-02 00:13:50 +02:00
										 |  |  | package main | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2014-07-30 00:30:57 +02:00
										 |  |  | 	"math/big" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2014-09-19 11:13:01 +02:00
										 |  |  | 	"unicode" | 
					
						
							| 
									
										
										
										
											2014-07-30 00:30:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 14:20:11 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/cmd/utils" | 
					
						
							| 
									
										
										
										
											2014-12-04 10:28:02 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core" | 
					
						
							| 
									
										
										
										
											2015-02-01 15:29:57 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							| 
									
										
										
										
											2014-10-23 15:01:27 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethutil" | 
					
						
							| 
									
										
										
										
											2014-10-31 14:43:14 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/state" | 
					
						
							| 
									
										
										
										
											2014-10-23 15:01:27 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/vm" | 
					
						
							| 
									
										
										
										
											2015-01-28 14:51:54 +01:00
										 |  |  | 	"github.com/obscuren/qml" | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type DebuggerWindow struct { | 
					
						
							|  |  |  | 	win    *qml.Window | 
					
						
							|  |  |  | 	engine *qml.Engine | 
					
						
							|  |  |  | 	lib    *UiLib | 
					
						
							| 
									
										
										
										
											2014-07-02 13:08:18 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:23:17 +01:00
										 |  |  | 	vm *vm.Vm | 
					
						
							| 
									
										
										
										
											2014-07-05 13:25:16 +02:00
										 |  |  | 	Db *Debugger | 
					
						
							| 
									
										
										
										
											2014-07-18 11:57:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-04 11:40:20 +01:00
										 |  |  | 	state *state.StateDB | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewDebuggerWindow(lib *UiLib) *DebuggerWindow { | 
					
						
							|  |  |  | 	engine := qml.NewEngine() | 
					
						
							|  |  |  | 	component, err := engine.LoadFile(lib.AssetPath("debugger/debugger.qml")) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Println(err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	win := component.CreateWindow(nil) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-19 11:23:17 +01:00
										 |  |  | 	w := &DebuggerWindow{engine: engine, win: win, lib: lib, vm: &vm.Vm{}} | 
					
						
							| 
									
										
										
										
											2014-07-05 13:25:16 +02:00
										 |  |  | 	w.Db = NewDebugger(w) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return w | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *DebuggerWindow) Show() { | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | 	context := self.engine.Context() | 
					
						
							|  |  |  | 	context.SetVar("dbg", self) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 	go func() { | 
					
						
							|  |  |  | 		self.win.Show() | 
					
						
							|  |  |  | 		self.win.Wait() | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-28 13:00:45 +02:00
										 |  |  | func (self *DebuggerWindow) SetCode(code string) { | 
					
						
							|  |  |  | 	self.win.Set("codeText", code) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-05-27 16:09:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-28 13:00:45 +02:00
										 |  |  | func (self *DebuggerWindow) SetData(data string) { | 
					
						
							|  |  |  | 	self.win.Set("dataText", data) | 
					
						
							| 
									
										
										
										
											2014-05-27 16:09:04 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-07-18 11:57:58 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-04 13:04:25 +02:00
										 |  |  | func (self *DebuggerWindow) SetAsm(data []byte) { | 
					
						
							|  |  |  | 	self.win.Root().Call("clearAsm") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-04 10:28:02 +01:00
										 |  |  | 	dis := core.Disassemble(data) | 
					
						
							| 
									
										
										
										
											2014-05-28 15:48:17 +02:00
										 |  |  | 	for _, str := range dis { | 
					
						
							|  |  |  | 		self.win.Root().Call("setAsm", str) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-05-27 16:09:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-04 13:04:25 +02:00
										 |  |  | func (self *DebuggerWindow) Compile(code string) { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	script := ethutil.StringToByteFunc(code, func(s string) (ret []byte) { | 
					
						
							| 
									
										
										
										
											2014-07-04 13:42:43 +02:00
										 |  |  | 		ret, err = ethutil.Compile(s, true) | 
					
						
							| 
									
										
										
										
											2014-07-04 13:04:25 +02:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		self.SetAsm(script) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-11 16:04:27 +02:00
										 |  |  | // Used by QML | 
					
						
							|  |  |  | func (self *DebuggerWindow) AutoComp(code string) { | 
					
						
							|  |  |  | 	if self.Db.done { | 
					
						
							|  |  |  | 		self.Compile(code) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-04 15:31:13 +02:00
										 |  |  | func (self *DebuggerWindow) ClearLog() { | 
					
						
							|  |  |  | 	self.win.Root().Call("clearLog") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-27 16:09:04 +02:00
										 |  |  | func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, dataStr string) { | 
					
						
							| 
									
										
										
										
											2014-09-19 22:42:55 +02:00
										 |  |  | 	self.Stop() | 
					
						
							| 
									
										
										
										
											2014-05-27 13:28:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-09 22:04:16 +02:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  | 			self.Logf("compile FAULT: %v", r) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-15 13:16:07 +02:00
										 |  |  | 	data := utils.FormatTransactionData(dataStr) | 
					
						
							| 
									
										
										
										
											2014-05-28 13:00:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	script := ethutil.StringToByteFunc(scriptStr, func(s string) (ret []byte) { | 
					
						
							| 
									
										
										
										
											2014-07-04 13:42:43 +02:00
										 |  |  | 		ret, err = ethutil.Compile(s, false) | 
					
						
							| 
									
										
										
										
											2014-05-28 13:00:45 +02:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2014-05-28 23:14:23 +02:00
										 |  |  | 		self.Logln(err) | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-26 12:10:11 +02:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		gas      = ethutil.Big(gasStr) | 
					
						
							|  |  |  | 		gasPrice = ethutil.Big(gasPriceStr) | 
					
						
							|  |  |  | 		value    = ethutil.Big(valueStr) | 
					
						
							|  |  |  | 		// Contract addr as test address | 
					
						
							| 
									
										
										
										
											2014-07-04 13:04:25 +02:00
										 |  |  | 		keyPair = self.lib.eth.KeyManager().KeyPair() | 
					
						
							| 
									
										
										
										
											2014-06-26 12:10:11 +02:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-10 19:59:12 +01:00
										 |  |  | 	statedb := self.lib.eth.ChainManager().TransState() | 
					
						
							|  |  |  | 	account := self.lib.eth.ChainManager().TransState().GetAccount(keyPair.Address()) | 
					
						
							| 
									
										
										
										
											2014-10-31 14:43:14 +01:00
										 |  |  | 	contract := statedb.NewStateObject([]byte{0}) | 
					
						
							| 
									
										
										
										
											2014-12-03 17:22:26 +01:00
										 |  |  | 	contract.SetCode(script) | 
					
						
							| 
									
										
										
										
											2014-10-23 01:01:41 +02:00
										 |  |  | 	contract.SetBalance(value) | 
					
						
							| 
									
										
										
										
											2014-07-04 13:04:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-22 19:54:33 +02:00
										 |  |  | 	self.SetAsm(script) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 13:17:24 +01:00
										 |  |  | 	block := self.lib.eth.ChainManager().CurrentBlock() | 
					
						
							| 
									
										
										
										
											2014-07-24 12:30:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-01 15:29:57 +01:00
										 |  |  | 	msg := types.NewTransactionMessage(nil, value, gas, gasPrice, data) | 
					
						
							|  |  |  | 	env := core.NewEnv(statedb, self.lib.eth.ChainManager(), msg, block) | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-05 09:00:57 +02:00
										 |  |  | 	self.Logf("callsize %d", len(script)) | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 	go func() { | 
					
						
							| 
									
										
										
										
											2015-02-01 15:29:57 +01:00
										 |  |  | 		pgas := new(big.Int).Set(gas) | 
					
						
							| 
									
										
										
										
											2014-12-03 17:22:26 +01:00
										 |  |  | 		ret, err := env.Call(account, contract.Address(), data, gas, gasPrice, ethutil.Big0) | 
					
						
							| 
									
										
										
										
											2015-02-01 15:29:57 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		rgas := new(big.Int).Sub(pgas, gas) | 
					
						
							|  |  |  | 		tot := new(big.Int).Mul(rgas, gasPrice) | 
					
						
							|  |  |  | 		self.Logf("gas usage %v total price = %v (%v)", rgas, tot, ethutil.CurrencyToString(tot)) | 
					
						
							| 
									
										
										
										
											2014-05-28 23:14:23 +02:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			self.Logln("exited with errors:", err) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2014-06-05 09:00:57 +02:00
										 |  |  | 			if len(ret) > 0 { | 
					
						
							|  |  |  | 				self.Logf("exited: % x", ret) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				self.Logf("exited: nil") | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-05-28 23:14:23 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 14:43:14 +01:00
										 |  |  | 		statedb.Reset() | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-09 22:04:16 +02:00
										 |  |  | 		if !self.Db.interrupt { | 
					
						
							|  |  |  | 			self.Db.done = true | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			self.Db.interrupt = false | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | 	}() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-28 23:14:23 +02:00
										 |  |  | func (self *DebuggerWindow) Logf(format string, v ...interface{}) { | 
					
						
							|  |  |  | 	self.win.Root().Call("setLog", fmt.Sprintf(format, v...)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *DebuggerWindow) Logln(v ...interface{}) { | 
					
						
							|  |  |  | 	str := fmt.Sprintln(v...) | 
					
						
							|  |  |  | 	self.Logf("%s", str[:len(str)-1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-27 10:42:37 +02:00
										 |  |  | func (self *DebuggerWindow) Next() { | 
					
						
							|  |  |  | 	self.Db.Next() | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-02 13:08:18 +02:00
										 |  |  | func (self *DebuggerWindow) Continue() { | 
					
						
							|  |  |  | 	self.vm.Stepping = false | 
					
						
							|  |  |  | 	self.Next() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-19 22:42:55 +02:00
										 |  |  | func (self *DebuggerWindow) Stop() { | 
					
						
							|  |  |  | 	if !self.Db.done { | 
					
						
							|  |  |  | 		self.Db.Q <- true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-02 13:08:18 +02:00
										 |  |  | func (self *DebuggerWindow) ExecCommand(command string) { | 
					
						
							|  |  |  | 	if len(command) > 0 { | 
					
						
							|  |  |  | 		cmd := strings.Split(command, " ") | 
					
						
							|  |  |  | 		switch cmd[0] { | 
					
						
							|  |  |  | 		case "help": | 
					
						
							| 
									
										
										
										
											2014-07-04 13:04:25 +02:00
										 |  |  | 			self.Logln("Debugger commands:") | 
					
						
							| 
									
										
										
										
											2014-07-04 15:31:13 +02:00
										 |  |  | 			self.Logln("break, bp                 Set breakpoint on instruction") | 
					
						
							|  |  |  | 			self.Logln("clear [log, break, bp]    Clears previous set sub-command(s)") | 
					
						
							| 
									
										
										
										
											2014-07-02 13:08:18 +02:00
										 |  |  | 		case "break", "bp": | 
					
						
							|  |  |  | 			if len(cmd) > 1 { | 
					
						
							|  |  |  | 				lineNo, err := strconv.Atoi(cmd[1]) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					self.Logln(err) | 
					
						
							|  |  |  | 					break | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-07-05 13:25:16 +02:00
										 |  |  | 				self.Db.breakPoints = append(self.Db.breakPoints, int64(lineNo)) | 
					
						
							| 
									
										
										
										
											2014-07-02 13:08:18 +02:00
										 |  |  | 				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": | 
					
						
							| 
									
										
										
										
											2014-07-05 13:25:16 +02:00
										 |  |  | 					self.Db.breakPoints = nil | 
					
						
							| 
									
										
										
										
											2014-07-02 13:08:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					self.Logln("Breakpoints cleared") | 
					
						
							| 
									
										
										
										
											2014-07-04 15:31:13 +02:00
										 |  |  | 				case "log": | 
					
						
							|  |  |  | 					self.ClearLog() | 
					
						
							| 
									
										
										
										
											2014-07-02 13:08:18 +02:00
										 |  |  | 				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]) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | type Debugger struct { | 
					
						
							| 
									
										
										
										
											2014-06-09 22:04:16 +02:00
										 |  |  | 	N               chan bool | 
					
						
							|  |  |  | 	Q               chan bool | 
					
						
							|  |  |  | 	done, interrupt bool | 
					
						
							| 
									
										
										
										
											2014-07-05 13:25:16 +02:00
										 |  |  | 	breakPoints     []int64 | 
					
						
							|  |  |  | 	main            *DebuggerWindow | 
					
						
							|  |  |  | 	win             *qml.Window | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewDebugger(main *DebuggerWindow) *Debugger { | 
					
						
							|  |  |  | 	db := &Debugger{make(chan bool), make(chan bool), true, false, nil, main, main.win} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return db | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type storeVal struct { | 
					
						
							|  |  |  | 	Key, Value string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-20 15:49:12 +01:00
										 |  |  | func (self *Debugger) Step(evm vm.VirtualMachine, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, context *vm.Context) { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 14:43:14 +01:00
										 |  |  | func (self *Debugger) BreakHook(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, stateObject *state.StateObject) bool { | 
					
						
							| 
									
										
										
										
											2014-07-05 13:25:16 +02:00
										 |  |  | 	self.main.Logln("break on instr:", pc) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return self.halting(pc, op, mem, stack, stateObject) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 14:43:14 +01:00
										 |  |  | func (self *Debugger) StepHook(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, stateObject *state.StateObject) bool { | 
					
						
							| 
									
										
										
										
											2014-07-05 13:25:16 +02:00
										 |  |  | 	return self.halting(pc, op, mem, stack, stateObject) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-11 16:04:27 +02:00
										 |  |  | func (self *Debugger) SetCode(byteCode []byte) { | 
					
						
							|  |  |  | 	self.main.SetAsm(byteCode) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-05 13:25:16 +02:00
										 |  |  | func (self *Debugger) BreakPoints() []int64 { | 
					
						
							|  |  |  | 	return self.breakPoints | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-31 14:43:14 +01:00
										 |  |  | func (d *Debugger) halting(pc int, op vm.OpCode, mem *vm.Memory, stack *vm.Stack, stateObject *state.StateObject) bool { | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | 	d.win.Root().Call("setInstruction", pc) | 
					
						
							|  |  |  | 	d.win.Root().Call("clearMem") | 
					
						
							|  |  |  | 	d.win.Root().Call("clearStack") | 
					
						
							|  |  |  | 	d.win.Root().Call("clearStorage") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	addr := 0 | 
					
						
							| 
									
										
										
										
											2014-09-22 14:54:27 +02:00
										 |  |  | 	for i := 0; i+16 <= mem.Len(); i += 16 { | 
					
						
							| 
									
										
										
										
											2014-09-19 11:13:01 +02:00
										 |  |  | 		dat := mem.Data()[i : i+16] | 
					
						
							|  |  |  | 		var str string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for _, d := range dat { | 
					
						
							|  |  |  | 			if unicode.IsGraphic(rune(d)) { | 
					
						
							|  |  |  | 				str += string(d) | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				str += "?" | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		d.win.Root().Call("setMem", memAddr{fmt.Sprintf("%03d", addr), fmt.Sprintf("%s  % x", str, dat)}) | 
					
						
							|  |  |  | 		addr += 16 | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, val := range stack.Data() { | 
					
						
							|  |  |  | 		d.win.Root().Call("setStack", val.String()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-02 12:07:26 +01:00
										 |  |  | 	it := stateObject.Trie().Iterator() | 
					
						
							|  |  |  | 	for it.Next() { | 
					
						
							|  |  |  | 		d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", it.Key), fmt.Sprintf("% x", it.Value)}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-19 11:13:01 +02:00
										 |  |  | 	stackFrameAt := new(big.Int).SetBytes(mem.Get(0, 32)) | 
					
						
							|  |  |  | 	psize := mem.Len() - int(new(big.Int).SetBytes(mem.Get(0, 32)).Uint64()) | 
					
						
							|  |  |  | 	d.win.Root().ObjectByName("stackFrame").Set("text", fmt.Sprintf(`<b>stack ptr</b>: %v`, stackFrameAt)) | 
					
						
							|  |  |  | 	d.win.Root().ObjectByName("stackSize").Set("text", fmt.Sprintf(`<b>stack size</b>: %d`, psize)) | 
					
						
							|  |  |  | 	d.win.Root().ObjectByName("memSize").Set("text", fmt.Sprintf(`<b>mem size</b>: %v`, mem.Len())) | 
					
						
							| 
									
										
										
										
											2014-09-19 01:42:26 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-02 13:08:18 +02:00
										 |  |  | out: | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-d.N: | 
					
						
							|  |  |  | 			break out | 
					
						
							|  |  |  | 		case <-d.Q: | 
					
						
							|  |  |  | 			d.interrupt = true | 
					
						
							|  |  |  | 			d.clearBuffers() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return false | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-05-27 13:28:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return true | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-09 22:04:16 +02:00
										 |  |  | func (d *Debugger) clearBuffers() { | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	// drain | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-d.N: | 
					
						
							|  |  |  | 		case <-d.Q: | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			break out | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-27 13:09:47 +02:00
										 |  |  | func (d *Debugger) Next() { | 
					
						
							|  |  |  | 	if !d.done { | 
					
						
							|  |  |  | 		d.N <- true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |