diff --git a/src/libs/qtcreatorcdbext/extensioncontext.h b/src/libs/qtcreatorcdbext/extensioncontext.h index 27a3f76b22e..5c7baad4362 100644 --- a/src/libs/qtcreatorcdbext/extensioncontext.h +++ b/src/libs/qtcreatorcdbext/extensioncontext.h @@ -90,6 +90,7 @@ public: // Return symbol group for frame (cached as long as frame/thread do not change). LocalsSymbolGroup *symbolGroup(CIDebugSymbols *symbols, ULONG threadId, int frame, std::string *errorMessage); int symbolGroupFrame() const; + void discardSymbolGroup(); WatchesSymbolGroup *watchesSymbolGroup(CIDebugSymbols *symbols, std::string *errorMessage); WatchesSymbolGroup *watchesSymbolGroup() const; // Do not create. @@ -105,7 +106,6 @@ public: private: bool isInitialized() const; - void discardSymbolGroup(); IInterfacePointer m_control; std::auto_ptr m_symbolGroup; diff --git a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp index ef3fd00ec0a..785efdcc8eb 100644 --- a/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp +++ b/src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp @@ -125,6 +125,7 @@ static const CommandDescription commandDescriptions[] = { "-u uninitialized-list Comma-separated list of uninitialized inames\n" "-I formatmap map of 'hex-encoded-iname=typecode'\n" "-T formatmap map of 'hex-encoded-type-name=typecode'\n" + "-D Discard existing symbol group\n" "-W Synchronize watch items (-w)\n" "-w iname expression Watch item"}, {"watches", @@ -403,6 +404,7 @@ static std::string commmandLocals(ExtensionCommandContext &commandExtCtx,PCSTR a StringVector uninitializedInames; InameExpressionMap watcherInameExpressionMap; bool watchSynchronization = false; + bool discardSymbolGroup = false; // Parse away options for (bool optionLeft = true; optionLeft && !tokens.empty(); ) { switch (parameters.parseOption(&tokens)) { @@ -446,6 +448,9 @@ static std::string commmandLocals(ExtensionCommandContext &commandExtCtx,PCSTR a case 'W': watchSynchronization = true; break; + case 'D': + discardSymbolGroup = true; + break; } // case option } break; @@ -466,6 +471,8 @@ static std::string commmandLocals(ExtensionCommandContext &commandExtCtx,PCSTR a iname = tokens.front(); const SymbolGroupValueContext dumpContext(commandExtCtx.dataSpaces(), commandExtCtx.symbols()); + if (discardSymbolGroup) + extCtx.discardSymbolGroup(); SymbolGroup * const symGroup = extCtx.symbolGroup(commandExtCtx.symbols(), commandExtCtx.threadId(), frame, errorMessage); if (!symGroup) return std::string(); diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index d6d8440035b..8ad1c17f48a 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -1111,9 +1111,13 @@ void CdbEngine::updateLocals() watchHandler()->endCycle(); return; } - // Watchers: Initial expand, get uninitialized and query + /* Watchers: Forcibly discard old symbol group as switching from + * thread 0/frame 0 -> thread 1/assembly -> thread 0/frame 0 will otherwise re-use it + * and cause errors as it seems to go 'stale' when switching threads. + * Initial expand, get uninitialized and query */ QByteArray arguments; ByteArrayInputStream str(arguments); + str << "-D"; // Pre-expand const QSet expanded = watchHandler()->expandedINames(); if (!expanded.isEmpty()) { @@ -1428,7 +1432,9 @@ enum StopActionFlags StopShowExceptionMessageBox = 0x4, // Notify stop or just continue StopNotifyStop = 0x8, - StopIgnoreContinue = 0x10 + StopIgnoreContinue = 0x10, + // Hit on break in artificial stop thread (created by DebugBreak()). + StopInArtificialThread = 0x20 }; unsigned CdbEngine::examineStopReason(const QByteArray &messageIn, @@ -1483,8 +1489,12 @@ unsigned CdbEngine::examineStopReason(const QByteArray &messageIn, } } if (isDebuggerWinException(exception.exceptionCode)) { + unsigned rc = StopReportStatusMessage|StopNotifyStop; + // Detect interruption by DebugBreak() and force a switch to thread 0. + if (exception.function == "ntdll!DbgBreakPoint") + rc |= StopInArtificialThread; *message = msgInterrupted(); - return StopReportStatusMessage|StopNotifyStop; + return rc; } #endif *exceptionBoxMessage = msgStoppedByException(description, QString::number(threadId)); @@ -1561,6 +1571,10 @@ void CdbEngine::handleSessionIdle(const QByteArray &messageBA) notifyInferiorSpontaneousStop(); } // Start sequence to get all relevant data. + if (stopFlags & StopInArtificialThread) { + showMessage(tr("Switching to main thread..."), LogMisc); + postCommand("~0 s", 0); + } unsigned sequence = CommandListStack|CommandListThreads; if (debuggerCore()->isDockVisible(QLatin1String(Constants::DOCKWIDGET_REGISTER))) sequence |= CommandListRegisters;