debugger: handle results of manual break commands

Change-Id: I0ab8ad3ef3ddfe7c8d69fd163864875190698475
Reviewed-on: http://codereview.qt.nokia.com/744
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
hjk
2011-06-24 14:17:16 +02:00
committed by hjk
parent d17d0cb6e9
commit c4713f5ab2
5 changed files with 96 additions and 12 deletions

View File

@@ -990,6 +990,14 @@ void BreakHandler::notifyBreakpointNeedsReinsertion(BreakpointId id)
it->state = BreakpointInsertRequested; 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) void BreakHandler::removeBreakpoint(BreakpointId id)
{ {
Iterator it = m_storage.find(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) void BreakHandler::appendBreakpoint(const BreakpointParameters &data)
{ {
QTC_ASSERT(data.type != UnknownType, return); 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); BreakpointId id(++currentId);
BreakpointItem item; BreakpointItem item;
item.data = data; item.data = data;
@@ -1036,6 +1043,35 @@ void BreakHandler::appendBreakpoint(const BreakpointParameters &data)
scheduleSynchronization(); 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 BreakpointId BreakHandler::at(int n) const
{ {
if (n < 0 || n >= m_storage.size()) if (n < 0 || n >= m_storage.size())
@@ -1062,6 +1098,17 @@ void BreakHandler::insertSubBreakpoint(const BreakpointResponse &data)
QTC_ASSERT(id.isMinor(), return); QTC_ASSERT(id.isMinor(), return);
BreakpointId majorId = id.parent(); BreakpointId majorId = id.parent();
Iterator it = m_storage.find(majorId); 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); QTC_ASSERT(it != m_storage.end(), return);
int row = indexOf(majorId); int row = indexOf(majorId);
QTC_ASSERT(row != -1, return); QTC_ASSERT(row != -1, return);
@@ -1094,6 +1141,7 @@ void BreakHandler::saveSessionData()
void BreakHandler::loadSessionData() void BreakHandler::loadSessionData()
{ {
m_storage.clear(); m_storage.clear();
reset();
loadBreakpoints(); loadBreakpoints();
} }
@@ -1103,7 +1151,7 @@ void BreakHandler::removeSessionData()
for ( ; it != et; ++it) for ( ; it != et; ++it)
it->destroyMarker(); it->destroyMarker();
m_storage.clear(); m_storage.clear();
layoutChanged(); reset();
} }
void BreakHandler::breakByFunction(const QString &functionName) void BreakHandler::breakByFunction(const QString &functionName)

View File

@@ -70,7 +70,10 @@ public:
// The only way to add a new breakpoint. // The only way to add a new breakpoint.
void appendBreakpoint(const BreakpointParameters &data); void appendBreakpoint(const BreakpointParameters &data);
void handleAlienBreakpoint(const BreakpointResponse &response,
DebuggerEngine *engine);
void insertSubBreakpoint(const BreakpointResponse &data); void insertSubBreakpoint(const BreakpointResponse &data);
void removeAlienBreakpoint(BreakpointId id);
BreakpointIds allBreakpointIds() const; BreakpointIds allBreakpointIds() const;
BreakpointIds engineBreakpointIds(DebuggerEngine *engine) const; BreakpointIds engineBreakpointIds(DebuggerEngine *engine) const;

View File

@@ -164,6 +164,15 @@ bool BreakpointParameters::conditionsMatch(const QByteArray &other) const
return s1 == s2; 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 BreakpointParameters::toString() const
{ {
QString result; QString result;

View File

@@ -164,6 +164,7 @@ public:
bool isBreakpoint() const { return !isWatchpoint() && !isTracepoint(); } bool isBreakpoint() const { return !isWatchpoint() && !isTracepoint(); }
bool isTracepoint() const { return tracepoint; } bool isTracepoint() const { return tracepoint; }
QString toString() const; 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); }
bool operator!=(const BreakpointParameters &p) const { return !equals(p); } bool operator!=(const BreakpointParameters &p) const { return !equals(p); }

View File

@@ -518,6 +518,26 @@ void GdbEngine::handleResponse(const QByteArray &buff)
attemptAdjustBreakpointLocation(id); attemptAdjustBreakpointLocation(id);
} }
m_hasBreakpointNotifications = true; m_hasBreakpointNotifications = true;
} else if (asyncClass == "breakpoint-created") {
// "{bkpt={number="1",type="breakpoint",disp="del",enabled="y",
// addr="<PENDING>",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 { } else {
qDebug() << "IGNORED ASYNC OUTPUT" qDebug() << "IGNORED ASYNC OUTPUT"
<< asyncClass << result.toString(); << asyncClass << result.toString();
@@ -838,7 +858,7 @@ void GdbEngine::flushQueuedCommands()
while (!m_commandsToRunOnTemporaryBreak.isEmpty()) { while (!m_commandsToRunOnTemporaryBreak.isEmpty()) {
GdbCommand cmd = m_commandsToRunOnTemporaryBreak.takeFirst(); GdbCommand cmd = m_commandsToRunOnTemporaryBreak.takeFirst();
showMessage(_("RUNNING QUEUED COMMAND " + cmd.command + ' ' showMessage(_("RUNNING QUEUED COMMAND " + cmd.command + ' '
+ cmd.callbackName)); + (cmd.callbackName ? cmd.callbackName : "<unnamed callback>")));
flushCommand(cmd); flushCommand(cmd);
} }
} }
@@ -2286,6 +2306,8 @@ void GdbEngine::updateResponse(BreakpointResponse &response, const GdbMi &bkpt)
{ {
QTC_ASSERT(bkpt.isValid(), return); QTC_ASSERT(bkpt.isValid(), return);
QByteArray originalLocation;
response.multiple = false; response.multiple = false;
response.enabled = true; response.enabled = true;
response.pending = false; response.pending = false;
@@ -2341,6 +2363,8 @@ void GdbEngine::updateResponse(BreakpointResponse &response, const GdbMi &bkpt)
response.tracepoint = true; response.tracepoint = true;
else if (!child.data().contains("reakpoint")) else if (!child.data().contains("reakpoint"))
response.type = WatchpointAtAddress; response.type = WatchpointAtAddress;
} else if (child.hasName("original-location")) {
originalLocation = child.data();
} }
// This field is not present. Contents needs to be parsed from // This field is not present. Contents needs to be parsed from
// the plain "ignore" response. // the plain "ignore" response.
@@ -2361,6 +2385,9 @@ void GdbEngine::updateResponse(BreakpointResponse &response, const GdbMi &bkpt)
} }
if (!name.isEmpty()) if (!name.isEmpty())
response.fileName = name; response.fileName = name;
if (name.isEmpty())
response.setLocation(originalLocation);
} }
QString GdbEngine::breakLocation(const QString &file) const QString GdbEngine::breakLocation(const QString &file) const
@@ -2797,11 +2824,7 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointId id)
BreakpointResponse sub; BreakpointResponse sub;
sub.address = address; sub.address = address;
sub.functionName = QString::fromUtf8(function); sub.functionName = QString::fromUtf8(function);
if (location.size()) { sub.setLocation(location);
int pos = location.indexOf(':');
sub.lineNumber = location.mid(pos + 1).toInt();
sub.fileName = QString::fromUtf8(location.left(pos));
}
sub.id = subId; sub.id = subId;
sub.type = response.type; sub.type = response.type;
sub.address = address; sub.address = address;