From 2a9233a03a5fa71e302a9268b156bb098038749d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Mon, 5 Oct 2009 17:20:38 +0200 Subject: [PATCH] CDB: Provide thread frame information --- src/plugins/debugger/cdb/cdbdebugengine.cpp | 32 +----- .../debugger/cdb/cdbstacktracecontext.cpp | 100 ++++++++++++++++++ .../debugger/cdb/cdbstacktracecontext.h | 9 ++ 3 files changed, 113 insertions(+), 28 deletions(-) diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index c6e4ca512c4..11f37d15f19 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -1701,36 +1701,12 @@ ULONG CdbDebugEnginePrivate::updateThreadList() if (debugCDB) qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess; - ThreadsHandler* th = manager()->threadsHandler(); QList<ThreadData> threads; - bool success = false; + ULONG currentThreadId; QString errorMessage; - ULONG currentThreadId = 0; - do { - ULONG threadCount; - HRESULT hr= m_cif.debugSystemObjects->GetNumberThreads(&threadCount); - if (FAILED(hr)) { - errorMessage= msgComFailed("GetNumberThreads", hr); - break; - } - // Get ids and index of current - if (threadCount) { - m_cif.debugSystemObjects->GetCurrentThreadId(¤tThreadId); - QVector<ULONG> threadIds(threadCount); - hr = m_cif.debugSystemObjects->GetThreadIdsByIndex(0, threadCount, &(*threadIds.begin()), 0); - if (FAILED(hr)) { - errorMessage= msgComFailed("GetThreadIdsByIndex", hr); - break; - } - for (ULONG i = 0; i < threadCount; i++) - threads.push_back(ThreadData(threadIds.at(i))); - } - - th->setThreads(threads); - success = true; - } while (false); - if (!success) - m_engine->warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); + if (!CdbStackTraceContext::getThreads(m_cif, true, &threads, ¤tThreadId, &errorMessage)) + m_engine->warning(errorMessage); + manager()->threadsHandler()->setThreads(threads); return currentThreadId; } diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp index 40cd9776bcb..3e5f1c65fcb 100644 --- a/src/plugins/debugger/cdb/cdbstacktracecontext.cpp +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.cpp @@ -219,5 +219,105 @@ void CdbStackTraceContext::format(QTextStream &str) const } } +// Thread state helper + +static inline QString msgGetThreadStateFailed(unsigned long threadId, const QString &why) +{ + return QString::fromLatin1("Unable to determine the state of thread %1: %2").arg(threadId).arg(why); +} + +static inline bool getStoppedThreadState(const CdbComInterfaces &cif, + ThreadData *t, + QString *errorMessage) +{ + ULONG currentThread; + HRESULT hr = cif.debugSystemObjects->GetCurrentThreadId(¤tThread); + if (FAILED(hr)) { + *errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("GetCurrentThreadId", hr)); + return false; + } + if (currentThread != t->id) { + hr = cif.debugSystemObjects->SetCurrentThreadId(t->id); + if (FAILED(hr)) { + *errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("SetCurrentThreadId", hr)); + return false; + } + } + ULONG frameCount; + DEBUG_STACK_FRAME topFrame[1]; + hr = cif.debugControl->GetStackTrace(0, 0, 0, topFrame, 1, &frameCount); + if (FAILED(hr)) { + *errorMessage = msgGetThreadStateFailed(t->id, msgComFailed("GetStackTrace", hr)); + return false; + } + + t->address = topFrame[0].InstructionOffset; + WCHAR wszBuf[MAX_PATH]; + + cif.debugSymbols->GetNameByOffsetWide(topFrame[0].InstructionOffset, wszBuf, MAX_PATH, 0, 0); + t->function = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)); + ULONG ulLine; + hr = cif.debugSymbols->GetLineByOffsetWide(topFrame[0].InstructionOffset, &ulLine, wszBuf, MAX_PATH, 0, 0); + if (SUCCEEDED(hr)) { + t->line = ulLine; + // Just display base name + t->file = QString::fromUtf16(reinterpret_cast<const ushort *>(wszBuf)); + if (!t->file.isEmpty()) { + const int slashPos = t->file.lastIndexOf(QLatin1Char('\\')); + if (slashPos != -1) + t->file.remove(0, slashPos + 1); + } + } + return true; +} + +static inline QString msgGetThreadsFailed(const QString &why) +{ + return QString::fromLatin1("Unable to determine the thread information: %1").arg(why); +} + +bool CdbStackTraceContext::getThreads(const CdbComInterfaces &cif, + bool isStopped, + QList<ThreadData> *threads, + ULONG *currentThreadId, + QString *errorMessage) +{ + threads->clear(); + ULONG threadCount; + *currentThreadId = 0; + HRESULT hr= cif.debugSystemObjects->GetNumberThreads(&threadCount); + if (FAILED(hr)) { + *errorMessage= msgGetThreadsFailed(msgComFailed("GetNumberThreads", hr)); + return false; + } + // Get ids and index of current + if (!threadCount) + return true; + hr = cif.debugSystemObjects->GetCurrentThreadId(currentThreadId); + if (FAILED(hr)) { + *errorMessage= msgGetThreadsFailed(msgComFailed("GetCurrentThreadId", hr)); + return false; + } + + QVector<ULONG> threadIds(threadCount); + hr = cif.debugSystemObjects->GetThreadIdsByIndex(0, threadCount, &(*threadIds.begin()), 0); + if (FAILED(hr)) { + *errorMessage= msgGetThreadsFailed(msgComFailed("GetThreadIdsByIndex", hr)); + return false; + } + for (ULONG i = 0; i < threadCount; i++) { + ThreadData threadData(threadIds.at(i)); + if (isStopped) { + if (!getStoppedThreadState(cif, &threadData, errorMessage)) { + qWarning("%s\n", qPrintable(*errorMessage)); + errorMessage->clear(); + } + } + threads->push_back(threadData); + } + return true; +} + + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/cdb/cdbstacktracecontext.h b/src/plugins/debugger/cdb/cdbstacktracecontext.h index d0d05bea1e8..ff8c62d5b19 100644 --- a/src/plugins/debugger/cdb/cdbstacktracecontext.h +++ b/src/plugins/debugger/cdb/cdbstacktracecontext.h @@ -49,6 +49,7 @@ struct CdbComInterfaces; class CdbSymbolGroupContext; class CdbStackFrameContext; class CdbDumperHelper; +struct ThreadData; /* Context representing a break point stack consisting of several frames. * Maintains an on-demand constructed list of CdbStackFrameContext @@ -81,6 +82,14 @@ public: void format(QTextStream &str) const; QString toString() const; + // Retrieve information about threads. When stopped, add + // current stack frame. + static bool getThreads(const CdbComInterfaces &cif, + bool isStopped, + QList<ThreadData> *threads, + ULONG *currentThreadId, + QString *errorMessage); + private: bool init(unsigned long frameCount, QString *errorMessage); CIDebugSymbolGroup *createSymbolGroup(int index, QString *errorMessage); -- GitLab