Browse Source

Debugger separate from AlethZero mainwin.

cl-refactor
Gav Wood 10 years ago
parent
commit
5fe0aca0b6
  1. 3
      alethzero/CMakeLists.txt
  2. 26
      alethzero/Context.cpp
  3. 41
      alethzero/Context.h
  4. 372
      alethzero/Debugger.cpp
  5. 102
      alethzero/Debugger.h
  6. 238
      alethzero/Debugger.ui
  7. 35
      alethzero/MainWin.h
  8. 3
      libdevcore/vector_ref.h

3
alethzero/CMakeLists.txt

@ -15,6 +15,7 @@ include_directories(BEFORE ${JSONCPP_INCLUDE_DIRS})
include_directories(${JSON_RPC_CPP_INCLUDE_DIRS})
qt5_wrap_ui(ui_Main.h Main.ui)
qt5_wrap_ui(ui_Debugger.h Debugger.ui)
file(GLOB HEADERS "*.h")
@ -27,7 +28,7 @@ endif ()
# eth_add_executable is defined in cmake/EthExecutableHelper.cmake
eth_add_executable(${EXECUTABLE}
ICON alethzero
UI_RESOURCES alethzero.icns Main.ui
UI_RESOURCES alethzero.icns Main.ui Debugger.ui
WIN_RESOURCES alethzero.rc
)

26
alethzero/Context.cpp

@ -0,0 +1,26 @@
/*
This file is part of cpp-ethereum.
cpp-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.
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Debugger.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "Context.h"
Context::~Context()
{
}

41
alethzero/Context.h

@ -0,0 +1,41 @@
/*
This file is part of cpp-ethereum.
cpp-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.
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Debugger.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <string>
#include <QString>
#include <libethcore/CommonEth.h>
namespace dev { namespace eth { class StateDiff; } }
class Context
{
public:
virtual ~Context();
virtual QString pretty(dev::Address _a) const = 0;
virtual QString prettyU256(dev::u256 _n) const = 0;
virtual QString render(dev::Address _a) const = 0;
virtual dev::Address fromString(QString const& _a) const = 0;
virtual std::string renderDiff(dev::eth::StateDiff const& _d) const = 0;
};

372
alethzero/Debugger.cpp

@ -0,0 +1,372 @@
/*
This file is part of cpp-ethereum.
cpp-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.
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Debugger.cpp
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#include "Debugger.h"
#include <fstream>
#include <QFileDialog>
#include <libevm/VM.h>
#include <libethereum/ExtVM.h>
#include <libethereum/Executive.h>
#include "ui_Debugger.h"
using namespace std;
using namespace dev;
using namespace dev::eth;
Debugger::Debugger(Context* _c, QWidget* _parent):
QDialog(_parent),
ui(new Ui::Debugger),
m_context(_c)
{
ui->setupUi(this);
}
Debugger::~Debugger()
{
delete ui;
}
void Debugger::init()
{
if (m_session.history.size())
{
alterDebugStateGroup(true);
ui->debugCode->setEnabled(false);
ui->debugTimeline->setMinimum(0);
ui->debugTimeline->setMaximum(m_session.history.size());
ui->debugTimeline->setValue(0);
}
}
void Debugger::populate(dev::eth::Executive& _executive, dev::bytesConstRef _transactionRLP)
{
finished();
if (m_session.populate(_executive, _transactionRLP))
init();
update();
}
bool DebugSession::populate(dev::eth::Executive& _executive, dev::bytesConstRef _transactionRLP)
{
if (_executive.setup(_transactionRLP))
return false;
vector<WorldState const*> levels;
bytes lastExtCode;
bytesConstRef lastData;
h256 lastHash;
h256 lastDataHash;
auto onOp = [&](uint64_t steps, Instruction inst, dev::bigint newMemSize, dev::bigint gasCost, VM* voidVM, ExtVMFace const* voidExt)
{
VM& vm = *voidVM;
ExtVM const& ext = *static_cast<ExtVM const*>(voidExt);
if (ext.code != lastExtCode)
{
lastExtCode = ext.code;
lastHash = sha3(lastExtCode);
if (!codes.count(lastHash))
codes[lastHash] = ext.code;
}
if (ext.data != lastData)
{
lastData = ext.data;
lastDataHash = sha3(lastData);
if (!codes.count(lastDataHash))
codes[lastDataHash] = ext.data.toBytes();
}
if (levels.size() < ext.depth)
levels.push_back(&history.back());
else
levels.resize(ext.depth);
history.append(WorldState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), lastHash, lastDataHash, vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels}));
};
_executive.go(onOp);
_executive.finalize();
return true;
}
void Debugger::finished()
{
m_session = DebugSession();
ui->callStack->clear();
ui->debugCode->clear();
ui->debugStack->clear();
ui->debugMemory->setHtml("");
ui->debugStorage->setHtml("");
ui->debugStateInfo->setText("");
alterDebugStateGroup(false);
}
void Debugger::update()
{
if (m_session.history.size())
{
WorldState const& nws = m_session.history[min((int)m_session.history.size() - 1, ui->debugTimeline->value())];
WorldState const& ws = ui->callStack->currentRow() > 0 ? *nws.levels[nws.levels.size() - ui->callStack->currentRow()] : nws;
if (ui->debugTimeline->value() >= m_session.history.size())
{
if (ws.gasCost > ws.gas)
ui->debugMemory->setHtml("<h3>OUT-OF-GAS</h3>");
else if (ws.inst == Instruction::RETURN && ws.stack.size() >= 2)
{
unsigned from = (unsigned)ws.stack.back();
unsigned size = (unsigned)ws.stack[ws.stack.size() - 2];
unsigned o = 0;
bytes out(size, 0);
for (; o < size && from + o < ws.memory.size(); ++o)
out[o] = ws.memory[from + o];
ui->debugMemory->setHtml("<h3>RETURN</h3>" + QString::fromStdString(dev::memDump(out, 16, true)));
}
else if (ws.inst == Instruction::STOP)
ui->debugMemory->setHtml("<h3>STOP</h3>");
else if (ws.inst == Instruction::SUICIDE && ws.stack.size() >= 1)
ui->debugMemory->setHtml("<h3>SUICIDE</h3>0x" + QString::fromStdString(toString(right160(ws.stack.back()))));
else
ui->debugMemory->setHtml("<h3>EXCEPTION</h3>");
ostringstream ss;
ss << dec << "EXIT | GAS: " << dec << max<dev::bigint>(0, (dev::bigint)ws.gas - ws.gasCost);
ui->debugStateInfo->setText(QString::fromStdString(ss.str()));
ui->debugStorage->setHtml("");
ui->debugCallData->setHtml("");
m_session.currentData = h256();
ui->callStack->clear();
m_session.currentLevels.clear();
ui->debugCode->clear();
m_session.currentCode = h256();
ui->debugStack->setHtml("");
}
else
{
if (m_session.currentLevels != nws.levels || !ui->callStack->count())
{
m_session.currentLevels = nws.levels;
ui->callStack->clear();
for (unsigned i = 0; i <= nws.levels.size(); ++i)
{
WorldState const& s = i ? *nws.levels[nws.levels.size() - i] : nws;
ostringstream out;
out << s.cur.abridged();
if (i)
out << " " << instructionInfo(s.inst).name << " @0x" << hex << s.curPC;
ui->callStack->addItem(QString::fromStdString(out.str()));
}
}
if (ws.code != m_session.currentCode)
{
m_session.currentCode = ws.code;
bytes const& code = m_session.codes[ws.code];
QListWidget* dc = ui->debugCode;
dc->clear();
m_session.pcWarp.clear();
for (unsigned i = 0; i <= code.size(); ++i)
{
byte b = i < code.size() ? code[i] : 0;
try
{
QString s = QString::fromStdString(instructionInfo((Instruction)b).name);
ostringstream out;
out << hex << setw(4) << setfill('0') << i;
m_session.pcWarp[i] = dc->count();
if (b >= (byte)Instruction::PUSH1 && b <= (byte)Instruction::PUSH32)
{
unsigned bc = b - (byte)Instruction::PUSH1 + 1;
s = "PUSH 0x" + QString::fromStdString(toHex(bytesConstRef(&code[i + 1], bc)));
i += bc;
}
dc->addItem(QString::fromStdString(out.str()) + " " + s);
}
catch (...)
{
cerr << "Unhandled exception!" << endl << boost::current_exception_diagnostic_information();
break; // probably hit data segment
}
}
}
if (ws.callData != m_session.currentData)
{
m_session.currentData = ws.callData;
if (ws.callData)
{
assert(m_session.codes.count(ws.callData));
ui->debugCallData->setHtml(QString::fromStdString(dev::memDump(m_session.codes[ws.callData], 16, true)));
}
else
ui->debugCallData->setHtml("");
}
QString stack;
for (auto i: ws.stack)
stack.prepend("<div>" + m_context->prettyU256(i) + "</div>");
ui->debugStack->setHtml(stack);
ui->debugMemory->setHtml(QString::fromStdString(dev::memDump(ws.memory, 16, true)));
assert(m_session.codes.count(ws.code));
if (m_session.codes[ws.code].size() >= (unsigned)ws.curPC)
{
int l = m_session.pcWarp[(unsigned)ws.curPC];
ui->debugCode->setCurrentRow(max(0, l - 5));
ui->debugCode->setCurrentRow(min(ui->debugCode->count() - 1, l + 5));
ui->debugCode->setCurrentRow(l);
}
else
cwarn << "PC (" << (unsigned)ws.curPC << ") is after code range (" << m_session.codes[ws.code].size() << ")";
ostringstream ss;
ss << dec << "STEP: " << ws.steps << " | PC: 0x" << hex << ws.curPC << " : " << instructionInfo(ws.inst).name << " | ADDMEM: " << dec << ws.newMemSize << " words | COST: " << dec << ws.gasCost << " | GAS: " << dec << ws.gas;
ui->debugStateInfo->setText(QString::fromStdString(ss.str()));
stringstream s;
for (auto const& i: ws.storage)
s << "@" << m_context->prettyU256(i.first).toStdString() << "&nbsp;&nbsp;&nbsp;&nbsp;" << m_context->prettyU256(i.second).toStdString() << "<br/>";
ui->debugStorage->setHtml(QString::fromStdString(s.str()));
}
}
}
void Debugger::on_callStack_currentItemChanged()
{
update();
}
void Debugger::alterDebugStateGroup(bool _enable) const
{
ui->stepOver->setEnabled(_enable);
ui->stepInto->setEnabled(_enable);
ui->stepOut->setEnabled(_enable);
ui->backOver->setEnabled(_enable);
ui->backInto->setEnabled(_enable);
ui->backOut->setEnabled(_enable);
ui->dump->setEnabled(_enable);
ui->dumpStorage->setEnabled(_enable);
ui->dumpPretty->setEnabled(_enable);
}
void Debugger::on_debugTimeline_valueChanged()
{
update();
}
void Debugger::on_stepOver_triggered()
{
if (ui->debugTimeline->value() < m_session.history.size()) {
auto l = m_session.history[ui->debugTimeline->value()].levels.size();
if ((ui->debugTimeline->value() + 1) < m_session.history.size() && m_session.history[ui->debugTimeline->value() + 1].levels.size() > l)
{
on_stepInto_triggered();
if (m_session.history[ui->debugTimeline->value()].levels.size() > l)
on_stepOut_triggered();
}
else
on_stepInto_triggered();
}
}
void Debugger::on_stepInto_triggered()
{
ui->debugTimeline->setValue(ui->debugTimeline->value() + 1);
ui->callStack->setCurrentRow(0);
}
void Debugger::on_stepOut_triggered()
{
if (ui->debugTimeline->value() < m_session.history.size())
{
auto ls = m_session.history[ui->debugTimeline->value()].levels.size();
auto l = ui->debugTimeline->value();
for (; l < m_session.history.size() && m_session.history[l].levels.size() >= ls; ++l) {}
ui->debugTimeline->setValue(l);
ui->callStack->setCurrentRow(0);
}
}
void Debugger::on_backInto_triggered()
{
ui->debugTimeline->setValue(ui->debugTimeline->value() - 1);
ui->callStack->setCurrentRow(0);
}
void Debugger::on_backOver_triggered()
{
auto l = m_session.history[ui->debugTimeline->value()].levels.size();
if (ui->debugTimeline->value() > 0 && m_session.history[ui->debugTimeline->value() - 1].levels.size() > l)
{
on_backInto_triggered();
if (m_session.history[ui->debugTimeline->value()].levels.size() > l)
on_backOut_triggered();
}
else
on_backInto_triggered();
}
void Debugger::on_backOut_triggered()
{
if (ui->debugTimeline->value() > 0 && m_session.history.size() > 0)
{
auto ls = m_session.history[min(ui->debugTimeline->value(), m_session.history.size() - 1)].levels.size();
int l = ui->debugTimeline->value();
for (; l > 0 && m_session.history[l].levels.size() >= ls; --l) {}
ui->debugTimeline->setValue(l);
ui->callStack->setCurrentRow(0);
}
}
void Debugger::on_dump_triggered()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_session.history)
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl;
}
void Debugger::on_dumpPretty_triggered()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_session.history)
{
f << endl << " STACK" << endl;
for (auto i: ws.stack)
f << (h256)i << endl;
f << " MEMORY" << endl << dev::memDump(ws.memory);
f << " STORAGE" << endl;
for (auto const& i: ws.storage)
f << showbase << hex << i.first << ": " << i.second << endl;
f << dec << ws.levels.size() << " | " << ws.cur << " | #" << ws.steps << " | " << hex << setw(4) << setfill('0') << ws.curPC << " : " << instructionInfo(ws.inst).name << " | " << dec << ws.gas << " | -" << dec << ws.gasCost << " | " << ws.newMemSize << "x32";
}
}
void Debugger::on_dumpStorage_triggered()
{
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_session.history)
{
if (ws.inst == Instruction::STOP || ws.inst == Instruction::RETURN || ws.inst == Instruction::SUICIDE)
for (auto i: ws.storage)
f << toHex(dev::toCompactBigEndian(i.first, 1)) << " " << toHex(dev::toCompactBigEndian(i.second, 1)) << endl;
f << ws.cur << " " << hex << toHex(dev::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(dev::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(dev::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl;
}
}

102
alethzero/Debugger.h

@ -0,0 +1,102 @@
/*
This file is part of cpp-ethereum.
cpp-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.
cpp-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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Debugger.h
* @author Gav Wood <i@gavwood.com>
* @date 2015
*/
#pragma once
#include <libdevcore/RLP.h>
#include <libethcore/CommonEth.h>
#include <libethereum/State.h>
#include <libethereum/Executive.h>
#include <QDialog>
#include <QMap>
#include <QList>
#include "Context.h"
namespace Ui { class Debugger; }
struct WorldState
{
uint64_t steps;
dev::Address cur;
dev::u256 curPC;
dev::eth::Instruction inst;
dev::bigint newMemSize;
dev::u256 gas;
dev::h256 code;
dev::h256 callData;
dev::u256s stack;
dev::bytes memory;
dev::bigint gasCost;
std::map<dev::u256, dev::u256> storage;
std::vector<WorldState const*> levels;
};
struct DebugSession
{
DebugSession() {}
bool populate(dev::eth::Executive& _executive, dev::bytesConstRef _transactionRLP);
dev::h256 currentCode;
dev::h256 currentData;
std::vector<WorldState const*> currentLevels;
QMap<unsigned, unsigned> pcWarp;
QList<WorldState> history;
std::map<dev::u256, dev::bytes> codes;
};
class Debugger: public QDialog
{
Q_OBJECT
public:
explicit Debugger(Context* _context, QWidget* _parent = 0);
~Debugger();
void populate(dev::eth::Executive& _executive, dev::bytesConstRef _transactionRLP);
protected slots:
void on_callStack_currentItemChanged();
void on_debugTimeline_valueChanged();
void on_stepOver_triggered();
void on_stepInto_triggered();
void on_stepOut_triggered();
void on_backOver_triggered();
void on_backInto_triggered();
void on_backOut_triggered();
void on_dump_triggered();
void on_dumpPretty_triggered();
void on_dumpStorage_triggered();
private:
void init();
void update();
void finished();
void alterDebugStateGroup(bool _enable) const;
Ui::Debugger* ui;
DebugSession m_session;
Context* m_context;
};

238
alethzero/Debugger.ui

@ -0,0 +1,238 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Debugger</class>
<widget class="QDialog" name="Debugger">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>946</width>
<height>690</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="stepOver">
<property name="text">
<string>Step Over</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="stepInto">
<property name="text">
<string>Step Into</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="stepOut">
<property name="text">
<string>Step Out</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backOver">
<property name="text">
<string>Back Over</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backInto">
<property name="text">
<string>Back Into</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="backOut">
<property name="text">
<string>Back Out</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="dump">
<property name="text">
<string>Dump</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="dumpPretty">
<property name="text">
<string>Dump Pretty</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="dumpStorage">
<property name="text">
<string>Dump Storage</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QSplitter" name="splitter_42">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QListWidget" name="debugCode">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
<widget class="QListWidget" name="callStack">
<property name="font">
<font>
<family>Ubuntu Mono</family>
</font>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
</widget>
</widget>
<widget class="QSplitter" name="splitter_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<widget class="QTextEdit" name="debugStack">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugMemory">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugStorage">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugCallData">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</widget>
</item>
<item>
<widget class="QLabel" name="debugStateInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="debugTimeline">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

35
alethzero/MainWin.h

@ -37,7 +37,8 @@
#include <libqwebthree/QWebThree.h>
#include <libwebthree/WebThree.h>
#include <libsolidity/CompilerStack.h>
#include "Context.h"
#include "Debugger.h"
#include "NatspecHandler.h"
namespace Ui {
@ -52,28 +53,11 @@ class State;
class QQuickView;
class OurWebThreeStubServer;
struct WorldState
{
uint64_t steps;
dev::Address cur;
dev::u256 curPC;
dev::eth::Instruction inst;
dev::bigint newMemSize;
dev::u256 gas;
dev::h256 code;
dev::h256 callData;
dev::u256s stack;
dev::bytes memory;
dev::bigint gasCost;
std::map<dev::u256, dev::u256> storage;
std::vector<WorldState const*> levels;
};
using WatchHandler = std::function<void(dev::eth::LocalisedLogEntries const&)>;
QString contentsOfQResource(std::string const& res);
class Main : public QMainWindow
class Main: public QMainWindow, public Context
{
Q_OBJECT
@ -179,9 +163,6 @@ signals:
private:
dev::p2p::NetworkPreferences netPrefs() const;
QString pretty(dev::Address _a) const;
QString prettyU256(dev::u256 _n) const;
QString lookup(QString const& _n) const;
dev::Address getNameReg() const;
dev::Address getCurrencies() const;
@ -190,9 +171,12 @@ private:
void initDebugger();
void updateDebugger();
void debugFinished();
QString render(dev::Address _a) const;
dev::Address fromString(QString const& _a) const;
std::string renderDiff(dev::eth::StateDiff const& _d) const;
QString pretty(dev::Address _a) const override;
QString prettyU256(dev::u256 _n) const override;
QString render(dev::Address _a) const override;
dev::Address fromString(QString const& _a) const override;
std::string renderDiff(dev::eth::StateDiff const& _d) const override;
void alterDebugStateGroup(bool _enable) const;
@ -269,6 +253,7 @@ private:
QMap<unsigned, unsigned> m_pcWarp;
QList<WorldState> m_history;
std::map<dev::u256, dev::bytes> m_codes; // and pcWarps
bool m_enableOptimizer = true;
QNetworkAccessManager m_webCtrl;

3
libdevcore/vector_ref.h

@ -1,7 +1,8 @@
#pragma once
#include <type_traits>
#include <cstring>
#include <cassert>
#include <type_traits>
#include <vector>
#include <string>

Loading…
Cancel
Save