debugger: work on breakpoint enabling/disabling in gdb engine

This commit is contained in:
hjk
2010-11-15 16:22:51 +01:00
parent a3923f8c24
commit 0b32820a48
6 changed files with 115 additions and 61 deletions

View File

@@ -489,8 +489,10 @@ void BreakHandler::setter(BreakpointId id, const type &value) \
Iterator it = m_storage.find(id); \ Iterator it = m_storage.find(id); \
QTC_ASSERT(it != m_storage.end(), \ QTC_ASSERT(it != m_storage.end(), \
qDebug() << "ID" << id << "NOT KNOWN"; return); \ qDebug() << "ID" << id << "NOT KNOWN"; return); \
if (it->data.setter(value)) \ if (!it->data.setter(value)) \
scheduleSynchronization(); \ return; \
it->state = BreakpointChangeRequested; \
scheduleSynchronization(); \
} }
#define PROPERTY(type, getter, setter) \ #define PROPERTY(type, getter, setter) \
@@ -524,6 +526,7 @@ void BreakHandler::setEnabled(BreakpointId id, bool on)
//qDebug() << "SET ENABLED: " << id << it->data.isEnabled() << on; //qDebug() << "SET ENABLED: " << id << it->data.isEnabled() << on;
if (it->data.setEnabled(on)) { if (it->data.setEnabled(on)) {
it->destroyMarker(); it->destroyMarker();
it->state = BreakpointChangeRequested;
updateMarker(id); updateMarker(id);
scheduleSynchronization(); scheduleSynchronization();
} }
@@ -579,6 +582,14 @@ void BreakHandler::ackIgnoreCount(BreakpointId id)
updateMarker(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 Qt::ItemFlags BreakHandler::flags(const QModelIndex &index) const
{ {
// switch (index.column()) { // switch (index.column()) {
@@ -825,10 +836,11 @@ void BreakHandler::cleanupBreakpoint(BreakpointId id)
layoutChanged(); layoutChanged();
} }
BreakpointResponse BreakHandler::response(BreakpointId id) const const BreakpointResponse &BreakHandler::response(BreakpointId id) const
{ {
static BreakpointResponse dummy;
ConstIterator it = m_storage.find(id); 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; return it->response;
} }
@@ -839,25 +851,6 @@ void BreakHandler::setResponse(BreakpointId id, const BreakpointResponse &data)
it->response = BreakpointResponse(data); it->response = BreakpointResponse(data);
updateMarker(id); 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() void BreakHandler::BreakpointItem::destroyMarker()
{ {

View File

@@ -124,13 +124,13 @@ public:
DebuggerEngine *engine(BreakpointId id) const; DebuggerEngine *engine(BreakpointId id) const;
void setEngine(BreakpointId id, DebuggerEngine *engine); void setEngine(BreakpointId id, DebuggerEngine *engine);
BreakpointResponse response(BreakpointId id) const; const BreakpointResponse &response(BreakpointId id) const;
void setResponse(BreakpointId id, const BreakpointResponse &data); void setResponse(BreakpointId id, const BreakpointResponse &data);
// Incorporate debugger feedback. No synchronization request needed. // Incorporate debugger feedback. No synchronization request needed.
// Return true if something changed.
void ackCondition(BreakpointId id); void ackCondition(BreakpointId id);
void ackIgnoreCount(BreakpointId id); void ackIgnoreCount(BreakpointId id);
void ackEnabled(BreakpointId id);
void notifyBreakpointInsertOk(BreakpointId id); void notifyBreakpointInsertOk(BreakpointId id);
void notifyBreakpointInsertFailed(BreakpointId id); void notifyBreakpointInsertFailed(BreakpointId id);

View File

@@ -124,13 +124,13 @@ bool BreakpointData::isLocatedAt(const QString &fileName, int lineNumber,
return lineNumber == line && fileNameMatch(fileName, m_markerFileName); 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. // Some versions of gdb "beautify" the passed condition.
QString s1 = m_condition; QByteArray s1 = m_condition;
s1.remove(QChar(' ')); s1.replace(' ', "");
QString s2 = other; QByteArray s2 = other;
s2.remove(QChar(' ')); s2.replace(' ', "");
return s1 == s2; return s1 == s2;
} }

View File

@@ -99,7 +99,7 @@ public:
bool isLocatedAt(const QString &fileName, int lineNumber, bool isLocatedAt(const QString &fileName, int lineNumber,
bool useMarkerPosition) const; bool useMarkerPosition) const;
bool conditionsMatch(const QString &other) const; bool conditionsMatch(const QByteArray &other) const;
QString functionName() const { return m_functionName; } QString functionName() const { return m_functionName; }
QString markerFileName() const { return m_markerFileName; } QString markerFileName() const { return m_markerFileName; }
QString fileName() const { return m_fileName; } QString fileName() const { return m_fileName; }

View File

@@ -2297,9 +2297,20 @@ void GdbEngine::handleBreakList(const GdbMi &table)
void GdbEngine::handleBreakDisable(const GdbResponse &response) void GdbEngine::handleBreakDisable(const GdbResponse &response)
{ {
if (response.resultClass == GdbResultDone) { QTC_ASSERT(response.resultClass == GdbResultDone, /**/)
breakHandler()->updateMarkers(); 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) void GdbEngine::handleBreakIgnore(const GdbResponse &response)
@@ -2314,35 +2325,30 @@ void GdbEngine::handleBreakIgnore(const GdbResponse &response)
// 29^done // 29^done
// //
// gdb 6.3 does not produce any console output // gdb 6.3 does not produce any console output
if (response.resultClass == GdbResultDone) { QTC_ASSERT(response.resultClass == GdbResultDone, /**/)
QString msg = _(response.data.findChild("consolestreamoutput").data()); QString msg = _(response.data.findChild("consolestreamoutput").data());
//if (msg.contains(__("Will stop next time breakpoint"))) { //if (msg.contains(__("Will stop next time breakpoint")))
// data->bpIgnoreCount = _("0"); // data->bpIgnoreCount = _("0");
//} else if (msg.contains(__("Will ignore next"))) { //else if (msg.contains(__("Will ignore next")))
// data->bpIgnoreCount = data->ignoreCount; // data->bpIgnoreCount = data->ignoreCount;
//} // FIXME: this assumes it is doing the right thing...
// FIXME: this assumes it is doing the right thing... BreakpointId id(response.cookie.toInt());
breakHandler()->ackIgnoreCount(BreakpointId(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) void GdbEngine::handleBreakCondition(const GdbResponse &response)
{ {
const int id = response.cookie.toInt(); QTC_ASSERT(response.resultClass == GdbResultDone, /**/)
if (response.resultClass == GdbResultDone) { const BreakpointId id = response.cookie.toInt();
// We just assume it was successful. Otherwise we had to parse // We just assume it was successful. Otherwise we had to parse
// the output stream data. // the output stream data.
//qDebug() << "HANDLE BREAK CONDITION" << bpNumber << data->condition; // The following happens on Mac:
breakHandler()->ackCondition(id); // QByteArray msg = response.data.findChild("msg").data();
} else { // if (1 || msg.startsWith("Error parsing breakpoint condition. "
QByteArray msg = response.data.findChild("msg").data(); // " Will try again when we hit the breakpoint.")) {
// happens on Mac breakHandler()->ackCondition(id);
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);
}
}
} }
void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointId id) void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointId id)
@@ -2607,9 +2613,63 @@ void GdbEngine::insertBreakpoint(BreakpointId id)
CB(handleBreakInsert1), 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) void GdbEngine::removeBreakpoint(BreakpointId id)

View File

@@ -354,6 +354,7 @@ private: ////////// View & Data Stuff //////////
void handleBreakList(const GdbMi &table); void handleBreakList(const GdbMi &table);
void handleBreakIgnore(const GdbResponse &response); void handleBreakIgnore(const GdbResponse &response);
void handleBreakDisable(const GdbResponse &response); void handleBreakDisable(const GdbResponse &response);
void handleBreakEnable(const GdbResponse &response);
void handleBreakInsert1(const GdbResponse &response); void handleBreakInsert1(const GdbResponse &response);
void handleBreakInsert2(const GdbResponse &response); void handleBreakInsert2(const GdbResponse &response);
void handleBreakCondition(const GdbResponse &response); void handleBreakCondition(const GdbResponse &response);