debugger: fix chain of fallbacks for disassembler view.

Use non-mixed mode if source is not available.
This commit is contained in:
hjk
2009-10-02 11:45:19 +02:00
parent 3407aab9a5
commit a8430f3382
9 changed files with 89 additions and 53 deletions

View File

@@ -43,6 +43,7 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QtCore/QDebug>
#include <QtGui/QPlainTextEdit> #include <QtGui/QPlainTextEdit>
#include <QtGui/QTextCursor> #include <QtGui/QTextCursor>
#include <QtGui/QSyntaxHighlighter> #include <QtGui/QSyntaxHighlighter>
@@ -182,7 +183,7 @@ private:
*/ */
DisassemblerViewAgent::DisassemblerViewAgent(DebuggerManager *manager) DisassemblerViewAgent::DisassemblerViewAgent(DebuggerManager *manager)
: QObject(manager), d(new DisassemblerViewAgentPrivate) : QObject(0), d(new DisassemblerViewAgentPrivate), m_manager(manager)
{ {
d->editor = 0; d->editor = 0;
d->locationMark = new LocationMark2(); d->locationMark = new LocationMark2();
@@ -212,13 +213,21 @@ void DisassemblerViewAgent::resetLocation()
d->editor->markableInterface()->removeMark(d->locationMark); 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) void DisassemblerViewAgent::setFrame(const StackFrame &frame)
{ {
d->frame = frame; d->frame = frame;
if (!frame.function.isEmpty()) { if (!frame.function.isEmpty() && frame.function != _("??")) {
QHash<QString, QString>::ConstIterator it = QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame));
d->cache.find(frame.function + frame.file);
if (it != d->cache.end()) { 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); setContents(*it);
return; return;
} }
@@ -234,7 +243,7 @@ void DisassemblerViewAgent::setContents(const QString &contents)
using namespace Core; using namespace Core;
using namespace TextEditor; using namespace TextEditor;
d->cache.insert(d->frame.function + d->frame.file, contents); d->cache.insert(frameKey(d->frame), contents);
QPlainTextEdit *plainTextEdit = 0; QPlainTextEdit *plainTextEdit = 0;
EditorManager *editorManager = EditorManager::instance(); EditorManager *editorManager = EditorManager::instance();
if (!d->editor) { 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 QString DisassemblerViewAgent::address() const
{ {
return d->frame.address; return d->frame.address;

View File

@@ -86,10 +86,12 @@ public:
void resetLocation(); void resetLocation();
Q_SLOT void setContents(const QString &contents); Q_SLOT void setContents(const QString &contents);
QString address() const; QString address() const;
bool contentsCoversAddress(const QString &contents) const;
void cleanup(); void cleanup();
private: private:
DisassemblerViewAgentPrivate *d; DisassemblerViewAgentPrivate *d;
DebuggerManager *m_manager;
}; };

View File

@@ -1634,14 +1634,14 @@ void DebuggerManager::setState(DebuggerState state)
showDebuggerOutput(LogDebug, msg); showDebuggerOutput(LogDebug, msg);
resetLocation(); //resetLocation();
if (state == d->m_state) if (state == d->m_state)
return; return;
d->m_state = state; d->m_state = state;
if (d->m_state == InferiorStopped) //if (d->m_state == InferiorStopped)
resetLocation(); // resetLocation();
if (d->m_state == DebuggerNotReady) { if (d->m_state == DebuggerNotReady) {
setBusyCursor(false); setBusyCursor(false);

View File

@@ -228,9 +228,10 @@ public slots:
void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever void showStatusMessage(const QString &msg, int timeout = -1); // -1 forever
private slots: public slots: // FIXME
void showDebuggerOutput(const QString &msg) void showDebuggerOutput(const QString &msg)
{ showDebuggerOutput(LogDebug, msg); } { showDebuggerOutput(LogDebug, msg); }
private slots:
void showDebuggerOutput(int channel, const QString &msg); void showDebuggerOutput(int channel, const QString &msg);
void showDebuggerInput(int channel, const QString &msg); void showDebuggerInput(int channel, const QString &msg);
void showApplicationOutput(const QString &data); void showApplicationOutput(const QString &data);

View File

@@ -967,10 +967,7 @@ void GdbEngine::handleExecRunToFunction(const GdbResponse &response)
setState(InferiorStopped); setState(InferiorStopped);
showStatusMessage(tr("Function reached. Stopped.")); showStatusMessage(tr("Function reached. Stopped."));
GdbMi frame = response.data.findChild("frame"); GdbMi frame = response.data.findChild("frame");
StackFrame f; StackFrame f = parseStackFrame(frame, 0);
f.file = QString::fromLocal8Bit(frame.findChild("fullname").data());
f.line = frame.findChild("line").data().toInt();
f.address = _(frame.findChild("addr").data());
gotoLocation(f, true); gotoLocation(f, true);
} }
@@ -1166,11 +1163,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
// system="0.00136",start="1218810678.805432",end="1218810678.812011"} // system="0.00136",start="1218810678.805432",end="1218810678.812011"}
setState(InferiorStopped); setState(InferiorStopped);
showStatusMessage(tr("Run to Function finished. Stopped.")); showStatusMessage(tr("Run to Function finished. Stopped."));
GdbMi frame = data.findChild("frame"); StackFrame f = parseStackFrame(data.findChild("frame"), 0);
StackFrame f;
f.file = QString::fromLocal8Bit(frame.findChild("fullname").data());
f.line = frame.findChild("line").data().toInt();
f.address = _(frame.findChild("addr").data());
gotoLocation(f, true); gotoLocation(f, true);
#endif #endif
} }
@@ -1288,13 +1281,11 @@ void GdbEngine::handleStop2(const GdbMi &data)
} }
} }
// Quick shot // Quick shot: Jump to stack frame #0.
StackFrame f; if (frame.isValid()) {
f.file = QFile::decodeName(fullName.data()); const StackFrame f = parseStackFrame(frame, 0);
f.line = frame.findChild("line").data().toInt(); gotoLocation(f, true);
f.address = _(frame.findChild("addr").data()); }
f.function = _(frame.findChild("func").data());
gotoLocation(f, true);
// //
// Stack // 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) void GdbEngine::handleStackListFrames(const GdbResponse &response)
{ {
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
@@ -2274,19 +2281,8 @@ void GdbEngine::handleStackListFrames(const GdbResponse &response)
int n = stack.childCount(); int n = stack.childCount();
for (int i = 0; i != n; ++i) { for (int i = 0; i != n; ++i) {
//qDebug() << "HANDLING FRAME:" << stack.childAt(i).toString(); stackFrames.append(parseStackFrame(stack.childAt(i), i));
const GdbMi frameMi = stack.childAt(i); const StackFrame &frame = stackFrames.back();
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);
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
const bool isBogus = const bool isBogus =
@@ -3875,18 +3871,18 @@ void GdbEngine::fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
QTC_ASSERT(agent, return); QTC_ASSERT(agent, return);
bool ok = true; bool ok = true;
quint64 address = agent->address().toULongLong(&ok, 0); quint64 address = agent->address().toULongLong(&ok, 0);
qDebug() << "ADDRESS: " << agent->address() << address; //qDebug() << "ADDRESS: " << agent->address() << address;
QTC_ASSERT(ok, return); QTC_ASSERT(ok, return);
quint64 start = address - 20; QString start = QString::number(address - 20, 16);
quint64 end = address + 100; QString end = QString::number(address + 100, 16);
// -data-disassemble [ -s start-addr -e end-addr ] // -data-disassemble [ -s start-addr -e end-addr ]
// | [ -f filename -l linenum [ -n lines ] ] -- mode // | [ -f filename -l linenum [ -n lines ] ] -- mode
if (useMixedMode) 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), Discardable, CB(handleFetchDisassemblerByAddress1),
QVariant::fromValue(DisassemblerAgentCookie(agent))); QVariant::fromValue(DisassemblerAgentCookie(agent)));
else 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), Discardable, CB(handleFetchDisassemblerByAddress0),
QVariant::fromValue(DisassemblerAgentCookie(agent))); QVariant::fromValue(DisassemblerAgentCookie(agent)));
} }
@@ -3957,8 +3953,13 @@ void GdbEngine::handleFetchDisassemblerByLine(const GdbResponse &response)
if (response.resultClass == GdbResultDone) { if (response.resultClass == GdbResultDone) {
GdbMi lines = response.data.findChild("asm_insns"); GdbMi lines = response.data.findChild("asm_insns");
if (!lines.children().isEmpty())
qDebug() << "LINES: " << lines.childAt(0).findChild("line").data();
if (lines.children().isEmpty()) if (lines.children().isEmpty())
fetchDisassemblerByAddress(ac.agent, true); fetchDisassemblerByAddress(ac.agent, true);
else if (lines.children().size() == 1
&& lines.childAt(0).findChild("line").data() == "0")
fetchDisassemblerByAddress(ac.agent, true);
else else
ac.agent->setContents(parseDisassembler(lines)); ac.agent->setContents(parseDisassembler(lines));
} else if (response.resultClass == GdbResultError) { } else if (response.resultClass == GdbResultError) {
@@ -3980,8 +3981,15 @@ void GdbEngine::handleFetchDisassemblerByAddress1(const GdbResponse &response)
GdbMi lines = response.data.findChild("asm_insns"); GdbMi lines = response.data.findChild("asm_insns");
if (lines.children().isEmpty()) if (lines.children().isEmpty())
fetchDisassemblerByAddress(ac.agent, false); fetchDisassemblerByAddress(ac.agent, false);
else else {
ac.agent->setContents(parseDisassembler(lines)); 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 { } else {
// 26^error,msg="Cannot access memory at address 0x801ca308" // 26^error,msg="Cannot access memory at address 0x801ca308"
QByteArray msg = response.data.findChild("msg").data(); QByteArray msg = response.data.findChild("msg").data();

View File

@@ -156,6 +156,7 @@ private:
bool supportsThreads() const; bool supportsThreads() const;
void gotoLocation(const StackFrame &frame, bool setLocationMarker); void gotoLocation(const StackFrame &frame, bool setLocationMarker);
StackFrame parseStackFrame(const GdbMi &mi, int level);
void connectAdapter(); void connectAdapter();
void disconnectAdapter(); void disconnectAdapter();

View File

@@ -969,8 +969,10 @@ void TrkGdbAdapter::handleTrkResult(const TrkResult &result)
lib.dataseg = dataseg; lib.dataseg = dataseg;
m_session.libraries.append(lib); m_session.libraries.append(lib);
logMessage(logMsg); logMessage(logMsg);
// This lets gdb trigger a register update etc // This lets gdb trigger a register update etc.
sendGdbServerMessage("T05library:;"); // 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"); sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE");
break; break;
} }

View File

@@ -38,16 +38,16 @@ namespace Internal {
struct StackFrame struct StackFrame
{ {
StackFrame(int level = 0); StackFrame();
bool isUsable() const; bool isUsable() const;
QString toToolTip() const; QString toToolTip() const;
QString toString() const; QString toString() const;
int level; int level;
QString function; QString function;
QString file; // we try to put an absolute file name in there QString file; // We try to put an absolute file name in there.
QString from; QString from; // Sometimes something like "/usr/lib/libstdc++.so.6"
QString to; QString to; // Used in ScriptEngine only.
int line; int line;
QString address; QString address;
}; };

View File

@@ -39,8 +39,8 @@
using namespace Debugger::Internal; using namespace Debugger::Internal;
StackFrame::StackFrame(int l) StackFrame::StackFrame()
: level(l), line(0) : level(0), line(0)
{} {}
bool StackFrame::isUsable() const bool StackFrame::isUsable() const