diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index ef01cadb67cdfeb238456d63a6491a014ff1d5b3..2867217731ea1cc198eaeb84636303647be49a10 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -121,7 +121,6 @@ void BreakHandler::clear() m_enabled.clear(); m_disabled.clear(); m_removed.clear(); - m_inserted.clear(); } BreakpointData *BreakHandler::findSimilarBreakpoint(const BreakpointData *needle) const @@ -527,17 +526,6 @@ void BreakHandler::append(BreakpointData *data) QTC_ASSERT(m_bp,/**/); data->m_handler = this; m_bp->append(data); - m_inserted.append(data); -} - -Breakpoints BreakHandler::insertedBreakpoints() const -{ - return m_inserted; -} - -void BreakHandler::takeInsertedBreakPoint(BreakpointData *d) -{ - m_inserted.removeAll(d); } Breakpoints BreakHandler::takeRemovedBreakpoints() diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 26e4e0eea6e478fb17bcfa7ba4c6fd77dca10444..f14d674f98f7c0663375c5a1f04c790874382670 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -78,8 +78,6 @@ public: bool isActive() const; bool isMasterList() const; - Breakpoints insertedBreakpoints() const; - void takeInsertedBreakPoint(BreakpointData *); Breakpoints takeRemovedBreakpoints(); // Owned. Breakpoints takeEnabledBreakpoints(); // Not owned. Breakpoints takeDisabledBreakpoints(); // Not owned. diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp index 6115b60053539c6a479cc12f8a8a0a4915606aba..f9eaca6bcb4fe0d5567a33df6978dc976f03a69d 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp +++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp @@ -67,6 +67,47 @@ static inline QString msgCannotSetBreakAtFunction(const QString &func, const QSt return QString::fromLatin1("Cannot set a breakpoint at '%1': %2").arg(func, why); } +static bool addBreakpoint(CIDebugControl* debugControl, + CIDebugSymbols *syms, + BreakpointData *nbd, + QString *warning) +{ + warning->clear(); + // Function breakpoints: Are the module names specified? + if (!nbd->funcName.isEmpty()) { + nbd->bpFuncName = nbd->funcName; + switch (resolveSymbol(syms, &nbd->bpFuncName, warning)) { + case ResolveSymbolOk: + break; + case ResolveSymbolAmbiguous: + *warning = msgCannotSetBreakAtFunction(nbd->funcName, *warning); + break; + case ResolveSymbolNotFound: + case ResolveSymbolError: + *warning = msgCannotSetBreakAtFunction(nbd->funcName, *warning); + return false; + }; + } // function breakpoint + // Now add... + quint64 address; + unsigned long id; + const CdbCore::BreakPoint ncdbbp = breakPointFromBreakPointData(*nbd); + if (!ncdbbp.add(debugControl, warning, &id, &address)) + return false; + if (debugBP) + qDebug("Added %lu at 0x%lx %s", id, address, qPrintable(ncdbbp.toString())); + nbd->pending = false; + nbd->bpNumber = QByteArray::number(uint(id)); + nbd->bpAddress = address; + // Take over rest as is + nbd->bpCondition = nbd->condition; + nbd->bpIgnoreCount = nbd->ignoreCount; + nbd->bpThreadSpec = nbd->threadSpec; + nbd->bpFileName = nbd->fileName; + nbd->bpLineNumber = nbd->lineNumber; + return true; +} + // Synchronize (halted) engine breakpoints with those of the BreakHandler. bool synchronizeBreakPoints(CIDebugControl* debugControl, CIDebugSymbols *syms, @@ -83,82 +124,35 @@ bool synchronizeBreakPoints(CIDebugControl* debugControl, *errorMessage = QString::fromLatin1("Cannot modify breakpoints: %1").arg(*errorMessage); return false; } + // Delete all breakpoints and re-insert all enabled breakpoints. This is the simplest + // way to apply changes since CDB ids shift when removing breakpoints and there is no + // easy way to re-match them. + if (engineCount) { + for (int b = engineCount - 1; b >= 0 ; b--) + if (!CdbCore::BreakPoint::removeBreakPointById(debugControl, b, errorMessage)) + return false; + } + qDeleteAll(handler->takeRemovedBreakpoints()); + // Mark disabled ones + foreach(BreakpointData *dbd, handler->takeDisabledBreakpoints()) + dbd->bpEnabled = false; + + // Insert all enabled ones as new QString warning; - // Insert new ones bool updateMarkers = false; - foreach (BreakpointData *nbd, handler->insertedBreakpoints()) { - warning.clear(); - // Function breakpoints: Are the module names specified? - bool breakPointOk = false; - if (nbd->funcName.isEmpty()) { - breakPointOk = true; - } else { - nbd->bpFuncName = nbd->funcName; - switch (resolveSymbol(syms, &nbd->bpFuncName, &warning)) { - case ResolveSymbolOk: - breakPointOk = true; - break; - case ResolveSymbolAmbiguous: - warnings->push_back(msgCannotSetBreakAtFunction(nbd->funcName, warning)); - warning.clear(); - breakPointOk = true; - break; - case ResolveSymbolNotFound: - case ResolveSymbolError: - warnings->push_back(msgCannotSetBreakAtFunction(nbd->funcName, warning)); - warning.clear(); - break; - }; - } // function breakpoint - // Now add... - if (breakPointOk) { - quint64 address; - unsigned long id; - const CdbCore::BreakPoint ncdbbp = breakPointFromBreakPointData(*nbd); - breakPointOk = ncdbbp.add(debugControl, &warning, &id, &address); - if (breakPointOk) { - if (debugBP) - qDebug("Added %lu at 0x%lx %s", id, address, qPrintable(ncdbbp.toString())); - handler->takeInsertedBreakPoint(nbd); + const int size = handler->size(); + for (int i = 0; i < size; i++) { + BreakpointData *breakpoint = handler->at(i); + if (breakpoint->enabled) + if (addBreakpoint(debugControl, syms, breakpoint, &warning)) { updateMarkers = true; - nbd->pending = false; - nbd->bpNumber = QByteArray::number(uint(id)); - nbd->bpAddress = address; - // Take over rest as is - nbd->bpCondition = nbd->condition; - nbd->bpIgnoreCount = nbd->ignoreCount; - nbd->bpThreadSpec = nbd->threadSpec; - nbd->bpFileName = nbd->fileName; - nbd->bpLineNumber = nbd->lineNumber; - } - } // had symbol - if (!breakPointOk && !warning.isEmpty()) - warnings->push_back(warning); } - // Delete - foreach (BreakpointData *rbd, handler->takeRemovedBreakpoints()) { - if (!CdbCore::BreakPoint::removeBreakPointById(debugControl, rbd->bpNumber.toUInt(), &warning)) - warnings->push_back(warning); - delete rbd; - } - // Enable/Disable - foreach (BreakpointData *ebd, handler->takeEnabledBreakpoints()) - if (!CdbCore::BreakPoint::setBreakPointEnabledById(debugControl, ebd->bpNumber.toUInt(), true, &warning)) - warnings->push_back(warning); - foreach (BreakpointData *dbd, handler->takeDisabledBreakpoints()) - if (!CdbCore::BreakPoint::setBreakPointEnabledById(debugControl, dbd->bpNumber.toUInt(), false, &warning)) - warnings->push_back(warning); - // Check for modified thread ids. - for (int i = handler->size() - 1; i >= 0; i--) { - BreakpointData *bpd = handler->at(i); - if (bpd->threadSpec != bpd->bpThreadSpec) { - const int newThreadSpec = bpd->threadSpec.isEmpty() ? -1 : bpd->threadSpec.toInt(); - if (CdbCore::BreakPoint::setBreakPointThreadById(debugControl, bpd->bpNumber.toUInt(), newThreadSpec, errorMessage)) { - bpd->bpThreadSpec = bpd->threadSpec; } else { - qWarning("%s", qPrintable(*errorMessage)); + warnings->push_back(warning); } - } } + // Mark enabled ones + foreach(BreakpointData *ebd, handler->takeEnabledBreakpoints()) + ebd->bpEnabled = true; if (updateMarkers) handler->updateMarkers(); diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index a06551300fefdea128cb0bf543980708ea9d7592..8d8475a5ad7de4277990ea8a41d357dfe4e3d6d7 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -1171,6 +1171,11 @@ bool CdbEnginePrivate::attemptBreakpointSynchronization(QString *errorMessage) *errorMessage = QLatin1String("attemptBreakpointSynchronization() called while debugger is not running"); return false; } + // Might be called nested while attempting to stop. + if (m_breakEventMode == BreakEventSyncBreakPoints) { + *errorMessage = QLatin1String("Nested invocation of attemptBreakpointSynchronization."); + return false; + } // This is called from // 1) CreateProcessEvent with the halted engine // 2) from the break handler, potentially while the debuggee is running