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