From a8430f3382a0812d46cc975760ea4b567b7eceb6 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Fri, 2 Oct 2009 11:45:19 +0200
Subject: [PATCH] debugger: fix chain of fallbacks for disassembler view.

Use non-mixed mode if source is not available.
---
 src/plugins/debugger/debuggeragents.cpp    | 32 +++++++--
 src/plugins/debugger/debuggeragents.h      |  2 +
 src/plugins/debugger/debuggermanager.cpp   |  6 +-
 src/plugins/debugger/debuggermanager.h     |  3 +-
 src/plugins/debugger/gdb/gdbengine.cpp     | 80 ++++++++++++----------
 src/plugins/debugger/gdb/gdbengine.h       |  1 +
 src/plugins/debugger/gdb/trkgdbadapter.cpp |  6 +-
 src/plugins/debugger/stackframe.h          |  8 +--
 src/plugins/debugger/stackhandler.cpp      |  4 +-
 9 files changed, 89 insertions(+), 53 deletions(-)

diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp
index fbdf2180020..6da7b7c3684 100644
--- a/src/plugins/debugger/debuggeragents.cpp
+++ b/src/plugins/debugger/debuggeragents.cpp
@@ -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;
diff --git a/src/plugins/debugger/debuggeragents.h b/src/plugins/debugger/debuggeragents.h
index 0fbe380e9fb..ed3daef9a49 100644
--- a/src/plugins/debugger/debuggeragents.h
+++ b/src/plugins/debugger/debuggeragents.h
@@ -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;
 };
 
 
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index f635bcf71e6..efdb4d9b326 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -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);
diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h
index e6dde17f5ed..0cd0ca2aeb0 100644
--- a/src/plugins/debugger/debuggermanager.h
+++ b/src/plugins/debugger/debuggermanager.h
@@ -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);
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 6aa664c6811..1eaae95ea27 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -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();
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index e6775a4d406..58352b4ab34 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -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();
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp
index 0d905033032..aec59eaf1f9 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp
@@ -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;
         }
diff --git a/src/plugins/debugger/stackframe.h b/src/plugins/debugger/stackframe.h
index 8a9f1c2a416..3a0e415e1f2 100644
--- a/src/plugins/debugger/stackframe.h
+++ b/src/plugins/debugger/stackframe.h
@@ -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;
 };
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp
index a28fa04399c..e3b25b24334 100644
--- a/src/plugins/debugger/stackhandler.cpp
+++ b/src/plugins/debugger/stackhandler.cpp
@@ -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
-- 
GitLab