Browse Source

Debugger improvements.

cl-refactor
Gav Wood 11 years ago
parent
commit
c565cb3aff
  1. 12
      alethzero/Main.ui
  2. 100
      alethzero/MainWin.cpp
  3. 4
      alethzero/MainWin.h

12
alethzero/Main.ui

@ -1010,7 +1010,7 @@
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::NoTextInteraction</set>
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
<widget class="QTextEdit" name="debugStorage">
@ -1024,7 +1024,15 @@
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::NoTextInteraction</set>
<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>

100
alethzero/MainWin.cpp

@ -27,6 +27,7 @@
#include <QtWebKitWidgets/QWebFrame>
#include <QtGui/QClipboard>
#include <QtCore/QtCore>
#include <boost/algorithm/string.hpp>
#include <libserpent/funcs.h>
#include <libserpent/util.h>
#include <libethcore/Dagger.h>
@ -284,8 +285,16 @@ QString fromRaw(eth::h256 _n)
if (_n)
{
std::string s((char const*)_n.data(), 32);
if (s.find_first_of('\0') != string::npos)
auto l = s.find_first_of('\0');
if (l != string::npos)
{
if (s.find_first_not_of('\0', l) != string::npos)
return QString();
s.resize(s.find_first_of('\0'));
}
for (auto i: s)
if (i < 32)
return QString();
return QString::fromStdString(s);
}
return QString();
@ -916,7 +925,9 @@ void Main::populateDebugger(eth::bytesConstRef _r)
vector<WorldState const*> levels;
m_codes.clear();
bytesConstRef lastExtCode;
bytesConstRef lastData;
h256 lastHash;
h256 lastDataHash;
auto onOp = [&](uint64_t steps, Instruction inst, unsigned newMemSize, eth::bigint gasCost, void* voidVM, void const* voidExt)
{
eth::VM& vm = *(eth::VM*)voidVM;
@ -928,11 +939,18 @@ void Main::populateDebugger(eth::bytesConstRef _r)
if (!m_codes.count(lastHash))
m_codes[lastHash] = ext.code.toBytes();
}
if (ext.data != lastData)
{
lastData = ext.data;
lastDataHash = sha3(lastData);
if (!m_codes.count(lastDataHash))
m_codes[lastDataHash] = ext.data.toBytes();
}
if (levels.size() < ext.level)
levels.push_back(&m_history.back());
else
levels.resize(ext.level);
m_history.append(WorldState({steps, ext.myAddress, vm.curPC(), inst, newMemSize, vm.gas(), lastHash, vm.stack(), vm.memory(), gasCost, ext.state().storage(ext.myAddress), levels}));
m_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}));
};
m_currentExecution->go(onOp);
initDebugger();
@ -1243,28 +1261,28 @@ void Main::on_debug_clicked()
debugFinished();
try
{
u256 totalReq = value() + fee();
eth::ClientGuard l(&*m_client);
for (auto i: m_myKeys)
if (m_client->state().balance(i.address()) >= totalReq)
{
Secret s = i.secret();
m_executiveState = state();
m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState));
Transaction t;
t.nonce = m_executiveState.transactionsFrom(toAddress(s));
t.value = value();
t.gasPrice = gasPrice();
t.gas = ui->gas->value();
t.data = m_data;
t.receiveAddress = isCreation() ? Address() : fromString(ui->destination->currentText());
t.sign(s);
auto r = t.rlp();
populateDebugger(&r);
m_currentExecution.reset();
return;
}
statusBar()->showMessage("Couldn't make transaction: no single account contains at least the required amount.");
u256 totalReq = value() + fee();
eth::ClientGuard l(&*m_client);
for (auto i: m_myKeys)
if (m_client->state().balance(i.address()) >= totalReq)
{
Secret s = i.secret();
m_executiveState = state();
m_currentExecution = unique_ptr<Executive>(new Executive(m_executiveState));
Transaction t;
t.nonce = m_executiveState.transactionsFrom(toAddress(s));
t.value = value();
t.gasPrice = gasPrice();
t.gas = ui->gas->value();
t.data = m_data;
t.receiveAddress = isCreation() ? Address() : fromString(ui->destination->currentText());
t.sign(s);
auto r = t.rlp();
populateDebugger(&r);
m_currentExecution.reset();
return;
}
statusBar()->showMessage("Couldn't make transaction: no single account contains at least the required amount.");
}
catch (eth::Exception const& _e)
{
@ -1292,9 +1310,11 @@ void Main::on_debugStepback_triggered()
void Main::on_dumpTrace_triggered()
{
for (auto i: m_history)
{
}
QString fn = QFileDialog::getSaveFileName(this, "Select file to output EVM trace");
ofstream f(fn.toStdString());
if (f.is_open())
for (WorldState const& ws: m_history)
f << ws.cur << " " << hex << (int)ws.curPC << " " << hex << (int)(byte)ws.inst << " " << hex << (uint64_t)ws.gas << endl;
}
void Main::on_callStack_currentItemChanged()
@ -1308,7 +1328,7 @@ void Main::debugFinished()
m_pcWarp.clear();
m_history.clear();
m_lastLevels.clear();
m_inDebug = h256();
m_lastCode = h256();
ui->callStack->clear();
ui->debugCode->clear();
ui->debugStack->clear();
@ -1369,7 +1389,7 @@ void Main::updateDebugger()
WorldState const& ws = ui->callStack->currentRow() > 0 ? *nws.levels[nws.levels.size() - ui->callStack->currentRow()] : nws;
if (ws.code != m_inDebug)
if (ws.code != m_lastCode)
{
bytes const& code = m_codes[ws.code];
QListWidget* dc = ui->debugCode;
@ -1397,11 +1417,29 @@ void Main::updateDebugger()
break; // probably hit data segment
}
}
m_inDebug = ws.code;
m_lastCode = ws.code;
}
if (ws.callData != m_lastData)
{
m_lastData = ws.callData;
assert(m_codes.count(ws.callData));
ui->debugCallData->setHtml(QString::fromStdString(eth::memDump(m_codes[ws.callData], 16, true)));
}
for (auto i: ws.stack)
ds->insertItem(0, QString::fromStdString(toHex(((h256)i).asArray())));
{
ostringstream s;
if (i >> 32 == 0)
s << hex << "0x" << (unsigned)i;
else if (i >> 200 == 0)
s << "0x" << (h160)right160(i);
else if (fromRaw((h256)i).size())
s << "\"" << fromRaw((h256)i).toStdString() << "\"";
else
s << "0x" << (h256)i;
ds->insertItem(0, QString::fromStdString(s.str()));
}
ui->debugMemory->setHtml(QString::fromStdString(eth::memDump(ws.memory, 16, true)));
assert(m_codes.count(ws.code));
assert(m_codes[ws.code].size() > (unsigned)ws.curPC);

4
alethzero/MainWin.h

@ -52,6 +52,7 @@ struct WorldState
unsigned newMemSize;
eth::u256 gas;
eth::h256 code;
eth::h256 callData;
eth::u256s stack;
eth::bytes memory;
eth::bigint gasCost;
@ -177,7 +178,8 @@ private:
eth::State m_executiveState;
std::unique_ptr<eth::Executive> m_currentExecution;
eth::h256 m_inDebug;
eth::h256 m_lastCode;
eth::h256 m_lastData;
std::vector<WorldState const*> m_lastLevels;
QMap<unsigned, unsigned> m_pcWarp;

Loading…
Cancel
Save