// 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.
private:
bool isInitialized() const;
- void discardSymbolGroup();
IInterfacePointer<CIDebugControl> m_control;
std::auto_ptr<LocalsSymbolGroup> m_symbolGroup;
"-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",
StringVector uninitializedInames;
InameExpressionMap watcherInameExpressionMap;
bool watchSynchronization = false;
+ bool discardSymbolGroup = false;
// Parse away options
for (bool optionLeft = true; optionLeft && !tokens.empty(); ) {
switch (parameters.parseOption(&tokens)) {
case 'W':
watchSynchronization = true;
break;
+ case 'D':
+ discardSymbolGroup = true;
+ break;
} // case option
}
break;
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();
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<QByteArray> expanded = watchHandler()->expandedINames();
if (!expanded.isEmpty()) {
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,
}
}
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));
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;