Commit 84f1fcc7 authored by hjk's avatar hjk
Browse files

Debugger: Show raw opcode bytes in disassembler view



Change-Id: I420dd5e9af4a92c84d53dbd52837be8f84440995
Reviewed-by: default avatarDavid Schulz <david.schulz@digia.com>
parent 0c294aa1
......@@ -324,12 +324,7 @@ void DisassemblerAgent::setContentsToEditor(const DisassemblerLines &contents)
qobject_cast<QPlainTextEdit *>(d->editor->widget());
QTC_ASSERT(plainTextEdit, return);
QString str;
for (int i = 0, n = contents.size(); i != n; ++i) {
str += contents.at(i).toString();
str += QLatin1Char('\n');
}
plainTextEdit->setPlainText(str);
plainTextEdit->setPlainText(contents.toString());
plainTextEdit->setReadOnly(true);
d->editor->document()->setDisplayName(_("Disassembler (%1)")
......
......@@ -170,17 +170,22 @@ void DisassemblerLines::appendUnparsed(const QString &unparsed)
line = line.mid(3);
if (line.startsWith(QLatin1String("0x"))) {
// Address line. Split at the tab.
int tab = line.indexOf(QLatin1Char('\t'));
if (tab == -1) {
int tab1 = line.indexOf(QLatin1Char('\t'));
if (tab1 == -1) {
appendComment(line);
return;
}
QString address = line.left(tab);
int tab2 = line.indexOf(QLatin1Char('\t'), tab1 + 1);
if (tab2 == -1)
tab2 = tab1;
QString address = line.left(tab1);
if (address.endsWith(QLatin1Char(':')))
address.chop(1);
int pos1 = address.indexOf(QLatin1Char('<')) + 1;
DisassemblerLine dl;
dl.data = line.mid(tab).trimmed();
dl.bytes = line.mid(tab1, tab2 - tab1).trimmed();
m_bytesLength = qMax(m_bytesLength, tab2 - tab1);
dl.data = line.mid(tab2).trimmed();
if (pos1 && address.indexOf(QLatin1String("<UNDEFINED> instruction:")) == -1) {
if (address.endsWith(QLatin1Char('>')))
address.chop(1);
......@@ -213,7 +218,7 @@ void DisassemblerLines::appendUnparsed(const QString &unparsed)
}
}
QString DisassemblerLine::toString() const
QString DisassemblerLine::toString(int maxOp) const
{
const QString someSpace = _(" ");
QString str;
......@@ -224,7 +229,8 @@ QString DisassemblerLine::toString() const
str += _("<+0x%2> ").arg(offset, 4, 16, QLatin1Char('0'));
else
str += _(" ");
str += _(" ");
str += _(" %1 ").arg(bytes);
str += QString(maxOp - bytes.size(), QLatin1Char(' '));
str += data;
} else if (isCode()) {
if (hunk)
......@@ -238,5 +244,15 @@ QString DisassemblerLine::toString() const
return str;
}
QString DisassemblerLines::toString() const
{
QString str;
for (int i = 0, n = size(); i != n; ++i) {
str += m_data.at(i).toString(m_bytesLength);
str += QLatin1Char('\n');
}
return str;
}
} // namespace Internal
} // namespace Debugger
......@@ -49,7 +49,7 @@ public:
bool isAssembler() const { return address != 0; }
bool isCode() const { return lineNumber != 0; }
bool isComment() const { return lineNumber == 0 && address == 0; }
QString toString() const;
QString toString(int maxOp = 0) const;
void fromString(const QString &unparsed);
// Return address of an assembly line "0x0dfd bla".
......@@ -63,12 +63,13 @@ public:
uint hunk; // (src) Number of hunk if source line was split
QByteArray rawData; // (ass) Raw bytes of the instruction
QString data; // (ass) Instruction text, (src) source text, (cmt) arbitrary.
QString bytes; // (ass) The instruction in raw bytes
};
class DisassemblerLines
{
public:
DisassemblerLines() {}
DisassemblerLines() : m_bytesLength(0) {}
bool coversAddress(quint64 address) const;
void appendUnparsed(const QString &line);
......@@ -76,6 +77,9 @@ public:
void appendComment(const QString &line);
// Mixed source/assembly: Retrieve contents of source (cached)
void appendSourceLine(const QString &fileName, uint line);
QString toString() const;
void setBytesLength(int x) { m_bytesLength = x; }
int bytesLength() const { return m_bytesLength; }
int size() const { return m_data.size(); }
const DisassemblerLine &at(int i) const { return m_data.at(i); }
......@@ -87,6 +91,7 @@ public:
private:
QString m_lastFunction;
int m_bytesLength;
QVector<DisassemblerLine> m_data;
QHash<quint64, int> m_rowCache;
};
......
......@@ -3976,7 +3976,7 @@ void GdbEngine::fetchDisassembler(DisassemblerAgent *agent)
static inline QByteArray disassemblerCommand(const Location &location, bool mixed)
{
QByteArray command = "disassemble ";
QByteArray command = "disassemble /r ";
if (mixed)
command += "/m ";
if (const quint64 address = location.address()) {
......@@ -4006,7 +4006,7 @@ void GdbEngine::fetchDisassemblerByCliRangeMixed(const DisassemblerAgentCookie &
const quint64 address = ac.agent->address();
QByteArray start = QByteArray::number(address - 20, 16);
QByteArray end = QByteArray::number(address + 100, 16);
QByteArray cmd = "disassemble /m 0x" + start + ",0x" + end;
QByteArray cmd = "disassemble /r /m 0x" + start + ",0x" + end;
postCommand(cmd, Discardable|ConsoleCommand,
CB(handleFetchDisassemblerByCliRangeMixed), QVariant::fromValue(ac));
}
......@@ -4019,7 +4019,7 @@ void GdbEngine::fetchDisassemblerByCliRangePlain(const DisassemblerAgentCookie &
const quint64 address = ac.agent->address();
QByteArray start = QByteArray::number(address - 20, 16);
QByteArray end = QByteArray::number(address + 100, 16);
QByteArray cmd = "disassemble 0x" + start + ",0x" + end;
QByteArray cmd = "disassemble /r 0x" + start + ",0x" + end;
postCommand(cmd, Discardable,
CB(handleFetchDisassemblerByCliRangePlain), QVariant::fromValue(ac));
}
......@@ -4055,6 +4055,7 @@ bool GdbEngine::handleCliDisassemblerResult(const QByteArray &output, Disassembl
currentFunction = -1;
DisassemblerLines result;
result.setBytesLength(dlines.bytesLength());
for (LineMap::const_iterator it = lineMap.begin(), et = lineMap.end(); it != et; ++it) {
LineData d = *it;
if (d.function != currentFunction) {
......
......@@ -56,6 +56,7 @@ void tst_disassembler::parse()
{
QFETCH(QString, raw);
QFETCH(QString, cooked);
QFETCH(int, bytes);
QFETCH(Debugger::Internal::DisassemblerLine, line);
lines.appendUnparsed(raw);
......@@ -68,7 +69,7 @@ void tst_disassembler::parse()
QCOMPARE(parsed.rawData, line.rawData);
QCOMPARE(parsed.data, line.data);
QString out___ = parsed.toString();
QString out___ = parsed.toString(bytes);
QCOMPARE(out___, cooked);
}
......@@ -76,6 +77,7 @@ void tst_disassembler::parse_data()
{
QTest::addColumn<QString>("raw");
QTest::addColumn<QString>("cooked");
QTest::addColumn<int>("bytes");
QTest::addColumn<Debugger::Internal::DisassemblerLine>("line");
DisassemblerLine line;
......@@ -86,15 +88,17 @@ void tst_disassembler::parse_data()
QTest::newRow("plain")
<< "0x000000000040f39e <+18>:\tmov %rax,%rdi"
<< "0x40f39e <+0x0012> mov %rax,%rdi"
<< line;
<< 0 << line;
line.address = 0x40f3a1;
line.offset = 21;
line.data = "callq 0x420d2c <_ZN7qobject5Names3Bar10TestObjectC2EPN4Myns7QObjectE>";
QTest::newRow("call")
<< "0x000000000040f3a1 <+21>:\tcallq 0x420d2c <_ZN7qobject5Names3Bar10TestObjectC2EPN4Myns7QObjectE>"
<< "0x40f3a1 <+0x0015> callq 0x420d2c <_ZN7qobject5Names3Bar10TestObjectC2EPN4Myns7QObjectE>"
<< line;
<< "0x000000000040f3a1 <+21>:\tcallq "
"0x420d2c <_ZN7qobject5Names3Bar10TestObjectC2EPN4Myns7QObjectE>"
<< "0x40f3a1 <+0x0015> callq "
"0x420d2c <_ZN7qobject5Names3Bar10TestObjectC2EPN4Myns7QObjectE>"
<< 0 << line;
line.address = 0x000000000041cd73;
......@@ -103,7 +107,7 @@ void tst_disassembler::parse_data()
QTest::newRow("set print max-symbolic-offset 1, plain")
<< "0x000000000041cd73:\tmov %rax,%rdi"
<< "0x41cd73 mov %rax,%rdi"
<< line;
<< 0 << line;
line.address = 0x000000000041cd73;
line.offset = 0;
......@@ -111,7 +115,19 @@ void tst_disassembler::parse_data()
QTest::newRow("set print max-symbolic-offset 1, call")
<< "0x00000000041cd73:\tcallq 0x420d2c <_ZN4Myns12QApplicationC1ERiPPci@plt>"
<< "0x41cd73 callq 0x420d2c <_ZN4Myns12QApplicationC1ERiPPci@plt>"
<< line;
<< 0 << line;
// With raw bytes:
line.address = 0x00000000004010d3;
line.offset = 0;
line.function = "main()";
line.offset = 132;
line.bytes = "48 89 c7";
line.data = "mov %rax,%rdi";
QTest::newRow("with raw bytes")
<< " 0x00000000004010d3 <main()+132>:\t48 89 c7\tmov %rax,%rdi"
<< "0x4010d3 <+0x0084> 48 89 c7 mov %rax,%rdi"
<< 10 << line;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment