From c4713f5ab229dcbb55eeabfc3dfb4cf3ba9d392a Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 24 Jun 2011 14:17:16 +0200 Subject: [PATCH] debugger: handle results of manual break commands Change-Id: I0ab8ad3ef3ddfe7c8d69fd163864875190698475 Reviewed-on: http://codereview.qt.nokia.com/744 Reviewed-by: Qt Sanity Bot Reviewed-by: hjk --- src/plugins/debugger/breakhandler.cpp | 60 +++++++++++++++++++++++--- src/plugins/debugger/breakhandler.h | 3 ++ src/plugins/debugger/breakpoint.cpp | 9 ++++ src/plugins/debugger/breakpoint.h | 1 + src/plugins/debugger/gdb/gdbengine.cpp | 35 ++++++++++++--- 5 files changed, 96 insertions(+), 12 deletions(-) diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 763b62b60a0..23b8cc8a7b5 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -990,6 +990,14 @@ void BreakHandler::notifyBreakpointNeedsReinsertion(BreakpointId id) it->state = BreakpointInsertRequested; } +void BreakHandler::removeAlienBreakpoint(BreakpointId id) +{ + Iterator it = m_storage.find(id); + BREAK_ASSERT(it != m_storage.end(), return); + it->state = BreakpointDead; + cleanupBreakpoint(id); +} + void BreakHandler::removeBreakpoint(BreakpointId id) { Iterator it = m_storage.find(id); @@ -1011,14 +1019,13 @@ void BreakHandler::removeBreakpoint(BreakpointId id) } } +// Ok to be not thread-safe. The order does not matter and only the gui +// produces authoritative ids. +static int currentId = 0; + void BreakHandler::appendBreakpoint(const BreakpointParameters &data) { QTC_ASSERT(data.type != UnknownType, return); - - // Ok to be not thread-safe. The order does not matter and only the gui - // produces authoritative ids. - static quint64 currentId = 0; - BreakpointId id(++currentId); BreakpointItem item; item.data = data; @@ -1036,6 +1043,35 @@ void BreakHandler::appendBreakpoint(const BreakpointParameters &data) scheduleSynchronization(); } +void BreakHandler::handleAlienBreakpoint(const BreakpointResponse &response, + DebuggerEngine *engine) +{ + if (response.id.isMinor()) { + insertSubBreakpoint(response); + } else { + BreakpointParameters data = response; + data.type = BreakpointByFileAndLine; + data.functionName.clear(); + + BreakpointId id(++currentId); + BreakpointItem item; + item.data = data; + item.response = response; + item.state = BreakpointInserted; + item.engine = engine; + + const int row = m_storage.size(); + beginInsertRows(QModelIndex(), row, row); + m_storage.insert(id, item); + endInsertRows(); + + layoutChanged(); + + updateMarker(id); + scheduleSynchronization(); + } +} + BreakpointId BreakHandler::at(int n) const { if (n < 0 || n >= m_storage.size()) @@ -1062,6 +1098,17 @@ void BreakHandler::insertSubBreakpoint(const BreakpointResponse &data) QTC_ASSERT(id.isMinor(), return); BreakpointId majorId = id.parent(); Iterator it = m_storage.find(majorId); + + if (it == m_storage.end()) { + qDebug() << "FAILED: " << id.toString() << majorId.toString(); + for (ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd(); + it != et; ++it) { + qDebug() << " ID: " << it->response.id.toString(); + qDebug() << " DATA: " << it->data.toString(); + qDebug() << " RESP: " << it->response.toString(); + } + } + QTC_ASSERT(it != m_storage.end(), return); int row = indexOf(majorId); QTC_ASSERT(row != -1, return); @@ -1094,6 +1141,7 @@ void BreakHandler::saveSessionData() void BreakHandler::loadSessionData() { m_storage.clear(); + reset(); loadBreakpoints(); } @@ -1103,7 +1151,7 @@ void BreakHandler::removeSessionData() for ( ; it != et; ++it) it->destroyMarker(); m_storage.clear(); - layoutChanged(); + reset(); } void BreakHandler::breakByFunction(const QString &functionName) diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 75d81e2bfd7..1207d550bd6 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -70,7 +70,10 @@ public: // The only way to add a new breakpoint. void appendBreakpoint(const BreakpointParameters &data); + void handleAlienBreakpoint(const BreakpointResponse &response, + DebuggerEngine *engine); void insertSubBreakpoint(const BreakpointResponse &data); + void removeAlienBreakpoint(BreakpointId id); BreakpointIds allBreakpointIds() const; BreakpointIds engineBreakpointIds(DebuggerEngine *engine) const; diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp index 64995dababd..b78f11f17d4 100644 --- a/src/plugins/debugger/breakpoint.cpp +++ b/src/plugins/debugger/breakpoint.cpp @@ -164,6 +164,15 @@ bool BreakpointParameters::conditionsMatch(const QByteArray &other) const return s1 == s2; } +void BreakpointParameters::setLocation(const QByteArray &location) +{ + if (location.size()) { + int pos = location.indexOf(':'); + lineNumber = location.mid(pos + 1).toInt(); + fileName = QString::fromUtf8(location.left(pos)); + } +} + QString BreakpointParameters::toString() const { QString result; diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index be196b6493a..06ed64edd6e 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -164,6 +164,7 @@ public: bool isBreakpoint() const { return !isWatchpoint() && !isTracepoint(); } bool isTracepoint() const { return tracepoint; } QString toString() const; + void setLocation(const QByteArray &location); // file.cpp:42 bool operator==(const BreakpointParameters &p) const { return equals(p); } bool operator!=(const BreakpointParameters &p) const { return !equals(p); } diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 7adbe9280c3..289a62ccf3c 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -518,6 +518,26 @@ void GdbEngine::handleResponse(const QByteArray &buff) attemptAdjustBreakpointLocation(id); } m_hasBreakpointNotifications = true; + } else if (asyncClass == "breakpoint-created") { + // "{bkpt={number="1",type="breakpoint",disp="del",enabled="y", + // addr="",pending="main",times="0", + //original-location="main"}}" + foreach (const GdbMi &bkpt, result.children()) { + QByteArray nr = bkpt.findChild("number").data(); + BreakpointResponse br; + updateResponse(br, bkpt); + br.id = BreakpointId(nr); + qDebug() << "NR: " << nr << " ID: " << br.id.toString(); + breakHandler()->handleAlienBreakpoint(br, this); + } + } else if (asyncClass == "breakpoint-deleted") { + // "breakpoint-deleted" "{id="1"}" + // New in FSF gdb since 2011-04-27. + BreakHandler *handler = breakHandler(); + QByteArray nr = result.findChild("id").data(); + BreakpointId id = handler->findBreakpointByNumber(nr.toInt()); + if (id.isValid()) + handler->removeAlienBreakpoint(id); } else { qDebug() << "IGNORED ASYNC OUTPUT" << asyncClass << result.toString(); @@ -838,7 +858,7 @@ void GdbEngine::flushQueuedCommands() while (!m_commandsToRunOnTemporaryBreak.isEmpty()) { GdbCommand cmd = m_commandsToRunOnTemporaryBreak.takeFirst(); showMessage(_("RUNNING QUEUED COMMAND " + cmd.command + ' ' - + cmd.callbackName)); + + (cmd.callbackName ? cmd.callbackName : ""))); flushCommand(cmd); } } @@ -2286,6 +2306,8 @@ void GdbEngine::updateResponse(BreakpointResponse &response, const GdbMi &bkpt) { QTC_ASSERT(bkpt.isValid(), return); + QByteArray originalLocation; + response.multiple = false; response.enabled = true; response.pending = false; @@ -2341,6 +2363,8 @@ void GdbEngine::updateResponse(BreakpointResponse &response, const GdbMi &bkpt) response.tracepoint = true; else if (!child.data().contains("reakpoint")) response.type = WatchpointAtAddress; + } else if (child.hasName("original-location")) { + originalLocation = child.data(); } // This field is not present. Contents needs to be parsed from // the plain "ignore" response. @@ -2361,6 +2385,9 @@ void GdbEngine::updateResponse(BreakpointResponse &response, const GdbMi &bkpt) } if (!name.isEmpty()) response.fileName = name; + + if (name.isEmpty()) + response.setLocation(originalLocation); } QString GdbEngine::breakLocation(const QString &file) const @@ -2797,11 +2824,7 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointId id) BreakpointResponse sub; sub.address = address; sub.functionName = QString::fromUtf8(function); - if (location.size()) { - int pos = location.indexOf(':'); - sub.lineNumber = location.mid(pos + 1).toInt(); - sub.fileName = QString::fromUtf8(location.left(pos)); - } + sub.setLocation(location); sub.id = subId; sub.type = response.type; sub.address = address;