Browse Source

bebugger bugfixes

cl-refactor
arkpar 10 years ago
parent
commit
f1a35dcaf0
  1. 130
      mix/DebuggingStateWrapper.cpp
  2. 6
      mix/DebuggingStateWrapper.h
  3. 2
      mix/MixApplication.cpp
  4. 30
      mix/qml/Debugger.qml
  5. 15
      mix/qml/ItemDelegateDataDump.qml
  6. 2
      mix/qml/StepActionImage.qml
  7. 3
      mix/qml/html/codeeditor.js
  8. 116
      mix/qml/js/Debugger.js

130
mix/DebuggingStateWrapper.cpp

@ -20,7 +20,7 @@
* Used to translate c++ type (u256, bytes, ...) into friendly value (to be used by QML).
*/
#include <QApplication>
#include <tuple>
#include <QDebug>
#include <QPointer>
#include <QQmlEngine>
@ -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<u256>::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<std::vector<std::string>> 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<std::vector<std::string>> dump = memDumpToList(_data, 16);
QStringList filled;
filled.append(" ");
filled.append(" ");
filled.append(" ");
return new QCallData(_owner, fillList(qVariantDump(dump), QVariant(filled)));
}
std::vector<std::vector<std::string>> QMachineState::memDumpToList(bytes const& _bytes, unsigned _width)
{
std::vector<std::vector<std::string>> dump;
for (unsigned i = 0; i < _bytes.size(); i += _width)
{
std::stringstream ret;
std::vector<std::string> 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<std::vector<std::string>> const& _dump)
{
QVariantList ret;
for (std::vector<std::string> 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");
}

6
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<std::vector<std::string>> 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<std::vector<std::string>> memDumpToList(bytes const& _bytes, unsigned _width);
};
}

2
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");

30
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
}
}

15
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 {

2
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();
}

3
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;

116
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)

Loading…
Cancel
Save