OSDN Git Service

Debugger[CDB]: Switch to thread 0 after DebugBreak().
authorFriedemann Kleint <Friedemann.Kleint@nokia.com>
Tue, 18 Jan 2011 14:28:55 +0000 (15:28 +0100)
committerFriedemann Kleint <Friedemann.Kleint@nokia.com>
Tue, 18 Jan 2011 14:34:58 +0000 (15:34 +0100)
Do not show artificial thread that is created by
DebugBreak() as it causes a switch to disassembly.
Forcibly discard the symbol group for each locals
update as the lazy creation mechanism does not trigger
on thread changes back and forth involving assembly,
which causes the symbol group to become stale.

src/libs/qtcreatorcdbext/extensioncontext.h
src/libs/qtcreatorcdbext/qtcreatorcdbextension.cpp
src/plugins/debugger/cdb/cdbengine.cpp

index 27a3f76..5c7baad 100644 (file)
@@ -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<CIDebugControl> m_control;
     std::auto_ptr<LocalsSymbolGroup> m_symbolGroup;
index ef3fd00..785efdc 100644 (file)
@@ -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();
index d6d8440..8ad1c17 100644 (file)
@@ -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<QByteArray> 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;