Browse Source

Debugger improvements.

cl-refactor
Gav Wood 11 years ago
parent
commit
0b8d5560d2
  1. 67
      alethzero/Main.ui
  2. 48
      alethzero/MainWin.cpp
  3. 21
      test/vm.cpp

67
alethzero/Main.ui

@ -932,6 +932,9 @@
</widget> </widget>
</widget> </widget>
<widget class="QDockWidget" name="dockWidget_9"> <widget class="QDockWidget" name="dockWidget_9">
<property name="floating">
<bool>false</bool>
</property>
<property name="features"> <property name="features">
<set>QDockWidget::DockWidgetFeatureMask</set> <set>QDockWidget::DockWidgetFeatureMask</set>
</property> </property>
@ -939,7 +942,7 @@
<string>Debugger</string> <string>Debugger</string>
</property> </property>
<attribute name="dockWidgetArea"> <attribute name="dockWidgetArea">
<number>8</number> <number>1</number>
</attribute> </attribute>
<widget class="QWidget" name="debugPanel"> <widget class="QWidget" name="debugPanel">
<property name="enabled"> <property name="enabled">
@ -966,19 +969,43 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="QListWidget" name="debugCode"> <widget class="QSplitter" name="splitter_42">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding"> <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch> <horstretch>1</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="frameShape"> <property name="orientation">
<enum>QFrame::NoFrame</enum> <enum>Qt::Vertical</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property> </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>
<widget class="QSplitter" name="splitter_4"> <widget class="QSplitter" name="splitter_4">
<property name="sizePolicy"> <property name="sizePolicy">
@ -990,15 +1017,18 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
<widget class="QListWidget" name="debugStack"> <widget class="QTextEdit" name="debugStack">
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::NoFrame</enum> <enum>QFrame::NoFrame</enum>
</property> </property>
<property name="lineWidth"> <property name="lineWidth">
<number>0</number> <number>0</number>
</property> </property>
<property name="selectionMode"> <property name="readOnly">
<enum>QAbstractItemView::NoSelection</enum> <bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property> </property>
</widget> </widget>
<widget class="QTextEdit" name="debugMemory"> <widget class="QTextEdit" name="debugMemory">
@ -1038,19 +1068,6 @@
</property> </property>
</widget> </widget>
</widget> </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>
</item> </item>
<item> <item>

48
alethzero/MainWin.cpp

@ -280,17 +280,22 @@ void Main::eval(QString const& _js)
ui->jsConsole->setHtml(s); ui->jsConsole->setHtml(s);
} }
QString fromRaw(eth::h256 _n) QString fromRaw(eth::h256 _n, unsigned* _inc = nullptr)
{ {
if (_n) if (_n)
{ {
std::string s((char const*)_n.data(), 32); std::string s((char const*)_n.data(), 32);
auto l = s.find_first_of('\0'); auto l = s.find_first_of('\0');
if (!l)
return QString();
if (l != string::npos) if (l != string::npos)
{ {
if (s.find_first_not_of('\0', l) != string::npos) auto p = s.find_first_not_of('\0', l);
if (!(p == string::npos || (_inc && p == 31)))
return QString(); return QString();
s.resize(s.find_first_of('\0')); if (_inc)
*_inc = (byte)s[31];
s.resize(l);
} }
for (auto i: s) for (auto i: s)
if (i < 32) if (i < 32)
@ -425,7 +430,7 @@ void Main::readSettings()
ui->idealPeers->setValue(s.value("idealPeers", ui->idealPeers->value()).toInt()); ui->idealPeers->setValue(s.value("idealPeers", ui->idealPeers->value()).toInt());
ui->port->setValue(s.value("port", ui->port->value()).toInt()); ui->port->setValue(s.value("port", ui->port->value()).toInt());
ui->nameReg->setText(s.value("NameReg", "").toString()); ui->nameReg->setText(s.value("NameReg", "").toString());
ui->urlEdit->setText(s.value("url", "http://gavwood.com/gavcoin.html").toString()); ui->urlEdit->setText(s.value("url", "about:blank").toString()); //http://gavwood.com/gavcoin.html
on_urlEdit_returnPressed(); on_urlEdit_returnPressed();
} }
@ -754,9 +759,9 @@ string Main::renderDiff(eth::StateDiff const& _d) const
s << std::hex << i.first; s << std::hex << i.first;
*/ */
if (!i.second.from()) if (!i.second.from())
s << ": " << prettyU256(i.second.to()).toHtmlEscaped().toStdString(); s << ": " << prettyU256(i.second.to()).toStdString();
else if (!i.second.to()) else if (!i.second.to())
s << " (" << prettyU256(i.second.from()).toHtmlEscaped().toStdString() << ")"; s << " (" << prettyU256(i.second.from()).toStdString() << ")";
else else
s << ": " << prettyU256(i.second.to()).toStdString() << " (" << prettyU256(i.second.from()).toStdString() << ")"; s << ": " << prettyU256(i.second.to()).toStdString() << " (" << prettyU256(i.second.from()).toStdString() << ")";
} }
@ -1338,7 +1343,12 @@ void Main::on_dumpTrace_triggered()
ofstream f(fn.toStdString()); ofstream f(fn.toStdString());
if (f.is_open()) if (f.is_open())
for (WorldState const& ws: m_history) for (WorldState const& ws: m_history)
{
if (ws.inst == Instruction::STOP || ws.inst == Instruction::RETURN || ws.inst == Instruction::SUICIDE)
for (auto i: ws.storage)
f << toHex(eth::toCompactBigEndian(i.first, 1)) << " " << toHex(eth::toCompactBigEndian(i.second, 1)) << endl;
f << ws.cur << " " << hex << toHex(eth::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(eth::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(eth::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl; f << ws.cur << " " << hex << toHex(eth::toCompactBigEndian(ws.curPC, 1)) << " " << hex << toHex(eth::toCompactBigEndian((int)(byte)ws.inst, 1)) << " " << hex << toHex(eth::toCompactBigEndian((uint64_t)ws.gas, 1)) << endl;
}
} }
void Main::on_callStack_currentItemChanged() void Main::on_callStack_currentItemChanged()
@ -1393,22 +1403,26 @@ void Main::on_debugTimeline_valueChanged()
QString Main::prettyU256(eth::u256 _n) const QString Main::prettyU256(eth::u256 _n) const
{ {
unsigned inc = 0;
QString raw;
ostringstream s; ostringstream s;
if (_n >> 32 == 0) if (!(_n >> 64))
s << hex << "0x" << (unsigned)_n; s << "<span style=\"color: #448\">0x</span><span style=\"color: #008\">" << (uint64_t)_n << "</span>";
else if (!~(_n >> 64))
s << "<span style=\"color: #448\">0x</span><span style=\"color: #008\">" << (int64_t)_n << "</span>";
else if (_n >> 200 == 0) else if (_n >> 200 == 0)
{ {
Address a = right160(_n); Address a = right160(_n);
QString n = pretty(a); QString n = pretty(a);
if (n.isNull()) if (n.isNull())
s << "0x" << a; s << "<span style=\"color: #844\">0x</span><span style=\"color: #800\">" << a << "</span>";
else else
s << "<b>" << n.toHtmlEscaped().toStdString() << "</b> (" << a.abridged() << ")"; s << "<span style=\"font-weight: bold; color: #800\">" << n.toHtmlEscaped().toStdString() << "</span> (<span style=\"color: #844\">0x</span><span style=\"color: #800\">" << a.abridged() << "</span>)";
} }
else if (fromRaw((h256)_n).size()) else if ((raw = fromRaw((h256)_n, &inc)).size())
return "\"" + fromRaw((h256)_n).toHtmlEscaped() + "\""; return "<span style=\"color: #484\">\"</span><span style=\"color: #080\">" + raw.toHtmlEscaped() + "</span><span style=\"color: #484\">\"" + (inc ? " + " + QString::number(inc) : "") + "</span>";
else else
s << "0x" << (h256)_n; s << "<span style=\"color: #466\">0x</span><span style=\"color: #044\">" << (h256)_n << "</span>";
return QString::fromStdString(s.str()); return QString::fromStdString(s.str());
} }
@ -1416,9 +1430,6 @@ void Main::updateDebugger()
{ {
if (m_history.size()) if (m_history.size())
{ {
QListWidget* ds = ui->debugStack;
ds->clear();
WorldState const& nws = m_history[min((int)m_history.size() - 1, ui->debugTimeline->value())]; WorldState const& nws = m_history[min((int)m_history.size() - 1, ui->debugTimeline->value())];
WorldState const& ws = ui->callStack->currentRow() > 0 ? *nws.levels[nws.levels.size() - ui->callStack->currentRow()] : nws; WorldState const& ws = ui->callStack->currentRow() > 0 ? *nws.levels[nws.levels.size() - ui->callStack->currentRow()] : nws;
@ -1453,6 +1464,7 @@ void Main::updateDebugger()
m_lastLevels.clear(); m_lastLevels.clear();
ui->debugCode->clear(); ui->debugCode->clear();
m_lastCode = h256(); m_lastCode = h256();
ui->debugStack->setHtml("");
} }
else else
{ {
@ -1514,8 +1526,10 @@ void Main::updateDebugger()
ui->debugCallData->setHtml(""); ui->debugCallData->setHtml("");
} }
QString stack;
for (auto i: ws.stack) for (auto i: ws.stack)
ds->insertItem(0, prettyU256(i)); stack.prepend("<div>" + prettyU256(i) + "</div>");
ui->debugStack->setHtml(stack);
ui->debugMemory->setHtml(QString::fromStdString(eth::memDump(ws.memory, 16, true))); ui->debugMemory->setHtml(QString::fromStdString(eth::memDump(ws.memory, 16, true)));
assert(m_codes.count(ws.code)); assert(m_codes.count(ws.code));
assert(m_codes[ws.code].size() > (unsigned)ws.curPC); assert(m_codes[ws.code].size() > (unsigned)ws.curPC);

21
test/vm.cpp

@ -409,10 +409,7 @@ void doTests(json_spirit::mValue& v, bool _fillin)
o["exec"] = mValue(fev.exportExec()); o["exec"] = mValue(fev.exportExec());
o["post"] = mValue(fev.exportState()); o["post"] = mValue(fev.exportState());
o["callcreates"] = fev.exportCallCreates(); o["callcreates"] = fev.exportCallCreates();
mArray df; o["out"] = "0x" + toHex(output);
for (auto const& i: output)
FakeExtVM::push(df, i);
o["out"] = df;
fev.push(o, "gas", vm.gas()); fev.push(o, "gas", vm.gas());
} }
else else
@ -426,11 +423,17 @@ void doTests(json_spirit::mValue& v, bool _fillin)
test.importState(o["post"].get_obj()); test.importState(o["post"].get_obj());
test.importCallCreates(o["callcreates"].get_array()); test.importCallCreates(o["callcreates"].get_array());
int i = 0; int i = 0;
for (auto const& d: o["out"].get_array()) if (o["out"].type() == array_type)
{ for (auto const& d: o["out"].get_array())
BOOST_CHECK_MESSAGE(output[i] == FakeExtVM::toInt(d), "Output byte [" << i << "] different!"); {
++i; BOOST_CHECK_MESSAGE(output[i] == FakeExtVM::toInt(d), "Output byte [" << i << "] different!");
} ++i;
}
else if (o["out"].get_str().find("0x") == 0)
BOOST_CHECK(output == fromHex(o["out"].get_str().substr(2)));
else
BOOST_CHECK(output == fromHex(o["out"].get_str()));
BOOST_CHECK(FakeExtVM::toInt(o["gas"]) == vm.gas()); BOOST_CHECK(FakeExtVM::toInt(o["gas"]) == vm.gas());
BOOST_CHECK(test.addresses == fev.addresses); BOOST_CHECK(test.addresses == fev.addresses);
BOOST_CHECK(test.callcreates == fev.callcreates); BOOST_CHECK(test.callcreates == fev.callcreates);

Loading…
Cancel
Save