From 2f69bae63f4180fc8b34bcefd55d120eca0431ab Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Mon, 17 May 2010 17:38:31 +0200
Subject: [PATCH] debugger: gather more information on threads when easily
 available

---
 .../debugger/cdb/cdbstacktracecontext.cpp     |  4 +-
 src/plugins/debugger/gdb/classicgdbengine.cpp |  2 +-
 src/plugins/debugger/gdb/gdbengine.cpp        | 47 +++++++++++++++++--
 src/plugins/debugger/gdb/gdbengine.h          |  3 +-
 src/plugins/debugger/gdb/pythongdbengine.cpp  |  2 +-
 src/plugins/debugger/stackhandler.cpp         | 21 +++++----
 src/plugins/debugger/stackhandler.h           | 13 +++--
 7 files changed, 70 insertions(+), 22 deletions(-)

diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
index 94ae7df065c..d7e9b7a3981 100644
--- a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
+++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp
@@ -129,10 +129,10 @@ bool CdbStackTraceContext::getThreads(const CdbCore::ComInterfaces &cif,
         const CdbCore::StackFrame &coreFrame = it.value();
         data.address = coreFrame.address;
         data.function = coreFrame.function;
-        data.line = coreFrame.line;
+        data.lineNumber = coreFrame.line;
         // Basename only for brevity
         const int slashPos = coreFrame.fileName.lastIndexOf(slash);
-        data.file = slashPos == -1 ? coreFrame.fileName : coreFrame.fileName.mid(slashPos + 1);
+        data.fileName = slashPos == -1 ? coreFrame.fileName : coreFrame.fileName.mid(slashPos + 1);
         threads->push_back(data);
     }
     return true;
diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp
index 84066bc534b..3816fc25854 100644
--- a/src/plugins/debugger/gdb/classicgdbengine.cpp
+++ b/src/plugins/debugger/gdb/classicgdbengine.cpp
@@ -581,7 +581,7 @@ void GdbEngine::updateAllClassic()
         QVariant::fromValue<StackCookie>(StackCookie(false, true)));
     manager()->stackHandler()->setCurrentIndex(0);
     if (supportsThreads())
-        postCommand("-thread-list-ids", WatchUpdate, CB(handleStackListThreads), 0);
+        postCommand("-thread-list-ids", WatchUpdate, CB(handleThreadListIds), 0);
     manager()->reloadRegisters();
     updateLocals();
 }
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 78f21a6e0eb..81986228765 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1464,10 +1464,12 @@ void GdbEngine::handleStop1(const GdbMi &data)
 
     if (supportsThreads()) {
         int currentId = data.findChild("thread-id").data().toInt();
-        if (m_gdbAdapter->isTrkAdapter())
+        if (m_gdbAdapter->isTrkAdapter()) {
             m_gdbAdapter->trkReloadThreads();
-        else
-            postCommand("-thread-list-ids", CB(handleStackListThreads), currentId);
+        } else {
+            // This is only available in gdb 7.1+.
+            postCommand("-thread-info", CB(handleThreadInfo), currentId);
+        }
     }
 
     //
@@ -2966,10 +2968,47 @@ void GdbEngine::handleStackSelectFrame(const GdbResponse &response)
     reloadRegisters();
 }
 
-void GdbEngine::handleStackListThreads(const GdbResponse &response)
+void GdbEngine::handleThreadInfo(const GdbResponse &response)
+{
+    int id = response.cookie.toInt();
+    if (response.resultClass == GdbResultDone) {
+        // ^done,threads=[{id="1",target-id="Thread 0xb7fdc710 (LWP 4264)",
+        // frame={level="0",addr="0x080530bf",func="testQString",args=[],
+        // file="/.../app.cpp",fullname="/../app.cpp",line="1175"},
+        // state="stopped",core="0"}],current-thread-id="1"
+        const QList<GdbMi> items = response.data.findChild("threads").children();
+        QList<ThreadData> threads;
+        for (int index = 0, n = items.size(); index != n; ++index) {
+            bool ok = false;
+            const GdbMi item = items.at(index);
+            const GdbMi frame = item.findChild("frame");
+            ThreadData thread;
+            thread.id = item.findChild("id").data().toInt();
+            thread.targetId = item.findChild("target-id").data().toInt();
+            thread.core = QString::fromLatin1(item.findChild("core").data());
+            thread.state = QString::fromLatin1(item.findChild("state").data());
+            thread.address = frame.findChild("addr").data().toULongLong(&ok, 0);
+            thread.function = QString::fromLatin1(frame.findChild("func").data());
+            thread.fileName = QString::fromLatin1(frame.findChild("fullname").data());
+            thread.lineNumber = frame.findChild("line").data().toInt();
+            threads.append(thread);
+        }
+        ThreadsHandler *threadsHandler = manager()->threadsHandler();
+        threadsHandler->setThreads(threads);
+        int currentIndex = response.data.findChild("current-thread-id").data().toInt();
+        threadsHandler->setCurrentThread(currentIndex);
+    } else {
+        // Fall back for older versions: Try to get at least a list
+        // of running threads.
+        postCommand("-thread-list-ids", CB(handleThreadListIds), id);
+    }
+}
+
+void GdbEngine::handleThreadListIds(const GdbResponse &response)
 {
     int id = response.cookie.toInt();
     // "72^done,{thread-ids={thread-id="2",thread-id="1"},number-of-threads="2"}
+    // In gdb 7.1+ additionally: current-thread-id="1"
     const QList<GdbMi> items = response.data.findChild("thread-ids").children();
     QList<ThreadData> threads;
     int currentIndex = -1;
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 372ff4d1318..a1b94ae9ec5 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -429,7 +429,8 @@ private: ////////// View & Data Stuff //////////
     void handleStackListFrames(const GdbResponse &response);
     void handleStackSelectThread(const GdbResponse &response);
     void handleStackSelectFrame(const GdbResponse &response);
-    void handleStackListThreads(const GdbResponse &response);
+    void handleThreadListIds(const GdbResponse &response);
+    void handleThreadInfo(const GdbResponse &response);
     Q_SLOT void reloadStack(bool forceGotoLocation);
     Q_SLOT virtual void reloadFullStack();
     int currentFrame() const;
diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp
index ebe0dff8f83..db59f7f6b94 100644
--- a/src/plugins/debugger/gdb/pythongdbengine.cpp
+++ b/src/plugins/debugger/gdb/pythongdbengine.cpp
@@ -197,7 +197,7 @@ void GdbEngine::updateAllPython()
     if (m_gdbAdapter->isTrkAdapter())
         m_gdbAdapter->trkReloadThreads();
     else
-        postCommand("-thread-list-ids", CB(handleStackListThreads), 0);
+        postCommand("-thread-list-ids", CB(handleThreadListIds), 0);
     manager()->reloadRegisters();
     updateLocals();
 }
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp
index 432cef2878e..95c64c68689 100644
--- a/src/plugins/debugger/stackhandler.cpp
+++ b/src/plugins/debugger/stackhandler.cpp
@@ -268,19 +268,20 @@ bool StackHandler::isDebuggingDebuggingHelpers() const
 //
 ////////////////////////////////////////////////////////////////////////
 
-ThreadData::ThreadData(int threadId) :
-    id(threadId),
-    address(0),
-    line(-1)
+ThreadData::ThreadData(int threadId)
 {
+    notifyRunning();
+    id = threadId;
 }
 
 void ThreadData::notifyRunning()
 {
     address = 0;
     function.clear();
-    file.clear();
-    line = -1;
+    fileName.clear();
+    frameLevel = -1;
+    state.clear();
+    lineNumber = -1;
 }
 
 enum { IdColumn, AddressColumn, FunctionColumn, FileColumn, LineColumn, ColumnCount };
@@ -320,9 +321,9 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const
         case FunctionColumn:
             return thread.function;
         case FileColumn:
-            return thread.file;
+            return thread.fileName;
         case LineColumn:
-            return thread.line >= 0 ? QString::number(thread.line) : QString();
+            return thread.lineNumber >= 0 ? QString::number(thread.lineNumber) : QString();
         case AddressColumn:
             return thread.address > 0 ? QLatin1String("0x") + QString::number(thread.address, 16) : QString();
         }
@@ -330,10 +331,10 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const
         if (thread.address == 0)
             return tr("Thread: %1").arg(thread.id);
         // Stopped
-        if (thread.file.isEmpty())
+        if (thread.fileName.isEmpty())
             return tr("Thread: %1 at %2 (0x%3)").arg(thread.id).arg(thread.function).arg(thread.address, 0, 16);
         return tr("Thread: %1 at %2, %3:%4 (0x%5)").
-                arg(thread.id).arg(thread.function, thread.file).arg(thread.line).arg(thread.address, 0, 16);
+                arg(thread.id).arg(thread.function, thread.fileName).arg(thread.lineNumber).arg(thread.address, 0, 16);
     } else if (role == Qt::DecorationRole && index.column() == 0) {
         // Return icon that indicates whether this is the active stack frame
         return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon;
diff --git a/src/plugins/debugger/stackhandler.h b/src/plugins/debugger/stackhandler.h
index 64c0eff0957..f0aa893ad51 100644
--- a/src/plugins/debugger/stackhandler.h
+++ b/src/plugins/debugger/stackhandler.h
@@ -101,14 +101,21 @@ private:
 struct ThreadData
 {
     ThreadData(int threadId = 0);
-    void notifyRunning(); // Clear state information
 
+    // Permanent data.
     int id;
+    QString targetId;
+    QString core;
+
     // State information when stopped
+    void notifyRunning(); // Clear state information
+
+    int frameLevel;
     quint64 address;
     QString function;
-    QString file;
-    int line;
+    QString fileName;
+    QString state;
+    int lineNumber;
 };
 
 /*! A model to represent the running threads in a QTreeView or ComboBox */
-- 
GitLab