forked from qt-creator/qt-creator
debugger: work on breakpoint enabling/disabling in gdb engine
This commit is contained in:
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user