From 98736d256bfb9d9946d192af03ff022a79817aca Mon Sep 17 00:00:00 2001
From: Arvid Ephraim Picciani <arvid.picciani@nokia.com>
Date: Mon, 13 Sep 2010 12:37:30 +0200
Subject: [PATCH] Display thread names

extract thread names from QThread object name

Task-Number: QTCREATORBUG-382
Reviewed-by: hjk
---
 share/qtcreator/gdbmacros/dumper.py     | 46 +++++++++++++++++++++++--
 src/plugins/debugger/debuggerplugin.cpp |  1 +
 src/plugins/debugger/gdb/gdbengine.cpp  | 26 ++++++++++++++
 src/plugins/debugger/gdb/gdbengine.h    |  1 +
 src/plugins/debugger/threadshandler.cpp |  6 ++++
 src/plugins/debugger/threadshandler.h   |  2 ++
 src/plugins/debugger/watchutils.cpp     |  6 ++++
 7 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py
index e2bda10df31..97f736b7b9c 100644
--- a/share/qtcreator/gdbmacros/dumper.py
+++ b/share/qtcreator/gdbmacros/dumper.py
@@ -61,8 +61,9 @@ Hex4EncodedLittleEndian, \
 Hex8EncodedLittleEndian, \
 Hex2EncodedUtf8, \
 Hex8EncodedBigEndian, \
-Hex4EncodedBigEndian \
-    = range(12)
+Hex4EncodedBigEndian, \
+Hex4EncodedLittleEndianWithoutQuotes \
+    = range(13)
 
 # Display modes
 StopDisplay, \
@@ -1684,4 +1685,45 @@ class Dumper:
                     with Children(self, 1):
                         self.listAnonymous(child, name, field.type)
 
+#######################################################################
+#
+# ThreadNames Command
+#
+#######################################################################
+
+
+class ThreadNamesCommand(gdb.Command):
+    """Guess Thread names"""
+
+    def __init__(self):
+        super(ThreadNamesCommand, self).__init__("threadnames", gdb.COMMAND_OBSCURE)
+        self.ns = qtNamespace()
+
+    def invoke(self, arg, from_tty):
+        out = '['
+        for thread in gdb.inferiors()[0].threads():
+            maximalStackDepth = int(arg)
+            thread.switch()
+            e = gdb.selected_frame ()
+            while True:
+                maximalStackDepth -= 1
+                if maximalStackDepth < 0:
+                    break
+                e = e.older()
+                if e == None or e.name() == None:
+                    break
+                if e.name() == self.ns + "QThreadPrivate::start":
+                    thrptr = e.read_var("thr").dereference()
+                    d_ptr = thrptr["d_ptr"]["d"].cast(lookupType(self.ns + "QObjectPrivate").pointer()).dereference()
+                    #warn("D_PTR: %s " % d_ptr)
+                    objectName = d_ptr["objectName"]
+                    i = 0
+                    out += '{valueencoded="' + str(Hex4EncodedLittleEndianWithoutQuotes)+'",id="'
+                    out += str(thread.num) + '",value="'
+                    out += encodeString(objectName)
+                    out += '"},'
+        print out[:-1] + ']'
+
+ThreadNamesCommand()
+
 
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 2947f2cc2bd..0a835346bc3 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -2042,6 +2042,7 @@ void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine, bool notify)
     m_stackWindow->setModel(engine->stackModel());
     m_threadsWindow->setModel(engine->threadsModel());
     m_threadBox->setModel(engine->threadsModel());
+    m_threadBox->setModelColumn(ThreadData::NameColumn);
     m_watchersWindow->setModel(engine->watchersModel());
     m_capabilities = engine->debuggerCapabilities();
     if (notify)
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index aa9095b2ff0..45a5761472b 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -2963,6 +2963,7 @@ void GdbEngine::handleThreadInfo(const GdbResponse &response)
             response.data.findChild("current-thread-id").data().toInt();
         threadsHandler()->setCurrentThreadId(currentThreadId);
         plugin()->updateState(this); // Adjust Threads combobox.
+        postCommand("threadnames " + theDebuggerAction(MaximalStackDepth)->value().toByteArray(), CB(handleThreadNames), id);
     } else {
         // Fall back for older versions: Try to get at least a list
         // of running threads.
@@ -2986,6 +2987,31 @@ void GdbEngine::handleThreadListIds(const GdbResponse &response)
     threadsHandler()->setCurrentThreadId(id);
 }
 
+void GdbEngine::handleThreadNames(const GdbResponse &response)
+{
+    if (response.resultClass == GdbResultDone) {
+        GdbMi contents = response.data.findChild("consolestreamoutput");
+        GdbMi names;
+        names.fromString(contents.data());
+
+        Threads threads = threadsHandler()->threads();
+
+        foreach (const GdbMi &name, names.children()) {
+            int id = name.findChild("id").data().toInt();
+            for (int index = 0, n = threads.size(); index != n; ++index) {
+                ThreadData & thread = threads[index];
+                if (thread.id == id) {
+                    thread.name = decodeData(name.findChild("value").data(), name.findChild("valueencoded").data().toInt());
+                    break;
+                }
+            }
+        }
+        threadsHandler()->setThreads(threads);
+        plugin()->updateState(this);
+    }
+
+}
+
 
 //////////////////////////////////////////////////////////////////////
 //
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 7ddff2918ab..1fa5825f50f 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -435,6 +435,7 @@ private: ////////// View & Data Stuff //////////
     void handleStackSelectFrame(const GdbResponse &response);
     void handleThreadListIds(const GdbResponse &response);
     void handleThreadInfo(const GdbResponse &response);
+    void handleThreadNames(const GdbResponse &response);
     Q_SLOT void reloadStack(bool forceGotoLocation);
     Q_SLOT virtual void reloadFullStack();
     int currentFrame() const;
diff --git a/src/plugins/debugger/threadshandler.cpp b/src/plugins/debugger/threadshandler.cpp
index 9092e099a4a..f8a07920b9b 100644
--- a/src/plugins/debugger/threadshandler.cpp
+++ b/src/plugins/debugger/threadshandler.cpp
@@ -149,6 +149,10 @@ QVariant ThreadsHandler::data(const QModelIndex &index, int role) const
             return thread.core;
         case ThreadData::StateColumn:
             return thread.state;
+        case ThreadData::NameColumn:
+            if (thread.name.isEmpty())
+                return thread.id;
+            return thread.name;
         }
     case Qt::ToolTipRole:
         return threadToolTip(thread);
@@ -183,6 +187,8 @@ QVariant ThreadsHandler::headerData
         return tr("Core");
     case ThreadData::StateColumn:
         return tr("State");
+    case ThreadData::NameColumn:
+        return tr("Name");
     }
     return QVariant();
 }
diff --git a/src/plugins/debugger/threadshandler.h b/src/plugins/debugger/threadshandler.h
index 6815dafc1ae..5dfb6046c21 100644
--- a/src/plugins/debugger/threadshandler.h
+++ b/src/plugins/debugger/threadshandler.h
@@ -59,6 +59,7 @@ struct ThreadData
         FileColumn,
         LineColumn,
         StateColumn,
+        NameColumn,
         CoreColumn,
         ColumnCount = CoreColumn
     };
@@ -77,6 +78,7 @@ struct ThreadData
     QString fileName;
     QString state;
     int lineNumber;
+    QString name;
 };
 
 typedef QVector<ThreadData> Threads;
diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp
index 435deb9e131..f4a1a6059d4 100644
--- a/src/plugins/debugger/watchutils.cpp
+++ b/src/plugins/debugger/watchutils.cpp
@@ -716,6 +716,12 @@ QString decodeData(const QByteArray &ba, int encoding)
             return doubleQuote + QString::fromUtf16(reinterpret_cast<const ushort *>
                 (decodedBa.data()), decodedBa.size() / 2) + doubleQuote;
         }
+        case 12: { //  %04x encoded 16 bit data, Little Endian, without quotes (see 7)
+            const QByteArray decodedBa = QByteArray::fromHex(ba);
+            //qDebug() << quoteUnprintableLatin1(decodedBa) << "\n\n";
+            return QString::fromUtf16(reinterpret_cast<const ushort *>
+                (decodedBa.data()), decodedBa.size() / 2);
+        }
     }
     qDebug() << "ENCODING ERROR: " << encoding;
     return QCoreApplication::translate("Debugger", "<Encoding error>");
-- 
GitLab