forked from qt-creator/qt-creator
debugger: make debugger view data store more structured
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
#include "threadshandler.h"
|
#include "threadshandler.h"
|
||||||
#include "registerhandler.h"
|
#include "registerhandler.h"
|
||||||
#include "bytearrayinputstream.h"
|
#include "bytearrayinputstream.h"
|
||||||
|
#include "debuggeragents.h"
|
||||||
#include "gdb/gdbmi.h"
|
#include "gdb/gdbmi.h"
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
# include "shared/dbgwinutils.h"
|
# include "shared/dbgwinutils.h"
|
||||||
@@ -99,19 +100,17 @@ QByteArray cdbAddBreakpointCommand(const Debugger::Internal::BreakpointParameter
|
|||||||
|
|
||||||
// Remove the address separator. Format the address exactly as
|
// Remove the address separator. Format the address exactly as
|
||||||
// the agent does (0xhex, as taken from frame) for the location mark to trigger.
|
// the agent does (0xhex, as taken from frame) for the location mark to trigger.
|
||||||
QString formatCdbDisassembler(const QList<QByteArray> &in)
|
Internal::DisassemblerLines formatCdbDisassembler(const QList<QByteArray> &in)
|
||||||
{
|
{
|
||||||
QString disassembly;
|
Internal::DisassemblerLines result;
|
||||||
const QChar newLine = QLatin1Char('\n');
|
|
||||||
foreach(QByteArray line, in) {
|
foreach(QByteArray line, in) {
|
||||||
// Remove 64bit separator.
|
// Remove 64bit separator.
|
||||||
if (line.size() >= 9 && line.at(8) == '`')
|
if (line.size() >= 9 && line.at(8) == '`')
|
||||||
line.remove(8, 1);
|
line.remove(8, 1);
|
||||||
// Ensure address is as wide as agent's address.
|
// Ensure address is as wide as agent's address.
|
||||||
disassembly += QString::fromLatin1(line);
|
result.appendLine(Internal::DisassemblerLine(line));
|
||||||
disassembly += newLine;
|
|
||||||
}
|
}
|
||||||
return disassembly;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
|
// Fix a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ namespace Debugger {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
class BreakpointData;
|
class BreakpointData;
|
||||||
class BreakpointParameters;
|
class BreakpointParameters;
|
||||||
|
class DisassemblerLines;
|
||||||
class StackFrame;
|
class StackFrame;
|
||||||
struct ThreadData;
|
struct ThreadData;
|
||||||
class Register;
|
class Register;
|
||||||
@@ -56,7 +57,7 @@ namespace Cdb {
|
|||||||
QByteArray cdbAddBreakpointCommand(const Debugger::Internal::BreakpointParameters &d, bool oneshot = false, int id = -1);
|
QByteArray cdbAddBreakpointCommand(const Debugger::Internal::BreakpointParameters &d, bool oneshot = false, int id = -1);
|
||||||
|
|
||||||
// Format CDB Dissambler output.
|
// Format CDB Dissambler output.
|
||||||
QString formatCdbDisassembler(const QList<QByteArray> &in);
|
Internal::DisassemblerLines formatCdbDisassembler(const QList<QByteArray> &in);
|
||||||
|
|
||||||
// Convert a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
|
// Convert a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
|
||||||
QByteArray fixCdbIntegerValue(QByteArray t, bool stripLeadingZeros = false, int *basePtr = 0);
|
QByteArray fixCdbIntegerValue(QByteArray t, bool stripLeadingZeros = false, int *basePtr = 0);
|
||||||
|
|||||||
@@ -50,9 +50,11 @@
|
|||||||
|
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QtCore/QMetaObject>
|
#include <QtCore/QMetaObject>
|
||||||
|
#include <QtCore/QTimer>
|
||||||
|
|
||||||
#include <QtGui/QMessageBox>
|
#include <QtGui/QMessageBox>
|
||||||
#include <QtGui/QPlainTextEdit>
|
#include <QtGui/QPlainTextEdit>
|
||||||
|
#include <QtGui/QTextBlock>
|
||||||
#include <QtGui/QTextCursor>
|
#include <QtGui/QTextCursor>
|
||||||
#include <QtGui/QIcon>
|
#include <QtGui/QIcon>
|
||||||
|
|
||||||
@@ -202,23 +204,25 @@ public:
|
|||||||
void documentClosing() {}
|
void documentClosing() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DisassemblerViewAgentPrivate
|
class DisassemblerViewAgentPrivate
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
DisassemblerViewAgentPrivate();
|
DisassemblerViewAgentPrivate();
|
||||||
void configureMimeType();
|
void configureMimeType();
|
||||||
|
|
||||||
|
public:
|
||||||
QPointer<TextEditor::ITextEditor> editor;
|
QPointer<TextEditor::ITextEditor> editor;
|
||||||
StackFrame frame;
|
StackFrame frame;
|
||||||
bool tryMixed;
|
bool tryMixed;
|
||||||
bool setMarker;
|
bool setMarker;
|
||||||
QPointer<DebuggerEngine> engine;
|
QPointer<DebuggerEngine> engine;
|
||||||
LocationMark2 *locationMark;
|
LocationMark2 *locationMark;
|
||||||
QHash<QString, QString> cache;
|
QHash<QString, DisassemblerLines> cache;
|
||||||
QString mimeType;
|
QString mimeType;
|
||||||
};
|
};
|
||||||
|
|
||||||
DisassemblerViewAgentPrivate::DisassemblerViewAgentPrivate() :
|
DisassemblerViewAgentPrivate::DisassemblerViewAgentPrivate()
|
||||||
editor(0),
|
: editor(0),
|
||||||
tryMixed(true),
|
tryMixed(true),
|
||||||
setMarker(true),
|
setMarker(true),
|
||||||
locationMark(new LocationMark2),
|
locationMark(new LocationMark2),
|
||||||
@@ -226,6 +230,7 @@ DisassemblerViewAgentPrivate::DisassemblerViewAgentPrivate() :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class DisassemblerViewAgent
|
\class DisassemblerViewAgent
|
||||||
|
|
||||||
@@ -288,7 +293,8 @@ void DisassemblerViewAgent::setFrame(const StackFrame &frame, bool tryMixed,
|
|||||||
d->setMarker = setMarker;
|
d->setMarker = setMarker;
|
||||||
d->tryMixed = tryMixed;
|
d->tryMixed = tryMixed;
|
||||||
if (isMixed()) {
|
if (isMixed()) {
|
||||||
QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
|
QHash<QString, DisassemblerLines>::ConstIterator it =
|
||||||
|
d->cache.find(frameKey(frame));
|
||||||
if (it != d->cache.end()) {
|
if (it != d->cache.end()) {
|
||||||
QString msg = _("Use cache disassembler for '%1' in '%2'")
|
QString msg = _("Use cache disassembler for '%1' in '%2'")
|
||||||
.arg(frame.function).arg(frame.file);
|
.arg(frame.function).arg(frame.file);
|
||||||
@@ -334,37 +340,12 @@ void DisassemblerViewAgent::setMimeType(const QString &mt)
|
|||||||
d->configureMimeType();
|
d->configureMimeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a pair of <linenumber [1..n], character position> of an address
|
void DisassemblerViewAgent::setContents(const DisassemblerLines &contents)
|
||||||
// in assembly code, assuming lines start with a sane hex address.
|
|
||||||
static QPair<int, int> lineNumberOfAddress(const QString &disassembly, quint64 address)
|
|
||||||
{
|
|
||||||
if (disassembly.isEmpty())
|
|
||||||
return QPair<int, int>(-1, -1);
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
const QChar newLine = QLatin1Char('\n');
|
|
||||||
|
|
||||||
const int size = disassembly.size();
|
|
||||||
for (int lineNumber = 1; pos < size; lineNumber++) {
|
|
||||||
int endOfLinePos = disassembly.indexOf(newLine, pos);
|
|
||||||
if (endOfLinePos == -1)
|
|
||||||
endOfLinePos = size;
|
|
||||||
const QString line = disassembly.mid(pos, endOfLinePos - pos);
|
|
||||||
if (DisassemblerViewAgent::addressFromDisassemblyLine(line) == address)
|
|
||||||
return QPair<int, int>(lineNumber, pos);
|
|
||||||
pos = endOfLinePos + 1;
|
|
||||||
}
|
|
||||||
return QPair<int, int>(-1, -1);;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DisassemblerViewAgent::setContents(const QString &contents)
|
|
||||||
{
|
{
|
||||||
QTC_ASSERT(d, return);
|
QTC_ASSERT(d, return);
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
|
|
||||||
d->cache.insert(frameKey(d->frame), contents);
|
|
||||||
QPlainTextEdit *plainTextEdit = 0;
|
|
||||||
EditorManager *editorManager = EditorManager::instance();
|
EditorManager *editorManager = EditorManager::instance();
|
||||||
if (!d->editor) {
|
if (!d->editor) {
|
||||||
QString titlePattern = "Disassembler";
|
QString titlePattern = "Disassembler";
|
||||||
@@ -380,33 +361,37 @@ void DisassemblerViewAgent::setContents(const QString &contents)
|
|||||||
|
|
||||||
editorManager->activateEditor(d->editor);
|
editorManager->activateEditor(d->editor);
|
||||||
|
|
||||||
plainTextEdit = qobject_cast<QPlainTextEdit *>(d->editor->widget());
|
QPlainTextEdit *plainTextEdit =
|
||||||
if (plainTextEdit) {
|
qobject_cast<QPlainTextEdit *>(d->editor->widget());
|
||||||
plainTextEdit->setPlainText(contents);
|
QTC_ASSERT(plainTextEdit, return);
|
||||||
plainTextEdit->setReadOnly(true);
|
|
||||||
|
QString str;
|
||||||
|
for (int i = 0, n = contents.size(); i != n; ++i) {
|
||||||
|
const DisassemblerLine &dl = contents.at(i);
|
||||||
|
if (dl.address) {
|
||||||
|
str += QString("0x");
|
||||||
|
str += QString::number(dl.address, 16);
|
||||||
|
str += " ";
|
||||||
|
}
|
||||||
|
str += dl.data;
|
||||||
|
str += "\n";
|
||||||
}
|
}
|
||||||
|
plainTextEdit->setPlainText(str);
|
||||||
|
plainTextEdit->setReadOnly(true);
|
||||||
|
|
||||||
if (d->setMarker)
|
if (d->setMarker)
|
||||||
d->editor->markableInterface()->removeMark(d->locationMark);
|
d->editor->markableInterface()->removeMark(d->locationMark);
|
||||||
d->editor->setDisplayName(_("Disassembler (%1)").arg(d->frame.function));
|
d->editor->setDisplayName(_("Disassembler (%1)").arg(d->frame.function));
|
||||||
|
d->cache.insert(frameKey(d->frame), contents);
|
||||||
|
|
||||||
const QPair<int, int> lineNumberPos =
|
int lineNumber = contents.m_rowCache[d->frame.address];
|
||||||
lineNumberOfAddress(contents, d->frame.address);
|
if (lineNumber && d->setMarker)
|
||||||
if (lineNumberPos.first > 0) {
|
d->editor->markableInterface()->addMark(d->locationMark, lineNumber);
|
||||||
if (d->setMarker)
|
|
||||||
d->editor->markableInterface()->addMark(d->locationMark, lineNumberPos.first);
|
|
||||||
if (plainTextEdit) {
|
|
||||||
QTextCursor tc = plainTextEdit->textCursor();
|
|
||||||
tc.setPosition(lineNumberPos.second);
|
|
||||||
plainTextEdit->setTextCursor(tc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DisassemblerViewAgent::contentsCoversAddress(const QString &contents) const
|
QTextCursor tc = plainTextEdit->textCursor();
|
||||||
{
|
QTextBlock block = tc.document()->findBlockByNumber(lineNumber - 1);
|
||||||
QTC_ASSERT(d, return false);
|
tc.setPosition(block.position());
|
||||||
return lineNumberOfAddress(contents, d->frame.address).first > 0;
|
plainTextEdit->setTextCursor(tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 DisassemblerViewAgent::address() const
|
quint64 DisassemblerViewAgent::address() const
|
||||||
@@ -416,20 +401,54 @@ quint64 DisassemblerViewAgent::address() const
|
|||||||
|
|
||||||
// Return address of an assembly line "0x0dfd bla"
|
// Return address of an assembly line "0x0dfd bla"
|
||||||
quint64 DisassemblerViewAgent::addressFromDisassemblyLine(const QString &line)
|
quint64 DisassemblerViewAgent::addressFromDisassemblyLine(const QString &line)
|
||||||
|
{
|
||||||
|
return DisassemblerLine(line).address;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisassemblerLine::DisassemblerLine(const QString &unparsed)
|
||||||
{
|
{
|
||||||
// Mac gdb has an overflow reporting 64bit addresses causing the instruction
|
// Mac gdb has an overflow reporting 64bit addresses causing the instruction
|
||||||
// to follow the last digit "0x000000013fff4810mov 1,1". Truncate here.
|
// to follow the last digit "0x000000013fff4810mov 1,1". Truncate here.
|
||||||
const int pos = qMin(line.indexOf(QLatin1Char(' ')), 19);
|
const int pos = qMin(unparsed.indexOf(QLatin1Char(' ')), 19);
|
||||||
if (pos < 0)
|
if (pos < 0) {
|
||||||
return 0;
|
address = 0;
|
||||||
QString addressS = line.left(pos);
|
data = unparsed;
|
||||||
if (addressS.endsWith(':')) // clang
|
return;
|
||||||
addressS.chop(1);
|
}
|
||||||
if (addressS.startsWith(QLatin1String("0x")))
|
QString addr = unparsed.left(pos);
|
||||||
addressS.remove(0, 2);
|
if (addr.endsWith(':')) // clang
|
||||||
|
addr.chop(1);
|
||||||
|
if (addr.startsWith(QLatin1String("0x")))
|
||||||
|
addr.remove(0, 2);
|
||||||
bool ok;
|
bool ok;
|
||||||
const quint64 address = addressS.toULongLong(&ok, 16);
|
address = addr.toULongLong(&ok, 16);
|
||||||
return ok ? address : quint64(0);
|
if (address)
|
||||||
|
data = unparsed.mid(pos + 1);
|
||||||
|
else
|
||||||
|
data = unparsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DisassemblerLines::lineForAddress(quint64 address) const
|
||||||
|
{
|
||||||
|
return m_rowCache.value(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DisassemblerLines::coversAddress(quint64 address) const
|
||||||
|
{
|
||||||
|
return m_rowCache.value(address) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisassemblerLines::appendComment(const QString &comment)
|
||||||
|
{
|
||||||
|
DisassemblerLine dl;
|
||||||
|
dl.data = comment;
|
||||||
|
m_data.append(dl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisassemblerLines::appendLine(const DisassemblerLine &dl)
|
||||||
|
{
|
||||||
|
m_data.append(dl);
|
||||||
|
m_rowCache[dl.address] = m_data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -31,7 +31,9 @@
|
|||||||
#define DEBUGGER_AGENTS_H
|
#define DEBUGGER_AGENTS_H
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
#include <QtCore/QHash>
|
||||||
#include <QtCore/QPointer>
|
#include <QtCore/QPointer>
|
||||||
|
#include <QtCore/QVector>
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
class IEditor;
|
class IEditor;
|
||||||
@@ -44,6 +46,8 @@ class DebuggerEngine;
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class StackFrame;
|
class StackFrame;
|
||||||
|
class DisassemblerViewAgent;
|
||||||
|
class DisassemblerViewAgentPrivate;
|
||||||
|
|
||||||
class MemoryViewAgent : public QObject
|
class MemoryViewAgent : public QObject
|
||||||
{
|
{
|
||||||
@@ -72,7 +76,32 @@ private:
|
|||||||
QPointer<Debugger::DebuggerEngine> m_engine;
|
QPointer<Debugger::DebuggerEngine> m_engine;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DisassemblerViewAgentPrivate;
|
class DisassemblerLine
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DisassemblerLine() : address(0) {}
|
||||||
|
DisassemblerLine(const QString &unparsed);
|
||||||
|
|
||||||
|
quint64 address;
|
||||||
|
QString data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DisassemblerLines
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DisassemblerLines() {}
|
||||||
|
bool coversAddress(quint64 address) const;
|
||||||
|
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:
|
||||||
|
friend class DisassemblerViewAgent;
|
||||||
|
QVector<DisassemblerLine> m_data;
|
||||||
|
QHash<quint64, int> m_rowCache;
|
||||||
|
};
|
||||||
|
|
||||||
class DisassemblerViewAgent : public QObject
|
class DisassemblerViewAgent : public QObject
|
||||||
{
|
{
|
||||||
@@ -86,7 +115,7 @@ public:
|
|||||||
void setFrame(const StackFrame &frame, bool tryMixed, bool setMarker);
|
void setFrame(const StackFrame &frame, bool tryMixed, bool setMarker);
|
||||||
const StackFrame &frame() const;
|
const StackFrame &frame() const;
|
||||||
void resetLocation();
|
void resetLocation();
|
||||||
Q_SLOT void setContents(const QString &contents);
|
void setContents(const DisassemblerLines &contents);
|
||||||
|
|
||||||
// Mimetype: "text/a-asm" or some specialized architecture
|
// Mimetype: "text/a-asm" or some specialized architecture
|
||||||
QString mimeType() const;
|
QString mimeType() const;
|
||||||
@@ -98,8 +127,7 @@ public:
|
|||||||
bool isMixed() const;
|
bool isMixed() const;
|
||||||
|
|
||||||
// Return address of an assembly line "0x0dfd bla"
|
// Return address of an assembly line "0x0dfd bla"
|
||||||
static quint64 addressFromDisassemblyLine(const QString &line);
|
static quint64 addressFromDisassemblyLine(const QString &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DisassemblerViewAgentPrivate *d;
|
DisassemblerViewAgentPrivate *d;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -874,6 +874,23 @@ void GdbEngine::handleResultRecord(GdbResponse *response)
|
|||||||
//shutdown();
|
//shutdown();
|
||||||
//showMessageBox(QMessageBox::Critical,
|
//showMessageBox(QMessageBox::Critical,
|
||||||
// tr("Executable failed"), QString::fromLocal8Bit(msg));
|
// tr("Executable failed"), QString::fromLocal8Bit(msg));
|
||||||
|
} else if (msg.contains("Cannot insert breakpoint")) {
|
||||||
|
// For breakpoints set by address to non-existent addresses we
|
||||||
|
// might get something like "6^error,msg="Warning:\nCannot insert
|
||||||
|
// breakpoint 3.\nError accessing memory address 0x34592327:
|
||||||
|
// Input/output error.\nCannot insert breakpoint 4.\nError
|
||||||
|
// accessing memory address 0x34592335: Input/output error.\n".
|
||||||
|
// This should not stop us from proceeding.
|
||||||
|
// Most notably, that happens after a "6^running" and "*running"
|
||||||
|
// We are probably sitting at _start and can't proceed as
|
||||||
|
// long as the breakpoints are enabled.
|
||||||
|
// FIXME: Should we silently disable the offending breakpoints?
|
||||||
|
showMessage(_("APPLYING WORKAROUND #5"));
|
||||||
|
showMessageBox(QMessageBox::Critical,
|
||||||
|
tr("Setting breakpoints failed"), QString::fromLocal8Bit(msg));
|
||||||
|
QTC_ASSERT(state() == InferiorRunOk, /**/);
|
||||||
|
notifyInferiorSpontaneousStop();
|
||||||
|
notifyEngineIll();
|
||||||
} else {
|
} else {
|
||||||
showMessageBox(QMessageBox::Critical,
|
showMessageBox(QMessageBox::Critical,
|
||||||
tr("Executable failed"), QString::fromLocal8Bit(msg));
|
tr("Executable failed"), QString::fromLocal8Bit(msg));
|
||||||
@@ -3876,24 +3893,20 @@ void GdbEngine::fetchDisassemblerByAddressCli(const DisassemblerAgentCookie &ac0
|
|||||||
QVariant::fromValue(ac));
|
QVariant::fromValue(ac));
|
||||||
}
|
}
|
||||||
|
|
||||||
static QByteArray parseLine(const GdbMi &line)
|
static DisassemblerLine parseLine(const GdbMi &line)
|
||||||
{
|
{
|
||||||
QByteArray ba;
|
DisassemblerLine dl;
|
||||||
ba.reserve(200);
|
|
||||||
QByteArray address = line.findChild("address").data();
|
QByteArray address = line.findChild("address").data();
|
||||||
//QByteArray funcName = line.findChild("func-name").data();
|
//QByteArray funcName = line.findChild("func-name").data();
|
||||||
//QByteArray offset = line.findChild("offset").data();
|
//QByteArray offset = line.findChild("offset").data();
|
||||||
QByteArray inst = line.findChild("inst").data();
|
dl.address = address.toULongLong();
|
||||||
ba += address;
|
|
||||||
ba += QByteArray(15 - address.size(), ' ');
|
|
||||||
//ba += funcName + "+" + offset + " ";
|
//ba += funcName + "+" + offset + " ";
|
||||||
//ba += QByteArray(30 - funcName.size() - offset.size(), ' ');
|
//ba += QByteArray(30 - funcName.size() - offset.size(), ' ');
|
||||||
ba += inst;
|
dl.data = _(line.findChild("inst").data());
|
||||||
ba += '\n';
|
return dl;
|
||||||
return ba;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GdbEngine::parseDisassembler(const GdbMi &lines)
|
DisassemblerLines GdbEngine::parseDisassembler(const GdbMi &lines)
|
||||||
{
|
{
|
||||||
// ^done,data={asm_insns=[src_and_asm_line={line="1243",file=".../app.cpp",
|
// ^done,data={asm_insns=[src_and_asm_line={line="1243",file=".../app.cpp",
|
||||||
// line_asm_insn=[{address="0x08054857",func-name="main",offset="27",
|
// line_asm_insn=[{address="0x08054857",func-name="main",offset="27",
|
||||||
@@ -3906,10 +3919,9 @@ QString GdbEngine::parseDisassembler(const GdbMi &lines)
|
|||||||
// {address="0x0805acf8",func-name="...",offset="25",inst="and $0xe8,%al"},
|
// {address="0x0805acf8",func-name="...",offset="25",inst="and $0xe8,%al"},
|
||||||
// {address="0x0805acfa",func-name="...",offset="27",inst="pop %esp"},
|
// {address="0x0805acfa",func-name="...",offset="27",inst="pop %esp"},
|
||||||
|
|
||||||
QList<QByteArray> fileContents;
|
QStringList fileContents;
|
||||||
bool fileLoaded = false;
|
bool fileLoaded = false;
|
||||||
QByteArray ba;
|
DisassemblerLines result;
|
||||||
ba.reserve(200 * lines.children().size());
|
|
||||||
|
|
||||||
// FIXME: Performance?
|
// FIXME: Performance?
|
||||||
foreach (const GdbMi &child, lines.children()) {
|
foreach (const GdbMi &child, lines.children()) {
|
||||||
@@ -3920,21 +3932,22 @@ QString GdbEngine::parseDisassembler(const GdbMi &lines)
|
|||||||
fileName = cleanupFullName(fileName);
|
fileName = cleanupFullName(fileName);
|
||||||
QFile file(fileName);
|
QFile file(fileName);
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
fileContents = file.readAll().split('\n');
|
QTextStream ts(&file);
|
||||||
|
fileContents = ts.readAll().split(QLatin1Char('\n'));
|
||||||
fileLoaded = true;
|
fileLoaded = true;
|
||||||
}
|
}
|
||||||
int line = child.findChild("line").data().toInt();
|
int line = child.findChild("line").data().toInt();
|
||||||
if (line >= 1 && line <= fileContents.size())
|
if (line >= 1 && line <= fileContents.size())
|
||||||
ba += " " + fileContents.at(line - 1) + '\n';
|
result.appendComment(fileContents.at(line - 1));
|
||||||
GdbMi insn = child.findChild("line_asm_insn");
|
GdbMi insn = child.findChild("line_asm_insn");
|
||||||
foreach (const GdbMi &line, insn.children())
|
foreach (const GdbMi &item, insn.children())
|
||||||
ba += parseLine(line);
|
result.appendLine(parseLine(item));
|
||||||
} else {
|
} else {
|
||||||
// The non-mixed version.
|
// The non-mixed version.
|
||||||
ba += parseLine(child);
|
result.appendLine(parseLine(child));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _(ba);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleFetchDisassemblerByLine(const GdbResponse &response)
|
void GdbEngine::handleFetchDisassemblerByLine(const GdbResponse &response)
|
||||||
@@ -3950,10 +3963,10 @@ void GdbEngine::handleFetchDisassemblerByLine(const GdbResponse &response)
|
|||||||
&& lines.childAt(0).findChild("line").data() == "0")
|
&& lines.childAt(0).findChild("line").data() == "0")
|
||||||
fetchDisassemblerByAddress(ac, true);
|
fetchDisassemblerByAddress(ac, true);
|
||||||
else {
|
else {
|
||||||
QString contents = parseDisassembler(lines);
|
DisassemblerLines dlines = parseDisassembler(lines);
|
||||||
if (ac.agent->contentsCoversAddress(contents)) {
|
if (dlines.coversAddress(ac.agent->address())) {
|
||||||
// All is well.
|
// All is well.
|
||||||
ac.agent->setContents(contents);
|
ac.agent->setContents(dlines);
|
||||||
} else {
|
} else {
|
||||||
// Can happen e.g. for initializer list on symbian/rvct where
|
// Can happen e.g. for initializer list on symbian/rvct where
|
||||||
// we get a file name and line number but where the 'fully
|
// we get a file name and line number but where the 'fully
|
||||||
@@ -3985,9 +3998,9 @@ void GdbEngine::handleFetchDisassemblerByAddress1(const GdbResponse &response)
|
|||||||
if (lines.children().isEmpty())
|
if (lines.children().isEmpty())
|
||||||
fetchDisassemblerByAddress(ac, false);
|
fetchDisassemblerByAddress(ac, false);
|
||||||
else {
|
else {
|
||||||
QString contents = parseDisassembler(lines);
|
DisassemblerLines dlines = parseDisassembler(lines);
|
||||||
if (ac.agent->contentsCoversAddress(contents)) {
|
if (dlines.coversAddress(ac.agent->address())) {
|
||||||
ac.agent->setContents(parseDisassembler(lines));
|
ac.agent->setContents(dlines);
|
||||||
} else {
|
} else {
|
||||||
showMessage(_("FALL BACK TO NON-MIXED"));
|
showMessage(_("FALL BACK TO NON-MIXED"));
|
||||||
fetchDisassemblerByAddress(ac, false);
|
fetchDisassemblerByAddress(ac, false);
|
||||||
@@ -4030,11 +4043,11 @@ void GdbEngine::handleFetchDisassemblerByCli(const GdbResponse &response)
|
|||||||
if (lines.isValid()) {
|
if (lines.isValid()) {
|
||||||
ac.agent->setContents(parseDisassembler(lines));
|
ac.agent->setContents(parseDisassembler(lines));
|
||||||
} else {
|
} else {
|
||||||
const QByteArray someSpace = " ";
|
const QString someSpace = _(" ");
|
||||||
// First line is something like
|
// First line is something like
|
||||||
// "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
|
// "Dump of assembler code from 0xb7ff598f to 0xb7ff5a07:"
|
||||||
GdbMi output = response.data.findChild("consolestreamoutput");
|
GdbMi output = response.data.findChild("consolestreamoutput");
|
||||||
QByteArray res;
|
DisassemblerLines dlines;
|
||||||
QByteArray lastFunction;
|
QByteArray lastFunction;
|
||||||
foreach (const QByteArray &line0, output.data().split('\n')) {
|
foreach (const QByteArray &line0, output.data().split('\n')) {
|
||||||
QByteArray line = line0.trimmed();
|
QByteArray line = line0.trimmed();
|
||||||
@@ -4057,23 +4070,19 @@ void GdbEngine::handleFetchDisassemblerByCli(const GdbResponse &response)
|
|||||||
if (pos1 < pos2 && pos2 < pos3) {
|
if (pos1 < pos2 && pos2 < pos3) {
|
||||||
QByteArray function = line.mid(pos1, pos2 - pos1);
|
QByteArray function = line.mid(pos1, pos2 - pos1);
|
||||||
if (function != lastFunction) {
|
if (function != lastFunction) {
|
||||||
res.append("\nFunction: ");
|
dlines.appendComment(QString());
|
||||||
res.append(function);
|
dlines.appendComment(_("Function: ") + _(function));
|
||||||
res.append('\n');
|
|
||||||
lastFunction = function;
|
lastFunction = function;
|
||||||
}
|
}
|
||||||
line.replace(pos1, pos2 - pos1, "");
|
line.replace(pos1, pos2 - pos1, "");
|
||||||
}
|
}
|
||||||
res.append(line);
|
dlines.appendLine(DisassemblerLine(_(line)));
|
||||||
res.append('\n');
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
res.append(someSpace);
|
dlines.appendComment(someSpace + _(line));
|
||||||
res.append(line);
|
|
||||||
res.append('\n');
|
|
||||||
}
|
}
|
||||||
if (res.size() > 1)
|
if (dlines.size())
|
||||||
ac.agent->setContents(_(res));
|
ac.agent->setContents(dlines);
|
||||||
else
|
else
|
||||||
fetchDisassemblerByAddressCli(ac);
|
fetchDisassemblerByAddressCli(ac);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ class GdbMi;
|
|||||||
|
|
||||||
class WatchData;
|
class WatchData;
|
||||||
class DisassemblerAgentCookie;
|
class DisassemblerAgentCookie;
|
||||||
|
class DisassemblerLines;
|
||||||
|
|
||||||
class AttachGdbAdapter;
|
class AttachGdbAdapter;
|
||||||
class CoreGdbAdapter;
|
class CoreGdbAdapter;
|
||||||
@@ -404,7 +405,7 @@ private: ////////// View & Data Stuff //////////
|
|||||||
void handleFetchDisassemblerByLine(const GdbResponse &response);
|
void handleFetchDisassemblerByLine(const GdbResponse &response);
|
||||||
void handleFetchDisassemblerByAddress1(const GdbResponse &response);
|
void handleFetchDisassemblerByAddress1(const GdbResponse &response);
|
||||||
void handleFetchDisassemblerByAddress0(const GdbResponse &response);
|
void handleFetchDisassemblerByAddress0(const GdbResponse &response);
|
||||||
QString parseDisassembler(const GdbMi &lines);
|
DisassemblerLines parseDisassembler(const GdbMi &lines);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Source file specific stuff
|
// Source file specific stuff
|
||||||
|
|||||||
@@ -446,9 +446,9 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload)
|
|||||||
QString da;
|
QString da;
|
||||||
s >> pc;
|
s >> pc;
|
||||||
s >> da;
|
s >> da;
|
||||||
DisassemblerViewAgent *view = m_frameToDisassemblerAgent.take(pc);
|
//DisassemblerViewAgent *view = m_frameToDisassemblerAgent.take(pc);
|
||||||
if (view)
|
//if (view)
|
||||||
view->setContents(da);
|
// view->setContents(da);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IPCEngineGuest::UpdateWatchData:
|
case IPCEngineGuest::UpdateWatchData:
|
||||||
|
|||||||
Reference in New Issue
Block a user