diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index fbee60996d4aa309217805b3c5049da676ee6c48..7b93d25872a98d003a0a721f97acb3e19b7f052e 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -1509,7 +1509,7 @@ void CdbEngine::handleDisassembler(const CdbBuiltinCommandPtr &command) DisassemblerAgent *agent = qvariant_cast<DisassemblerAgent*>(command->cookie); DisassemblerLines disassemblerLines; foreach(const QByteArray &line, command->reply) - disassemblerLines.appendLine(DisassemblerLine(QString::fromLatin1(line))); + disassemblerLines.appendUnparsed(QString::fromLatin1(line)); agent->setContents(disassemblerLines); } diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 49f23ee194f7427f0f00cade4d2632c9a7b6503a..b447a7c062ec3488b942fb83a688ac5de368e4a4 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -48,7 +48,7 @@ #include "breakhandler.h" #include "breakwindow.h" #include "consolewindow.h" -#include "disassembleragent.h" +#include "disassemblerlines.h" #include "logwindow.h" #include "moduleswindow.h" #include "moduleshandler.h" @@ -1621,7 +1621,7 @@ void DebuggerPluginPrivate::requestContextMenu(ITextEditor *editor, .section('\n', lineNumber - 1, lineNumber - 1); BreakpointResponse needle; needle.type = BreakpointByAddress; - needle.address = DisassemblerAgent::addressFromDisassemblyLine(line); + needle.address = DisassemblerLine::addressFromDisassemblyLine(line); args.address = needle.address; needle.lineNumber = -1; id = breakHandler()->findSimilarBreakpoint(needle); @@ -1704,7 +1704,7 @@ void DebuggerPluginPrivate::toggleBreakpoint() if (textEditor->property("DisassemblerView").toBool()) { QString line = textEditor->contents() .section('\n', lineNumber - 1, lineNumber - 1); - quint64 address = DisassemblerAgent::addressFromDisassemblyLine(line); + quint64 address = DisassemblerLine::addressFromDisassemblyLine(line); toggleBreakpointByAddress(address); } else if (lineNumber >= 0) { toggleBreakpointByFileAndLine(textEditor->file()->fileName(), lineNumber); @@ -1751,7 +1751,7 @@ void DebuggerPluginPrivate::requestMark(ITextEditor *editor, int lineNumber) if (editor->property("DisassemblerView").toBool()) { QString line = editor->contents() .section('\n', lineNumber - 1, lineNumber - 1); - quint64 address = DisassemblerAgent::addressFromDisassemblyLine(line); + quint64 address = DisassemblerLine::addressFromDisassemblyLine(line); toggleBreakpointByAddress(address); } else if (editor->file()) { toggleBreakpointByFileAndLine(editor->file()->fileName(), lineNumber); diff --git a/src/plugins/debugger/debuggerstreamops.cpp b/src/plugins/debugger/debuggerstreamops.cpp index 22b9cab355022ede9004b1272954b474ff1177b0..a0bf16bc53c7631eae488a606a213fedccd2cd04 100644 --- a/src/plugins/debugger/debuggerstreamops.cpp +++ b/src/plugins/debugger/debuggerstreamops.cpp @@ -265,6 +265,9 @@ QDataStream &operator>>(QDataStream &stream, WatchData &wd) QDataStream &operator<<(QDataStream& stream, const DisassemblerLine &o) { stream << o.address; + stream << o.function; + stream << o.offset; + stream << o.lineNumber; stream << o.data; return stream; } @@ -272,6 +275,9 @@ QDataStream &operator<<(QDataStream& stream, const DisassemblerLine &o) QDataStream &operator>>(QDataStream& stream, DisassemblerLine &o) { stream >> o.address; + stream >> o.function; + stream >> o.offset; + stream >> o.lineNumber; stream >> o.data; return stream; } diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp index 38ea07e976a5b2811444748f81c371074eddd646..f06340f09765b3550f5319f0bd129e8d195ef727 100644 --- a/src/plugins/debugger/disassembleragent.cpp +++ b/src/plugins/debugger/disassembleragent.cpp @@ -254,13 +254,7 @@ void DisassemblerAgent::setContents(const DisassemblerLines &contents) QString str; for (int i = 0, n = contents.size(); i != n; ++i) { - const DisassemblerLine &dl = contents.at(i); - if (dl.address) { - str += QLatin1String("0x"); - str += QString::number(dl.address, 16); - str += QLatin1String(" "); - } - str += dl.data; + str += contents.at(i).toString(); str += QLatin1Char('\n'); } plainTextEdit->setPlainText(str); @@ -331,12 +325,6 @@ quint64 DisassemblerAgent::address() const return d->location.address(); } -// Return address of an assembly line "0x0dfd bla" -quint64 DisassemblerAgent::addressFromDisassemblyLine(const QString &line) -{ - return DisassemblerLine(line).address; -} - void DisassemblerAgent::setTryMixed(bool on) { d->tryMixed = on; diff --git a/src/plugins/debugger/disassembleragent.h b/src/plugins/debugger/disassembleragent.h index 7c779315b3a75b4c0880336911a19314159e3ca2..3fc122c2627a4412273864a7874330814d53878d 100644 --- a/src/plugins/debugger/disassembleragent.h +++ b/src/plugins/debugger/disassembleragent.h @@ -72,9 +72,6 @@ public: void cleanup(); bool isMixed() const; - // Return address of an assembly line "0x0dfd bla" - static quint64 addressFromDisassemblyLine(const QString &data); - private: DisassemblerAgentPrivate *d; }; diff --git a/src/plugins/debugger/disassemblerlines.cpp b/src/plugins/debugger/disassemblerlines.cpp index db1e2f421c1af9cb4270efab2f380188827bbc7f..c9cba4f896bc801299f4539ab1e26b3555441063 100644 --- a/src/plugins/debugger/disassemblerlines.cpp +++ b/src/plugins/debugger/disassemblerlines.cpp @@ -32,6 +32,7 @@ **************************************************************************/ #include "disassemblerlines.h" +#include "debuggerstringutils.h" #include <QtCore/QDebug> #include <QtCore/QRegExp> @@ -39,7 +40,7 @@ namespace Debugger { namespace Internal { -DisassemblerLine::DisassemblerLine(const QString &unparsed) +void DisassemblerLine::fromString(const QString &unparsed) { int pos = -1; for (int i = 0; i != unparsed.size(); ++i) { @@ -71,6 +72,13 @@ DisassemblerLine::DisassemblerLine(const QString &unparsed) data = unparsed; } +quint64 DisassemblerLine::addressFromDisassemblyLine(const QString &line) +{ + DisassemblerLine l; + l.fromString(line); + return l.address; +} + int DisassemblerLines::lineForAddress(quint64 address) const { return m_rowCache.value(address); @@ -81,17 +89,80 @@ bool DisassemblerLines::coversAddress(quint64 address) const return m_rowCache.value(address) != 0; } -void DisassemblerLines::appendComment(const QString &comment) +void DisassemblerLines::appendLine(const DisassemblerLine &dl) { - DisassemblerLine dl; - dl.data = comment; m_data.append(dl); + m_rowCache[dl.address] = m_data.size(); } -void DisassemblerLines::appendLine(const DisassemblerLine &dl) +void DisassemblerLines::appendUnparsed(const QString &unparsed) { - m_data.append(dl); - m_rowCache[dl.address] = m_data.size(); + QString line = unparsed.trimmed(); + if (line.isEmpty()) + return; + if (line.startsWith("Current language:")) + return; + if (line.startsWith("Dump of assembler")) { + m_lastFunction.clear(); + return; + } + if (line.startsWith("The current source")) + return; + if (line.startsWith("End of assembler")) { + m_lastFunction.clear(); + return; + } + if (line.startsWith("=> ")) + line = line.mid(3); + if (line.startsWith("0x")) { + // Address line. + int pos1 = line.indexOf('<') + 1; + int pos2 = line.indexOf('+', pos1); + int pos3 = line.indexOf('>', pos1); + if (pos1 < pos2 && pos2 < pos3) { + QString function = line.mid(pos1, pos2 - pos1); + if (function != m_lastFunction) { + DisassemblerLine dl; + dl.data = _("Function: ") + function; + m_data.append(dl); + m_lastFunction = function; + } + //line.replace(pos1, pos2 - pos1, ""); + } + DisassemblerLine dl; + dl.address = line.left(pos1 - 1).toULongLong(0, 0); + dl.function = m_lastFunction; + dl.offset = line.mid(pos2, pos3 - pos2).toUInt(); + dl.data = line.mid(pos3 + 3).trimmed(); + m_rowCache[dl.address] = m_data.size() + 1; + m_data.append(dl); + } else { + // Comment line. + DisassemblerLine dl; + dl.data = line; + m_data.append(dl); + } +} + +QString DisassemblerLine::toString() const +{ + const QString someSpace = _(" "); + QString str; + if (isAssembler()) { + if (address) + str += _("0x%1 ").arg(address, 0, 16); + if (offset) + str += _("<+0x%1> ").arg(offset, 4, 10, QLatin1Char('0')); + str += _(" "); + str += data; + } else if (isCode()) { + str += someSpace; + str += data; + } else { + str += someSpace; + str += data; + } + return str; } } // namespace Internal diff --git a/src/plugins/debugger/disassemblerlines.h b/src/plugins/debugger/disassemblerlines.h index 9d49b9b3613a13079f305b2eb19a4f7afd013da5..9d17f4b943c16fb7b48dfedf318c8199d72d9c55 100644 --- a/src/plugins/debugger/disassemblerlines.h +++ b/src/plugins/debugger/disassemblerlines.h @@ -41,15 +41,31 @@ namespace Debugger { namespace Internal { +// A DisassemblerLine represents either +// - an assembler instruction (address, offset, function, data fields), or +// - a code line (lineNumber, data fields), or +// - a comment line. + class DisassemblerLine { + //DisassemblerLine(const QString &unparsed); public: - DisassemblerLine() : address(0) {} - DisassemblerLine(const QString &unparsed); + DisassemblerLine() : address(0), offset(0), lineNumber(0) {} + bool isAssembler() const { return address != 0; } + bool isCode() const { return lineNumber != 0; } + bool isComment() const { return lineNumber == 0 && address == 0; } + QString toString() const; + void fromString(const QString &unparsed); + + // Return address of an assembly line "0x0dfd bla". + static quint64 addressFromDisassemblyLine(const QString &line); public: - quint64 address; - QString data; + quint64 address; // (ass) Address of instruction in memory/in binary. + QString function; // (ass) Function to which current instruction belongs. + uint offset; // (ass) Offset of instruction in relation to current function. + uint lineNumber; // (src) Line number in source. + QString data; // (ass) Instruction text, (src) source text, (cmt) arbitrary. }; class DisassemblerLines @@ -58,13 +74,14 @@ public: DisassemblerLines() {} bool coversAddress(quint64 address) const; + void appendUnparsed(const QString &line); void appendLine(const DisassemblerLine &dl); - void appendComment(const QString &comment); int size() const { return m_data.size(); } const DisassemblerLine &at(int i) const { return m_data.at(i); } int lineForAddress(quint64 address) const; private: + QString m_lastFunction; QVector<DisassemblerLine> m_data; QHash<quint64, int> m_rowCache; }; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index bd68d7d2a22839f43a2019ac158911250ea473d0..3e52db0fbced16439e99b253a17bc03e99cde7ea 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -4119,6 +4119,8 @@ static DisassemblerLine parseLine(const GdbMi &line) QByteArray address = line.findChild("address").data(); dl.address = address.toULongLong(); dl.data = _(line.findChild("inst").data()); + dl.function = _(line.findChild("func-name").data()); + dl.offset = line.findChild("offset").data().toUInt(); return dl; } @@ -4153,8 +4155,12 @@ DisassemblerLines GdbEngine::parseMiDisassembler(const GdbMi &lines) fileLoaded = true; } int line = child.findChild("line").data().toInt(); - if (line >= 1 && line <= fileContents.size()) - result.appendComment(fileContents.at(line - 1)); + if (line >= 1 && line <= fileContents.size()) { + DisassemblerLine dl; + dl.lineNumber = line; + dl.data = fileContents.at(line - 1); + result.appendLine(dl); + } GdbMi insn = child.findChild("line_asm_insn"); foreach (const GdbMi &item, insn.children()) result.appendLine(parseLine(item)); @@ -4172,45 +4178,8 @@ DisassemblerLines GdbEngine::parseCliDisassembler(const GdbMi &output) // First line is something like // "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:" DisassemblerLines dlines; - QByteArray lastFunction; - foreach (const QByteArray &line0, output.data().split('\n')) { - QByteArray line = line0.trimmed(); - if (line.startsWith("=> ")) - line = line.mid(3); - if (line.isEmpty()) - continue; - if (line.startsWith("Current language:")) - continue; - if (line.startsWith("Dump of assembler")) - continue; - if (line.startsWith("The current source")) - continue; - if (line.startsWith("End of assembler")) - continue; - if (line.startsWith("0x")) { - int pos1 = line.indexOf('<') + 1; - int pos2 = line.indexOf('+', pos1); - int pos3 = line.indexOf('>', pos1); - if (pos1 < pos2 && pos2 < pos3) { - QByteArray function = line.mid(pos1, pos2 - pos1); - if (function != lastFunction) { - dlines.appendComment(QString()); - dlines.appendComment(_("Function: ") + _(function)); - lastFunction = function; - } - line.replace(pos1, pos2 - pos1, ""); - } - if (pos3 - pos2 == 1) - line.insert(pos2 + 1, "000"); - if (pos3 - pos2 == 2) - line.insert(pos2 + 1, "00"); - if (pos3 - pos2 == 3) - line.insert(pos2 + 1, "0"); - dlines.appendLine(DisassemblerLine(_(line))); - continue; - } - dlines.appendComment(someSpace + _(line)); - } + foreach (const QByteArray &line, output.data().split('\n')) + dlines.appendUnparsed(_(line)); return dlines; }