From f1a35dcaf071c14dac8e87f6a0183f8fac9a5825 Mon Sep 17 00:00:00 2001 From: arkpar Date: Sat, 31 Jan 2015 01:02:41 +0100 Subject: [PATCH] bebugger bugfixes --- mix/DebuggingStateWrapper.cpp | 130 +++++++++++-------------------- mix/DebuggingStateWrapper.h | 6 -- mix/MixApplication.cpp | 2 +- mix/qml/Debugger.qml | 30 +++---- mix/qml/ItemDelegateDataDump.qml | 15 ---- mix/qml/StepActionImage.qml | 2 + mix/qml/html/codeeditor.js | 3 +- mix/qml/js/Debugger.js | 116 +++++++++++++-------------- 8 files changed, 120 insertions(+), 184 deletions(-) diff --git a/mix/DebuggingStateWrapper.cpp b/mix/DebuggingStateWrapper.cpp index c99ce9681..5a1812610 100644 --- a/mix/DebuggingStateWrapper.cpp +++ b/mix/DebuggingStateWrapper.cpp @@ -20,7 +20,7 @@ * Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML). */ -#include +#include #include #include #include @@ -36,6 +36,39 @@ using namespace dev; using namespace dev::eth; using namespace dev::mix; +namespace +{ + static QVariantList memDumpToList(bytes const& _bytes, unsigned _width) + { + QVariantList dumpList; + for (unsigned i = 0; i < _bytes.size(); i += _width) + { + std::stringstream ret; + + for (unsigned j = i; j < i + _width; ++j) + if (j < _bytes.size()) + if (_bytes[j] >= 32 && _bytes[j] < 127) + ret << (char)_bytes[j]; + else + ret << '?'; + else + ret << ' '; + QString strPart = QString::fromStdString(ret.str()); + + ret.clear(); + ret.str(std::string()); + + for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j) + ret << std::setfill('0') << std::setw(2) << std::hex << (unsigned)_bytes[j] << " "; + QString hexPart = QString::fromStdString(ret.str()); + + QStringList line = { strPart, hexPart }; + dumpList.push_back(line); + } + return dumpList; + } +} + QCode* QMachineState::getHumanReadableCode(QObject* _owner, const bytes& _code) { QVariantList codeStr; @@ -86,7 +119,7 @@ QStringList QMachineState::debugStack() QStringList stack; for (std::vector::reverse_iterator i = m_state.stack.rbegin(); i != m_state.stack.rend(); ++i) stack.append(QString::fromStdString(prettyU256(*i))); - return fillList(stack, ""); + return stack; } QStringList QMachineState::debugStorage() @@ -95,95 +128,20 @@ QStringList QMachineState::debugStorage() for (auto const& i: m_state.storage) { std::stringstream s; - s << "@" << prettyU256(i.first) << " " << prettyU256(i.second); + s << "@" << prettyU256(i.first) << "\t" << prettyU256(i.second); storage.append(QString::fromStdString(s.str())); } - return fillList(storage, "@ -"); + return storage; } QVariantList QMachineState::debugMemory() { - std::vector> dump = memDumpToList(m_state.memory, 16); - QStringList filled; - filled.append(" "); - filled.append(" "); - filled.append(" "); - return fillList(qVariantDump(dump), QVariant(filled)); + return memDumpToList(m_state.memory, 16); } QCallData* QMachineState::getDebugCallData(QObject* _owner, bytes const& _data) { - std::vector> dump = memDumpToList(_data, 16); - QStringList filled; - filled.append(" "); - filled.append(" "); - filled.append(" "); - return new QCallData(_owner, fillList(qVariantDump(dump), QVariant(filled))); -} - -std::vector> QMachineState::memDumpToList(bytes const& _bytes, unsigned _width) -{ - std::vector> dump; - for (unsigned i = 0; i < _bytes.size(); i += _width) - { - std::stringstream ret; - std::vector dumpLine; - ret << std::hex << std::setw(4) << std::setfill('0') << i << " "; - dumpLine.push_back(ret.str()); - ret.str(std::string()); - ret.clear(); - - for (unsigned j = i; j < i + _width; ++j) - if (j < _bytes.size()) - if (_bytes[j] >= 32 && _bytes[j] < 127) - ret << (char)_bytes[j]; - else - ret << '?'; - else - ret << ' '; - dumpLine.push_back(ret.str()); - ret.str(std::string()); - ret.clear(); - - for (unsigned j = i; j < i + _width && j < _bytes.size(); ++j) - ret << std::setfill('0') << std::setw(2) << std::hex << (unsigned)_bytes[j] << " "; - dumpLine.push_back(ret.str()); - dump.push_back(dumpLine); - } - return dump; -} - -QVariantList QMachineState::qVariantDump(std::vector> const& _dump) -{ - QVariantList ret; - for (std::vector const& line: _dump) - { - QStringList qLine; - for (std::string const& cell: line) - qLine.push_back(QString::fromStdString(cell)); - ret.append(QVariant(qLine)); - } - return ret; -} - -QStringList QMachineState::fillList(QStringList& _list, QString const& _emptyValue) -{ - if (_list.size() < 20) - { - for (int k = _list.size(); k < 20 - _list.size(); k++) - _list.append(_emptyValue); - } - return _list; -} - -QVariantList QMachineState::fillList(QVariantList _list, QVariant const& _emptyValue) -{ - if (_list.size() < 20) - { - for (int k = _list.size(); k < 20 - _list.size(); k++) - _list.append(_emptyValue); - } - return _list; + return new QCallData(_owner, memDumpToList(_data, 16)); } QStringList QMachineState::levels() @@ -208,7 +166,7 @@ QString QMachineState::instruction() QString QMachineState::endOfDebug() { if (m_state.gasCost > m_state.gas) - return QApplication::tr("OUT-OF-GAS"); + return QObject::tr("OUT-OF-GAS"); else if (m_state.inst == Instruction::RETURN && m_state.stack.size() >= 2) { unsigned from = (unsigned)m_state.stack.back(); @@ -217,12 +175,12 @@ QString QMachineState::endOfDebug() bytes out(size, 0); for (; o < size && from + o < m_state.memory.size(); ++o) out[o] = m_state.memory[from + o]; - return QApplication::tr("RETURN") + " " + QString::fromStdString(dev::memDump(out, 16, false)); + return QObject::tr("RETURN") + " " + QString::fromStdString(dev::memDump(out, 16, false)); } else if (m_state.inst == Instruction::STOP) - return QApplication::tr("STOP"); + return QObject::tr("STOP"); else if (m_state.inst == Instruction::SUICIDE && m_state.stack.size() >= 1) - return QApplication::tr("SUICIDE") + " 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); + return QObject::tr("SUICIDE") + " 0x" + QString::fromStdString(toString(right160(m_state.stack.back()))); else - return QApplication::tr("EXCEPTION"); + return QObject::tr("EXCEPTION"); } diff --git a/mix/DebuggingStateWrapper.h b/mix/DebuggingStateWrapper.h index d7591ea4e..8e83628f7 100644 --- a/mix/DebuggingStateWrapper.h +++ b/mix/DebuggingStateWrapper.h @@ -156,12 +156,6 @@ private: MachineState m_state; QCode* m_code; QCallData* m_callData; - static QStringList fillList(QStringList& _list, QString const& _emptyValue); - static QVariantList fillList(QVariantList _list, QVariant const& _emptyValue); - static QVariantList qVariantDump(std::vector> const& _dump); - /// Nicely renders the given bytes to a string, store the content in an array. - /// @a _bytes: bytes array to be rendered as string. @a _width of a bytes line. - static std::vector> memDumpToList(bytes const& _bytes, unsigned _width); }; } diff --git a/mix/MixApplication.cpp b/mix/MixApplication.cpp index 991859778..deff7c011 100644 --- a/mix/MixApplication.cpp +++ b/mix/MixApplication.cpp @@ -36,7 +36,7 @@ using namespace dev::mix; MixApplication::MixApplication(int _argc, char* _argv[]): QApplication(_argc, _argv), m_engine(new QQmlApplicationEngine()), m_appContext(new AppContext(m_engine.get())) { - setOrganizationName(tr("Ethreum")); + setOrganizationName(tr("Ethereum")); setOrganizationDomain(tr("ethereum.org")); setApplicationName(tr("Mix")); setApplicationVersion("0.1"); diff --git a/mix/qml/Debugger.qml b/mix/qml/Debugger.qml index 11b6b6bf0..975a083ab 100644 --- a/mix/qml/Debugger.qml +++ b/mix/qml/Debugger.qml @@ -13,13 +13,6 @@ Rectangle { anchors.fill: parent; color: "#ededed" clip: true - Keys.onPressed: - { - if (event.key === Qt.Key_F10) - Debugger.moveSelection(1); - else if (event.key === Qt.Key_F9) - Debugger.moveSelection(-1); - } onVisibleChanged: { @@ -166,6 +159,7 @@ Rectangle { onClicked: Debugger.stepOutBack() width: 28 height: 30 + buttonShortcut: "Ctrl+Shift+F11" buttonTooltip: qsTr("Step Out Back") } @@ -177,6 +171,7 @@ Rectangle { onClicked: Debugger.stepIntoBack() width: 28 height: 30 + buttonShortcut: "Ctrl+F11" buttonTooltip: qsTr("Step Into Back") } @@ -188,6 +183,7 @@ Rectangle { onClicked: Debugger.stepOverBack() width: 28 height: 30 + buttonShortcut: "Ctrl+F10" buttonTooltip: qsTr("Step Over Back") } @@ -199,6 +195,7 @@ Rectangle { onClicked: Debugger.stepOverForward() width: 28 height: 30 + buttonShortcut: "F10" buttonTooltip: qsTr("Step Over Forward") } @@ -210,6 +207,7 @@ Rectangle { onClicked: Debugger.stepIntoForward() width: 28 height: 30 + buttonShortcut: "F11" buttonTooltip: qsTr("Step Into Forward") } @@ -221,6 +219,7 @@ Rectangle { onClicked: Debugger.stepOutForward() width: 28 height: 30 + buttonShortcut: "Shift+F11" buttonTooltip: qsTr("Step Out Forward") } } @@ -283,7 +282,7 @@ Rectangle { id: statesList delegate: renderDelegate highlight: highlightBar - highlightFollowsCurrentItem: false + //highlightFollowsCurrentItem: false model: ListModel {} } @@ -295,9 +294,9 @@ Rectangle { width: statesList.currentItem.width; y: statesList.currentItem.y color: "#4A90E2" - Behavior on y { - PropertyAnimation { properties: "y"; easing.type: Easing.InOutQuad; duration: 50} - } + //Behavior on y { + // PropertyAnimation { properties: "y"; easing.type: Easing.InOutQuad; duration: 50} + //} } } @@ -314,6 +313,7 @@ Rectangle { width: 15 color: "#b2b3ae" text: line.split(' ')[0] + font.family: "monospace" font.pointSize: 9 id: id wrapMode: Text.NoWrap @@ -321,6 +321,7 @@ Rectangle { Text { wrapMode: Text.NoWrap color: parent.ListView.isCurrentItem ? "white" : "black" + font.family: "monospace" text: line.replace(line.split(' ')[0], '') anchors.left: id.right font.pointSize: 9 @@ -481,8 +482,10 @@ Rectangle { font.family: "monospace" anchors.leftMargin: 5 color: "#4a4a4a" - text: modelData.split(' ')[0].substring(0, 10); + text: modelData.split('\t')[0]; font.pointSize: 9 + width: parent.width - 5 + elide: Text.ElideRight } } Rectangle @@ -502,7 +505,8 @@ Rectangle { font.family: "monospace" anchors.verticalCenter: parent.verticalCenter color: "#4a4a4a" - text: modelData.split(' ')[1].substring(0, 10); + text: modelData.split('\t')[1]; + elide: Text.ElideRight font.pointSize: 9 } } diff --git a/mix/qml/ItemDelegateDataDump.qml b/mix/qml/ItemDelegateDataDump.qml index 1c0ea183e..a57a61b03 100644 --- a/mix/qml/ItemDelegateDataDump.qml +++ b/mix/qml/ItemDelegateDataDump.qml @@ -49,21 +49,6 @@ Rectangle { font.pointSize: 8 } } - - Rectangle - { - Layout.fillWidth: true - Layout.minimumWidth: 50 - Layout.minimumHeight: parent.height - Text { - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - font.family: "monospace" - color: "#4a4a4a" - text: modelData[2] - font.pointSize: 8 - } - } } Rectangle { diff --git a/mix/qml/StepActionImage.qml b/mix/qml/StepActionImage.qml index 64440aa83..a4ff23e54 100644 --- a/mix/qml/StepActionImage.qml +++ b/mix/qml/StepActionImage.qml @@ -9,6 +9,7 @@ Rectangle { property string disableStateImg property string enabledStateImg property string buttonTooltip + property string buttonShortcut signal clicked function enabled(state) @@ -33,6 +34,7 @@ Rectangle { Action { tooltip: buttonTooltip id: buttonAction + shortcut: buttonShortcut onTriggered: { buttonActionContainer.clicked(); } diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index 325741158..2cebc121e 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -4,10 +4,11 @@ var editor = CodeMirror(document.body, { //styleActiveLine: true, matchBrackets: true, autofocus: true, - indentWithTabs: true, }); editor.setOption("theme", "solarized dark"); +editor.setOption("indentUnit", 4); +editor.setOption("indentWithTabs", true); editor.setOption("fullScreen", true); editor.changeRegistered = false; diff --git a/mix/qml/js/Debugger.js b/mix/qml/js/Debugger.js index 9f561b173..169f84db8 100644 --- a/mix/qml/js/Debugger.js +++ b/mix/qml/js/Debugger.js @@ -2,7 +2,6 @@ //statesList => ListView var currentSelectedState = null; -var jumpStartingPoint = null; var debugData = null; var codeMap = null; @@ -12,13 +11,14 @@ function init(data) jumpIntoBackAction.enabled(false); jumpIntoForwardAction.enabled(false); jumpOutForwardAction.enabled(false); + jumpOverBackAction.enabled(false); + jumpOverForwardAction.enabled(false); if (data === null) { statesList.model.clear(); statesSlider.maximumValue = 0; statesSlider.value = 0; currentSelectedState = null; - jumpStartingPoint = null; debugData = null; return; } @@ -40,6 +40,7 @@ function setupInstructions(stateIndex) { statesList.model.append(instructions[i]); codeMap[instructions[i].processIndex] = i; } + callDataDump.listModel = debugData.states[stateIndex].callData.items; } function moveSelection(incr) @@ -49,12 +50,15 @@ function moveSelection(incr) { if (currentSelectedState + incr < debugData.states.length) select(currentSelectedState + incr); - statesSlider.value = currentSelectedState; } } function select(stateIndex) { + if (stateIndex < 0) + stateIndex = 0; + if (stateIndex >= debugData.states.length) + stateIndex = debugData.state.length - 1; if (debugData.states[stateIndex].codeIndex !== debugData.states[currentSelectedState].codeIndex) setupInstructions(stateIndex); currentSelectedState = stateIndex; @@ -63,15 +67,13 @@ function select(stateIndex) highlightSelection(codeLine); completeCtxInformation(state); - if (state.instruction === "CALL" || state.instruction === "CREATE") - jumpIntoForwardAction.enabled(true); - else - jumpIntoForwardAction.enabled(false); - - if (state.instruction === "JUMPDEST") - jumpIntoBackAction.enabled(true); - else - jumpIntoBackAction.enabled(false); + statesSlider.value = currentSelectedState; + jumpIntoForwardAction.enabled(stateIndex < debugData.states.length - 1) + jumpIntoBackAction.enabled(stateIndex > 0); + jumpOverForwardAction.enabled(stateIndex < debugData.states.length - 1); + jumpOverBackAction.enabled(stateIndex > 0); + jumpOutBackAction.enabled(state.levels.length > 1); + jumpOutForwardAction.enabled(state.levels.length > 1); } function codeStr(stateIndex) @@ -83,6 +85,7 @@ function codeStr(stateIndex) function highlightSelection(index) { statesList.currentIndex = index; + statesList.positionViewAtIndex(index, ListView.Center); } function completeCtxInformation(state) @@ -95,18 +98,18 @@ function completeCtxInformation(state) stack.listModel = state.debugStack; storage.listModel = state.debugStorage; memoryDump.listModel = state.debugMemory; - callDataDump.listModel = state.debugCallData; } -function stepOutBack() +function isCallInstruction(index) { - if (jumpStartingPoint != null) - { - select(jumpStartingPoint); - jumpStartingPoint = null; - jumpOutBackAction.enabled(false); - jumpOutForwardAction.enabled(false); - } + var state = debugData.states[index]; + return state.instruction === "CALL" || state.instruction === "CREATE"; +} + +function isReturnInstruction(index) +{ + var state = debugData.states[index]; + return state.instruction === "RETURN" } function stepIntoBack() @@ -116,63 +119,52 @@ function stepIntoBack() function stepOverBack() { - var state = debugData.states[currentSelectedState]; - if (state.instruction === "CALL" || state.instruction === "CREATE") - { - for (var k = currentSelectedState; k > 0; k--) - { - var line = codeMap[debugData.states[k].curPC]; - if (line === statesList.currentIndex - 2) - { - select(k); - break; - } - } - } + if (currentSelectedState > 0 && isReturnInstruction(currentSelectedState - 1)) + stepOutBack(); else moveSelection(-1); } function stepOverForward() { - var state = debugData.states[currentSelectedState]; - if (state.instruction === "CALL" || state.instruction === "CREATE") - { - for (var k = currentSelectedState; k < debugData.states.length; k++) - { - var line = codeMap[debugData.states[k].curPC]; - if (line === statesList.currentIndex + 2) - { - select(k); - break; - } - } - } + if (isCallInstruction(currentSelectedState)) + stepOutForward(); else moveSelection(1); } function stepIntoForward() { - var state = debugData.states[currentSelectedState]; - if (state.instruction === "CALL" || state.instruction === "CREATE") - { - jumpStartingPoint = currentSelectedState; - moveSelection(1); - jumpOutBackAction.enabled(true); - jumpOutForwardAction.enabled(true); - } + moveSelection(1); +} + +function stepOutBack() +{ + var i = currentSelectedState - 1; + var depth = 0; + while (--i >= 0) + if (isCallInstruction(i)) + if (depth == 0) + break; + else depth--; + else if (isReturnInstruction(i)) + depth++; + select(i); } function stepOutForward() { - if (jumpStartingPoint != null) - { - stepOutBack(); - stepOverForward(); - jumpOutBackAction.enabled(false); - jumpOutForwardAction.enabled(false); - } + var i = currentSelectedState; + var depth = 0; + while (++i < debugData.states.length) + if (isReturnInstruction(i)) + if (depth == 0) + break; + else + depth--; + else if (isCallInstruction(i)) + depth++; + select(i + 1); } function jumpTo(value)