forked from qt-creator/qt-creator
CDB: Fix step into, improve multithread dumping, exception logging
Use new call syntax of 6.11. for dumper call loading. Execute Dumpers in a single thread (current) if at all possible (not in some WaitFor or artificial break thread). Show one more frame in threads view if it is FastCallReturn. Fix step into (ignore one event), log some more exceptions. Generally log exceptions to the debugger windows to be able to see stuff like DLL missing, etc.
This commit is contained in:
@@ -302,6 +302,7 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *manager,
|
||||
m_dumper(new CdbDumperHelper(manager, &m_cif)),
|
||||
m_currentThreadId(-1),
|
||||
m_eventThreadId(-1),
|
||||
m_interrupted(false),
|
||||
m_watchTimer(-1),
|
||||
m_debugEventCallBack(engine),
|
||||
m_engine(engine),
|
||||
@@ -445,6 +446,7 @@ void CdbDebugEnginePrivate::clearForRun()
|
||||
|
||||
m_breakEventMode = BreakEventHandle;
|
||||
m_eventThreadId = -1;
|
||||
m_interrupted = false;
|
||||
cleanStackTrace();
|
||||
}
|
||||
|
||||
@@ -1026,6 +1028,9 @@ bool CdbDebugEngine::step(unsigned long executionStatus)
|
||||
warning(msgStepFailed(executionStatus, m_d->m_currentThreadId, msgDebuggerCommandFailed(command, hr)));
|
||||
}
|
||||
if (success) {
|
||||
// Oddity: Step into will first break at the calling function. Ignore
|
||||
if (executionStatus == DEBUG_STATUS_STEP_INTO || executionStatus == DEBUG_STATUS_REVERSE_STEP_INTO)
|
||||
m_d->m_breakEventMode = CdbDebugEnginePrivate::BreakEventIgnoreOnce;
|
||||
startWatchTimer();
|
||||
setState(InferiorRunning, Q_FUNC_INFO, __LINE__);
|
||||
} else {
|
||||
@@ -1169,7 +1174,9 @@ bool CdbDebugEnginePrivate::interruptInterferiorProcess(QString *errorMessage)
|
||||
qDebug() << Q_FUNC_INFO << "\n ex=" << executionStatus;
|
||||
}
|
||||
|
||||
if (!DebugBreakProcess(m_hDebuggeeProcess)) {
|
||||
if (DebugBreakProcess(m_hDebuggeeProcess)) {
|
||||
m_interrupted = true;
|
||||
} else {
|
||||
*errorMessage = QString::fromLatin1("DebugBreakProcess failed: %1").arg(Utils::winErrorMessage(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
@@ -1704,12 +1711,34 @@ ULONG CdbDebugEnginePrivate::updateThreadList()
|
||||
QList<ThreadData> threads;
|
||||
ULONG currentThreadId;
|
||||
QString errorMessage;
|
||||
// When interrupting, an artifical thread with a breakpoint is created.
|
||||
if (!CdbStackTraceContext::getThreads(m_cif, true, &threads, ¤tThreadId, &errorMessage))
|
||||
m_engine->warning(errorMessage);
|
||||
manager()->threadsHandler()->setThreads(threads);
|
||||
return currentThreadId;
|
||||
}
|
||||
|
||||
// Figure out the thread to run the dumpers in (see notes on.
|
||||
// CdbDumperHelper). Avoid the artifical threads created by interrupt
|
||||
// and threads that are in waitFor().
|
||||
// A stricter version could only use the thread if it is the event
|
||||
// thread of a step or breakpoint hit (see CdbDebugEnginePrivate::m_interrupted).
|
||||
|
||||
static inline unsigned long dumperThreadId(const QList<StackFrame> &frames,
|
||||
unsigned long currentThread)
|
||||
{
|
||||
if (frames.empty())
|
||||
return CdbDumperHelper::InvalidDumperCallThread;
|
||||
if (frames.at(0).function == QLatin1String(CdbStackTraceContext::winFuncDebugBreakPoint))
|
||||
return CdbDumperHelper::InvalidDumperCallThread;
|
||||
const int waitCheckDepth = qMin(frames.size(), 5);
|
||||
static const QString waitForPrefix = QLatin1String(CdbStackTraceContext::winFuncWaitForPrefix);
|
||||
for (int f = 0; f < waitCheckDepth; f++)
|
||||
if (frames.at(f).function.startsWith(waitForPrefix))
|
||||
return CdbDumperHelper::InvalidDumperCallThread;
|
||||
return currentThread;
|
||||
}
|
||||
|
||||
void CdbDebugEnginePrivate::updateStackTrace()
|
||||
{
|
||||
if (debugCDB)
|
||||
@@ -1750,11 +1779,19 @@ void CdbDebugEnginePrivate::updateStackTrace()
|
||||
CdbDebugEngine::tr("Thread %1: No debug information available (%2).").arg(m_currentThreadId).arg(topFunction);
|
||||
m_engine->warning(msg);
|
||||
}
|
||||
|
||||
// Set up dumper with a thread (or invalid)
|
||||
const unsigned long dumperThread = dumperThreadId(stackFrames, m_currentThreadId);
|
||||
if (debugCDB)
|
||||
qDebug() << "updateStackTrace() current: " << m_currentThreadId << " dumper=" << dumperThread;
|
||||
m_dumper->setDumperCallThread(dumperThread);
|
||||
// Display frames
|
||||
manager()->stackHandler()->setFrames(stackFrames);
|
||||
m_firstActivatedFrame = true;
|
||||
if (current >= 0) {
|
||||
manager()->stackHandler()->setCurrentIndex(current);
|
||||
// First time : repaint
|
||||
if (m_dumper->isEnabled() && m_dumper->state() != CdbDumperHelper::Initialized)
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
m_engine->activateFrame(current);
|
||||
}
|
||||
manager()->watchHandler()->updateWatchers();
|
||||
|
||||
Reference in New Issue
Block a user