forked from qt-creator/qt-creator
debugger: fix chain of fallbacks for disassembler view.
Use non-mixed mode if source is not available.
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtGui/QPlainTextEdit>
|
||||
#include <QtGui/QTextCursor>
|
||||
#include <QtGui/QSyntaxHighlighter>
|
||||
@@ -182,7 +183,7 @@ private:
|
||||
*/
|
||||
|
||||
DisassemblerViewAgent::DisassemblerViewAgent(DebuggerManager *manager)
|
||||
: QObject(manager), d(new DisassemblerViewAgentPrivate)
|
||||
: QObject(0), d(new DisassemblerViewAgentPrivate), m_manager(manager)
|
||||
{
|
||||
d->editor = 0;
|
||||
d->locationMark = new LocationMark2();
|
||||
@@ -212,13 +213,21 @@ void DisassemblerViewAgent::resetLocation()
|
||||
d->editor->markableInterface()->removeMark(d->locationMark);
|
||||
}
|
||||
|
||||
QString frameKey(const StackFrame &frame)
|
||||
{
|
||||
return _("%1:%2:%3").arg(frame.function).arg(frame.file).arg(frame.from);
|
||||
}
|
||||
|
||||
void DisassemblerViewAgent::setFrame(const StackFrame &frame)
|
||||
{
|
||||
d->frame = frame;
|
||||
if (!frame.function.isEmpty()) {
|
||||
QHash<QString, QString>::ConstIterator it =
|
||||
d->cache.find(frame.function + frame.file);
|
||||
if (!frame.function.isEmpty() && frame.function != _("??")) {
|
||||
QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
|
||||
if (it != d->cache.end()) {
|
||||
QString msg = QString::fromLatin1("Use cache dissassembler for %1 in %2")
|
||||
.arg(frame.function).arg(frame.file);
|
||||
qDebug() << msg;
|
||||
m_manager->showDebuggerOutput(msg);
|
||||
setContents(*it);
|
||||
return;
|
||||
}
|
||||
@@ -234,7 +243,7 @@ void DisassemblerViewAgent::setContents(const QString &contents)
|
||||
using namespace Core;
|
||||
using namespace TextEditor;
|
||||
|
||||
d->cache.insert(d->frame.function + d->frame.file, contents);
|
||||
d->cache.insert(frameKey(d->frame), contents);
|
||||
QPlainTextEdit *plainTextEdit = 0;
|
||||
EditorManager *editorManager = EditorManager::instance();
|
||||
if (!d->editor) {
|
||||
@@ -273,6 +282,19 @@ void DisassemblerViewAgent::setContents(const QString &contents)
|
||||
}
|
||||
}
|
||||
|
||||
bool DisassemblerViewAgent::contentsCoversAddress(const QString &contents) const
|
||||
{
|
||||
QTC_ASSERT(d, return false);
|
||||
for (int pos = 0, line = 0; ; ++line, ++pos) {
|
||||
if (contents.midRef(pos, d->frame.address.size()) == d->frame.address)
|
||||
return true;
|
||||
pos = contents.indexOf('\n', pos + 1);
|
||||
if (pos == -1)
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QString DisassemblerViewAgent::address() const
|
||||
{
|
||||
return d->frame.address;
|
||||
|
||||
@@ -86,10 +86,12 @@ public:
|
||||
void resetLocation();
|
||||
Q_SLOT void setContents(const QString &contents);
|
||||
QString address() const;
|
||||
bool contentsCoversAddress(const QString &contents) const;
|
||||
void cleanup();
|
||||
|
||||
private:
|
||||
DisassemblerViewAgentPrivate *d;
|
||||
DebuggerManager *m_manager;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1634,14 +1634,14 @@ void DebuggerManager::setState(DebuggerState state)
|
||||
|
||||
showDebuggerOutput(LogDebug, msg);
|
||||
|
||||
resetLocation();
|
||||
//resetLocation();
|
||||
if (state == d->m_state)
|
||||
return;
|
||||
|
||||
d->m_state = state;
|
||||
|
||||
if (d->m_state == InferiorStopped)
|
||||
resetLocation();
|
||||
//if (d->m_state == InferiorStopped)
|
||||
// resetLocation();
|
||||
|
||||
if (d->m_state == DebuggerNotReady) {
|
||||
setBusyCursor(false);
|
||||
|
||||
@@ -228,9 +228,10 @@ public slots:
|
||||
|
||||
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
|
||||
|
||||
private slots:
|
||||
public slots: // FIXME
|
||||
void showDebuggerOutput(const QString &msg)
|
||||
{ showDebuggerOutput(LogDebug, msg); }
|
||||
private slots:
|
||||
void showDebuggerOutput(int channel, const QString &msg);
|
||||
void showDebuggerInput(int channel, const QString &msg);
|
||||
void showApplicationOutput(const QString &data);
|
||||
|
||||
@@ -967,10 +967,7 @@ void GdbEngine::handleExecRunToFunction(const GdbResponse &response)
|
||||
setState(InferiorStopped);
|
||||
showStatusMessage(tr("Function reached. Stopped."));
|
||||
GdbMi frame = response.data.findChild("frame");
|
||||
StackFrame f;
|
||||
f.file = QString::fromLocal8Bit(frame.findChild("fullname").data());
|
||||
f.line = frame.findChild("line").data().toInt();
|
||||
f.address = _(frame.findChild("addr").data());
|
||||
StackFrame f = parseStackFrame(frame, 0);
|
||||
gotoLocation(f, true);
|
||||
}
|
||||
|
||||
@@ -1166,11 +1163,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
||||
// system="0.00136",start="1218810678.805432",end="1218810678.812011"}
|
||||
setState(InferiorStopped);
|
||||
showStatusMessage(tr("Run to Function finished. Stopped."));
|
||||
GdbMi frame = data.findChild("frame");
|
||||
StackFrame f;
|
||||
f.file = QString::fromLocal8Bit(frame.findChild("fullname").data());
|
||||
f.line = frame.findChild("line").data().toInt();
|
||||
f.address = _(frame.findChild("addr").data());
|
||||
StackFrame f = parseStackFrame(data.findChild("frame"), 0);
|
||||
gotoLocation(f, true);
|
||||
#endif
|
||||
}
|
||||
@@ -1288,13 +1281,11 @@ void GdbEngine::handleStop2(const GdbMi &data)
|
||||
}
|
||||
}
|
||||
|
||||
// Quick shot
|
||||
StackFrame f;
|
||||
f.file = QFile::decodeName(fullName.data());
|
||||
f.line = frame.findChild("line").data().toInt();
|
||||
f.address = _(frame.findChild("addr").data());
|
||||
f.function = _(frame.findChild("func").data());
|
||||
gotoLocation(f, true);
|
||||
// Quick shot: Jump to stack frame #0.
|
||||
if (frame.isValid()) {
|
||||
const StackFrame f = parseStackFrame(frame, 0);
|
||||
gotoLocation(f, true);
|
||||
}
|
||||
|
||||
//
|
||||
// Stack
|
||||
@@ -2253,6 +2244,22 @@ void GdbEngine::handleStackSelectThread(const GdbResponse &)
|
||||
}
|
||||
|
||||
|
||||
StackFrame GdbEngine::parseStackFrame(const GdbMi &frameMi, int level)
|
||||
{
|
||||
//qDebug() << "HANDLING FRAME:" << frameMi.toString();
|
||||
QStringList files;
|
||||
files.append(QFile::decodeName(frameMi.findChild("fullname").data()));
|
||||
files.append(QFile::decodeName(frameMi.findChild("file").data()));
|
||||
StackFrame frame;
|
||||
frame.level = level;
|
||||
frame.file = fullName(files);
|
||||
frame.function = _(frameMi.findChild("func").data());
|
||||
frame.from = _(frameMi.findChild("from").data());
|
||||
frame.line = frameMi.findChild("line").data().toInt();
|
||||
frame.address = _(frameMi.findChild("addr").data());
|
||||
return frame;
|
||||
}
|
||||
|
||||
void GdbEngine::handleStackListFrames(const GdbResponse &response)
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
@@ -2274,19 +2281,8 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response)
|
||||
|
||||
int n = stack.childCount();
|
||||
for (int i = 0; i != n; ++i) {
|
||||
//qDebug() << "HANDLING FRAME:" << stack.childAt(i).toString();
|
||||
const GdbMi frameMi = stack.childAt(i);
|
||||
StackFrame frame(i);
|
||||
QStringList files;
|
||||
files.append(QFile::decodeName(frameMi.findChild("fullname").data()));
|
||||
files.append(QFile::decodeName(frameMi.findChild("file").data()));
|
||||
frame.file = fullName(files);
|
||||
frame.function = _(frameMi.findChild("func").data());
|
||||
frame.from = _(frameMi.findChild("from").data());
|
||||
frame.line = frameMi.findChild("line").data().toInt();
|
||||
frame.address = _(frameMi.findChild("addr").data());
|
||||
|
||||
stackFrames.append(frame);
|
||||
stackFrames.append(parseStackFrame(stack.childAt(i), i));
|
||||
const StackFrame &frame = stackFrames.back();
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
const bool isBogus =
|
||||
@@ -3875,18 +3871,18 @@ void GdbEngine::fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
|
||||
QTC_ASSERT(agent, return);
|
||||
bool ok = true;
|
||||
quint64 address = agent->address().toULongLong(&ok, 0);
|
||||
qDebug() << "ADDRESS: " << agent->address() << address;
|
||||
//qDebug() << "ADDRESS: " << agent->address() << address;
|
||||
QTC_ASSERT(ok, return);
|
||||
quint64 start = address - 20;
|
||||
quint64 end = address + 100;
|
||||
QString start = QString::number(address - 20, 16);
|
||||
QString end = QString::number(address + 100, 16);
|
||||
// -data-disassemble [ -s start-addr -e end-addr ]
|
||||
// | [ -f filename -l linenum [ -n lines ] ] -- mode
|
||||
if (useMixedMode)
|
||||
postCommand(_("-data-disassemble -s %1 -e %2 -- 1").arg(start).arg(end),
|
||||
postCommand(_("-data-disassemble -s 0x%1 -e 0x%2 -- 1").arg(start).arg(end),
|
||||
Discardable, CB(handleFetchDisassemblerByAddress1),
|
||||
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
||||
else
|
||||
postCommand(_("-data-disassemble -s %1 -e %2 -- 0").arg(start).arg(end),
|
||||
postCommand(_("-data-disassemble -s 0x%1 -e 0x%2 -- 0").arg(start).arg(end),
|
||||
Discardable, CB(handleFetchDisassemblerByAddress0),
|
||||
QVariant::fromValue(DisassemblerAgentCookie(agent)));
|
||||
}
|
||||
@@ -3957,8 +3953,13 @@ void GdbEngine::handleFetchDisassemblerByLine(const GdbResponse &response)
|
||||
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
GdbMi lines = response.data.findChild("asm_insns");
|
||||
if (!lines.children().isEmpty())
|
||||
qDebug() << "LINES: " << lines.childAt(0).findChild("line").data();
|
||||
if (lines.children().isEmpty())
|
||||
fetchDisassemblerByAddress(ac.agent, true);
|
||||
else if (lines.children().size() == 1
|
||||
&& lines.childAt(0).findChild("line").data() == "0")
|
||||
fetchDisassemblerByAddress(ac.agent, true);
|
||||
else
|
||||
ac.agent->setContents(parseDisassembler(lines));
|
||||
} else if (response.resultClass == GdbResultError) {
|
||||
@@ -3980,8 +3981,15 @@ void GdbEngine::handleFetchDisassemblerByAddress1(const GdbResponse &response)
|
||||
GdbMi lines = response.data.findChild("asm_insns");
|
||||
if (lines.children().isEmpty())
|
||||
fetchDisassemblerByAddress(ac.agent, false);
|
||||
else
|
||||
ac.agent->setContents(parseDisassembler(lines));
|
||||
else {
|
||||
QString contents = parseDisassembler(lines);
|
||||
if (ac.agent->contentsCoversAddress(contents)) {
|
||||
ac.agent->setContents(parseDisassembler(lines));
|
||||
} else {
|
||||
qDebug() << "FALL BACK TO NON-MIXED";
|
||||
fetchDisassemblerByAddress(ac.agent, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 26^error,msg="Cannot access memory at address 0x801ca308"
|
||||
QByteArray msg = response.data.findChild("msg").data();
|
||||
|
||||
@@ -156,6 +156,7 @@ private:
|
||||
|
||||
bool supportsThreads() const;
|
||||
void gotoLocation(const StackFrame &frame, bool setLocationMarker);
|
||||
StackFrame parseStackFrame(const GdbMi &mi, int level);
|
||||
|
||||
void connectAdapter();
|
||||
void disconnectAdapter();
|
||||
|
||||
@@ -969,8 +969,10 @@ void TrkGdbAdapter::handleTrkResult(const TrkResult &result)
|
||||
lib.dataseg = dataseg;
|
||||
m_session.libraries.append(lib);
|
||||
logMessage(logMsg);
|
||||
// This lets gdb trigger a register update etc
|
||||
sendGdbServerMessage("T05library:;");
|
||||
// This lets gdb trigger a register update etc.
|
||||
// With CS gdb 6.4 we get a non-standard $qfDllInfo#7f+ request
|
||||
// afterwards, so don't use it for now.
|
||||
//sendGdbServerMessage("T05library:;");
|
||||
sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -38,16 +38,16 @@ namespace Internal {
|
||||
|
||||
struct StackFrame
|
||||
{
|
||||
StackFrame(int level = 0);
|
||||
StackFrame();
|
||||
bool isUsable() const;
|
||||
QString toToolTip() const;
|
||||
QString toString() const;
|
||||
|
||||
int level;
|
||||
QString function;
|
||||
QString file; // we try to put an absolute file name in there
|
||||
QString from;
|
||||
QString to;
|
||||
QString file; // We try to put an absolute file name in there.
|
||||
QString from; // Sometimes something like "/usr/lib/libstdc++.so.6"
|
||||
QString to; // Used in ScriptEngine only.
|
||||
int line;
|
||||
QString address;
|
||||
};
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
|
||||
using namespace Debugger::Internal;
|
||||
|
||||
StackFrame::StackFrame(int l)
|
||||
: level(l), line(0)
|
||||
StackFrame::StackFrame()
|
||||
: level(0), line(0)
|
||||
{}
|
||||
|
||||
bool StackFrame::isUsable() const
|
||||
|
||||
Reference in New Issue
Block a user