forked from qt-creator/qt-creator
CDB: Provide thread frame information
This commit is contained in:
@@ -1701,36 +1701,12 @@ ULONG CdbDebugEnginePrivate::updateThreadList()
|
|||||||
if (debugCDB)
|
if (debugCDB)
|
||||||
qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess;
|
qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess;
|
||||||
|
|
||||||
ThreadsHandler* th = manager()->threadsHandler();
|
|
||||||
QList<ThreadData> threads;
|
QList<ThreadData> threads;
|
||||||
bool success = false;
|
ULONG currentThreadId;
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
ULONG currentThreadId = 0;
|
if (!CdbStackTraceContext::getThreads(m_cif, true, &threads, ¤tThreadId, &errorMessage))
|
||||||
do {
|
m_engine->warning(errorMessage);
|
||||||
ULONG threadCount;
|
manager()->threadsHandler()->setThreads(threads);
|
||||||
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));
|
|
||||||
return currentThreadId;
|
return currentThreadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ struct CdbComInterfaces;
|
|||||||
class CdbSymbolGroupContext;
|
class CdbSymbolGroupContext;
|
||||||
class CdbStackFrameContext;
|
class CdbStackFrameContext;
|
||||||
class CdbDumperHelper;
|
class CdbDumperHelper;
|
||||||
|
struct ThreadData;
|
||||||
|
|
||||||
/* Context representing a break point stack consisting of several frames.
|
/* Context representing a break point stack consisting of several frames.
|
||||||
* Maintains an on-demand constructed list of CdbStackFrameContext
|
* Maintains an on-demand constructed list of CdbStackFrameContext
|
||||||
@@ -81,6 +82,14 @@ public:
|
|||||||
void format(QTextStream &str) const;
|
void format(QTextStream &str) const;
|
||||||
QString toString() 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:
|
private:
|
||||||
bool init(unsigned long frameCount, QString *errorMessage);
|
bool init(unsigned long frameCount, QString *errorMessage);
|
||||||
CIDebugSymbolGroup *createSymbolGroup(int index, QString *errorMessage);
|
CIDebugSymbolGroup *createSymbolGroup(int index, QString *errorMessage);
|
||||||
|
|||||||
Reference in New Issue
Block a user