From 0b32820a4875e6c36022b3589ec24e66d647a131 Mon Sep 17 00:00:00 2001 From: hjk Date: Mon, 15 Nov 2010 16:22:51 +0100 Subject: [PATCH] debugger: work on breakpoint enabling/disabling in gdb engine --- src/plugins/debugger/breakhandler.cpp | 39 ++++---- src/plugins/debugger/breakhandler.h | 4 +- src/plugins/debugger/breakpoint.cpp | 10 +-- src/plugins/debugger/breakpoint.h | 2 +- src/plugins/debugger/gdb/gdbengine.cpp | 120 ++++++++++++++++++------- src/plugins/debugger/gdb/gdbengine.h | 1 + 6 files changed, 115 insertions(+), 61 deletions(-) diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 82762209030..444b6481eb9 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -489,8 +489,10 @@ void BreakHandler::setter(BreakpointId id, const type &value) \ Iterator it = m_storage.find(id); \ QTC_ASSERT(it != m_storage.end(), \ qDebug() << "ID" << id << "NOT KNOWN"; return); \ - if (it->data.setter(value)) \ - scheduleSynchronization(); \ + if (!it->data.setter(value)) \ + return; \ + it->state = BreakpointChangeRequested; \ + scheduleSynchronization(); \ } #define PROPERTY(type, getter, setter) \ @@ -524,6 +526,7 @@ void BreakHandler::setEnabled(BreakpointId id, bool on) //qDebug() << "SET ENABLED: " << id << it->data.isEnabled() << on; if (it->data.setEnabled(on)) { it->destroyMarker(); + it->state = BreakpointChangeRequested; updateMarker(id); scheduleSynchronization(); } @@ -579,6 +582,14 @@ void BreakHandler::ackIgnoreCount(BreakpointId id) updateMarker(id); } +void BreakHandler::ackEnabled(BreakpointId id) +{ + Iterator it = m_storage.find(id); + QTC_ASSERT(it != m_storage.end(), return); + it->response.bpEnabled = it->data.isEnabled(); + updateMarker(id); +} + Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const { // switch (index.column()) { @@ -825,10 +836,11 @@ void BreakHandler::cleanupBreakpoint(BreakpointId id) layoutChanged(); } -BreakpointResponse BreakHandler::response(BreakpointId id) const +const BreakpointResponse &BreakHandler::response(BreakpointId id) const { + static BreakpointResponse dummy; ConstIterator it = m_storage.find(id); - QTC_ASSERT(it != m_storage.end(), return BreakpointResponse()); + QTC_ASSERT(it != m_storage.end(), return dummy); return it->response; } @@ -839,25 +851,6 @@ void BreakHandler::setResponse(BreakpointId id, const BreakpointResponse &data) it->response = BreakpointResponse(data); updateMarker(id); } -#if 0 -void BreakHandler::notifyBreakpointAdjusted(BreakpointId id) -{ - QTC_ASSERT(state(id)== BreakpointChangeProceeding, /**/); - bp->bpNumber = rbp.bpNumber; - bp->bpCondition = rbp.bpCondition; - bp->bpIgnoreCount = rbp.bpIgnoreCount; - bp->bpFileName = rbp.bpFileName; - bp->bpFullName = rbp.bpFullName; - bp->bpLineNumber = rbp.bpLineNumber; - bp->bpCorrectedLineNumber = rbp.bpCorrectedLineNumber; - bp->bpThreadSpec = rbp.bpThreadSpec; - bp->bpFuncName = rbp.bpFuncName; - bp->bpAddress = rbp.bpAddress; - bp->bpMultiple = rbp.bpMultiple; - bp->bpEnabled = rbp.bpEnabled; - setState(id, BreakpointOk); -} -#endif void BreakHandler::BreakpointItem::destroyMarker() { diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 3e552d9e04d..92093e444bb 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -124,13 +124,13 @@ public: DebuggerEngine *engine(BreakpointId id) const; void setEngine(BreakpointId id, DebuggerEngine *engine); - BreakpointResponse response(BreakpointId id) const; + const BreakpointResponse &response(BreakpointId id) const; void setResponse(BreakpointId id, const BreakpointResponse &data); // Incorporate debugger feedback. No synchronization request needed. - // Return true if something changed. void ackCondition(BreakpointId id); void ackIgnoreCount(BreakpointId id); + void ackEnabled(BreakpointId id); void notifyBreakpointInsertOk(BreakpointId id); void notifyBreakpointInsertFailed(BreakpointId id); diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp index 3ca98104f3c..fbaaeec5bdd 100644 --- a/src/plugins/debugger/breakpoint.cpp +++ b/src/plugins/debugger/breakpoint.cpp @@ -124,13 +124,13 @@ bool BreakpointData::isLocatedAt(const QString &fileName, int lineNumber, return lineNumber == line && fileNameMatch(fileName, m_markerFileName); } -bool BreakpointData::conditionsMatch(const QString &other) const +bool BreakpointData::conditionsMatch(const QByteArray &other) const { // Some versions of gdb "beautify" the passed condition. - QString s1 = m_condition; - s1.remove(QChar(' ')); - QString s2 = other; - s2.remove(QChar(' ')); + QByteArray s1 = m_condition; + s1.replace(' ', ""); + QByteArray s2 = other; + s2.replace(' ', ""); return s1 == s2; } diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index 81e3da214af..ac239db57b6 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -99,7 +99,7 @@ public: bool isLocatedAt(const QString &fileName, int lineNumber, bool useMarkerPosition) const; - bool conditionsMatch(const QString &other) const; + bool conditionsMatch(const QByteArray &other) const; QString functionName() const { return m_functionName; } QString markerFileName() const { return m_markerFileName; } QString fileName() const { return m_fileName; } diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index fdae9ffc626..21565cbdae8 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -2297,9 +2297,20 @@ void GdbEngine::handleBreakList(const GdbMi &table) void GdbEngine::handleBreakDisable(const GdbResponse &response) { - if (response.resultClass == GdbResultDone) { - breakHandler()->updateMarkers(); - } + QTC_ASSERT(response.resultClass == GdbResultDone, /**/) + const BreakpointId id =response.cookie.toInt(); + // This should only be the requested state. + QTC_ASSERT(!breakHandler()->isEnabled(id), /* Prevent later recursion */); + breakHandler()->ackEnabled(id); +} + +void GdbEngine::handleBreakEnable(const GdbResponse &response) +{ + QTC_ASSERT(response.resultClass == GdbResultDone, /**/) + const BreakpointId id = response.cookie.toInt(); + // This should only be the "wish" state. + QTC_ASSERT(breakHandler()->isEnabled(id), /* Prevent later recursion */); + breakHandler()->ackEnabled(id); } void GdbEngine::handleBreakIgnore(const GdbResponse &response) @@ -2314,35 +2325,30 @@ void GdbEngine::handleBreakIgnore(const GdbResponse &response) // 29^done // // gdb 6.3 does not produce any console output - if (response.resultClass == GdbResultDone) { - QString msg = _(response.data.findChild("consolestreamoutput").data()); - //if (msg.contains(__("Will stop next time breakpoint"))) { - // data->bpIgnoreCount = _("0"); - //} else if (msg.contains(__("Will ignore next"))) { - // data->bpIgnoreCount = data->ignoreCount; - //} - // FIXME: this assumes it is doing the right thing... - breakHandler()->ackIgnoreCount(BreakpointId(response.cookie.toInt())); - } + QTC_ASSERT(response.resultClass == GdbResultDone, /**/) + QString msg = _(response.data.findChild("consolestreamoutput").data()); + //if (msg.contains(__("Will stop next time breakpoint"))) + // data->bpIgnoreCount = _("0"); + //else if (msg.contains(__("Will ignore next"))) + // data->bpIgnoreCount = data->ignoreCount; + // FIXME: this assumes it is doing the right thing... + BreakpointId id(response.cookie.toInt()); + // This should only be the "wish" state. + QTC_ASSERT(!breakHandler()->isEnabled(id), /* prevent later recursion */); + breakHandler()->ackEnabled(id); } void GdbEngine::handleBreakCondition(const GdbResponse &response) { - const int id = response.cookie.toInt(); - if (response.resultClass == GdbResultDone) { - // We just assume it was successful. Otherwise we had to parse - // the output stream data. - //qDebug() << "HANDLE BREAK CONDITION" << bpNumber << data->condition; - breakHandler()->ackCondition(id); - } else { - QByteArray msg = response.data.findChild("msg").data(); - // happens on Mac - if (1 || msg.startsWith("Error parsing breakpoint condition. " - " Will try again when we hit the breakpoint.")) { - //qDebug() << "ERROR BREAK CONDITION" << bpNumber << data->condition; - breakHandler()->ackCondition(id); - } - } + QTC_ASSERT(response.resultClass == GdbResultDone, /**/) + const BreakpointId id = response.cookie.toInt(); + // We just assume it was successful. Otherwise we had to parse + // the output stream data. + // The following happens on Mac: + // QByteArray msg = response.data.findChild("msg").data(); + // if (1 || msg.startsWith("Error parsing breakpoint condition. " + // " Will try again when we hit the breakpoint.")) { + breakHandler()->ackCondition(id); } void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointId id) @@ -2607,9 +2613,63 @@ void GdbEngine::insertBreakpoint(BreakpointId id) CB(handleBreakInsert1), id); } -void GdbEngine::changeBreakpoint(BreakpointId) +void GdbEngine::changeBreakpoint(BreakpointId id) { - QTC_ASSERT(false, return); + const BreakpointData *data0 = breakHandler()->breakpointById(id); + QTC_ASSERT(data0, return); + const BreakpointData &data = *data0; + const BreakpointResponse &response = breakHandler()->response(id); + QTC_ASSERT(response.bpNumber > 0, return); + const QByteArray bpnr = QByteArray::number(response.bpNumber); + + if (data.condition() != response.bpCondition + && !data.conditionsMatch(response.bpCondition)) { + // Update conditions if needed. + postCommand("condition " + bpnr + ' ' + data.condition(), + NeedsStop | RebuildBreakpointModel, + CB(handleBreakCondition), id); + } + if (data.ignoreCount() != response.bpIgnoreCount) { + // Update ignorecount if needed. + postCommand("ignore " + bpnr + ' ' + QByteArray::number(data.ignoreCount()), + NeedsStop | RebuildBreakpointModel, + CB(handleBreakIgnore), id); + } + if (!data.isEnabled() && response.bpEnabled) { + postCommand("-break-disable " + bpnr, + NeedsStop | RebuildBreakpointModel, + CB(handleBreakDisable), id); + } + if (data.isEnabled() && !response.bpEnabled) { + postCommand("-break-enable " + bpnr, + NeedsStop | RebuildBreakpointModel, + CB(handleBreakEnable), id); + } +/* + if (data.threadSpec() != response.bpThreadSpec) + // The only way to change this seems to be to re-set the bp completely. + //qDebug() << "FIXME: THREAD: " << data.threadSpec << response.bpThreadSpec; + FIXME + data.setThreadSpec.clear(); + postCommand("-break-delete " + bpnr, + NeedsStop | RebuildBreakpointModel); + sendInsertBreakpoint(index); + continue; + } +*/ + +/* + if (data->bpAddress && data->bpCorrectedLineNumber == 0) { + // Prevent endless loop. + data->bpCorrectedLineNumber = -1; + if (debuggerCore()->boolSetting(AdjustBreakpointLocations)) { + postCommand( + "info line *0x" + QByteArray::number(data->bpAddress, 16), + NeedsStop | RebuildBreakpointModel, + CB(handleInfoLine), id) + } + } +*/ } void GdbEngine::removeBreakpoint(BreakpointId id) diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index ce932356a2f..49ef60c3686 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -354,6 +354,7 @@ private: ////////// View & Data Stuff ////////// void handleBreakList(const GdbMi &table); void handleBreakIgnore(const GdbResponse &response); void handleBreakDisable(const GdbResponse &response); + void handleBreakEnable(const GdbResponse &response); void handleBreakInsert1(const GdbResponse &response); void handleBreakInsert2(const GdbResponse &response); void handleBreakCondition(const GdbResponse &response);