forked from qt-creator/qt-creator
debugger: work on breakpoint enabling/disabling in gdb engine
This commit is contained in:
@@ -489,7 +489,9 @@ 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)) \
|
||||||
|
return; \
|
||||||
|
it->state = BreakpointChangeRequested; \
|
||||||
scheduleSynchronization(); \
|
scheduleSynchronization(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|||||||
@@ -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...
|
||||||
breakHandler()->ackIgnoreCount(BreakpointId(response.cookie.toInt()));
|
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)
|
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:
|
||||||
|
// 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);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user