debugger: rewrite parser for cli sub-breakpoint notifications

Change-Id: I971a2af2534bc650e8c604a5c2dc2e1846dbb045
Reviewed-on: http://codereview.qt.nokia.com/592
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
hjk
2011-06-21 16:45:23 +02:00
committed by hjk
parent a7d8f34679
commit 41df1fb2d3
10 changed files with 206 additions and 104 deletions

View File

@@ -224,7 +224,7 @@ BreakpointId BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needl
const BreakpointParameters &data = it->data; const BreakpointParameters &data = it->data;
const BreakpointResponse &response = it->response; const BreakpointResponse &response = it->response;
//qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString(); //qDebug() << "COMPARING " << data.toString() << " WITH " << needle.toString();
if (response.number && response.number == needle.number) if (response.id.isValid() && response.id.majorPart() == needle.id.majorPart())
return id; return id;
if (isSimilarTo(data, needle)) if (isSimilarTo(data, needle))
@@ -237,7 +237,7 @@ BreakpointId BreakHandler::findBreakpointByNumber(int bpNumber) const
{ {
ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd(); ConstIterator it = m_storage.constBegin(), et = m_storage.constEnd();
for ( ; it != et; ++it) for ( ; it != et; ++it)
if (it->response.number == bpNumber) if (it->response.id.majorPart() == bpNumber)
return it.key(); return it.key();
return BreakpointId(); return BreakpointId();
} }
@@ -577,16 +577,18 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
case 1: case 1:
if (role == Qt::DisplayRole) if (role == Qt::DisplayRole)
return res.functionName; return res.functionName;
case 4:
if (role == Qt::DisplayRole)
if (res.address)
return QString::fromAscii("0x%1").arg(res.address, 0, 16);
} }
return QVariant(); return QVariant();
} }
switch (mi.column()) { switch (mi.column()) {
case 0: case 0:
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole)
return id.toString(); return id.toString();
//return QString("%1 - %2").arg(id).arg(response.number);
}
if (role == Qt::DecorationRole) if (role == Qt::DecorationRole)
return it->icon(); return it->icon();
break; break;
@@ -644,16 +646,10 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
break; break;
case 4: case 4:
if (role == Qt::DisplayRole) { if (role == Qt::DisplayRole) {
QString displayValue;
const quint64 address = orig ? data.address : response.address; const quint64 address = orig ? data.address : response.address;
if (address) if (address)
displayValue += QString::fromAscii("0x%1").arg(address, 0, 16); return QString::fromAscii("0x%1").arg(address, 0, 16);
if (0 && !response.extra.isEmpty()) { return QVariant();
if (!displayValue.isEmpty())
displayValue += QLatin1Char(' ');
displayValue += QString::fromAscii(response.extra);
}
return displayValue;
} }
break; break;
case 5: case 5:
@@ -1060,16 +1056,34 @@ int BreakHandler::indexOf(BreakpointId id) const
return -1; return -1;
} }
void BreakHandler::appendSubBreakpoint(BreakpointId id, const BreakpointResponse &data) void BreakHandler::insertSubBreakpoint(const BreakpointResponse &data)
{ {
Iterator it = m_storage.find(id); BreakpointId id = data.id;
QTC_ASSERT(id.isMinor(), return);
BreakpointId majorId = id.parent();
Iterator it = m_storage.find(majorId);
QTC_ASSERT(it != m_storage.end(), return); QTC_ASSERT(it != m_storage.end(), return);
int row = indexOf(id); int row = indexOf(majorId);
QTC_ASSERT(row != -1, return); QTC_ASSERT(row != -1, return);
int minorPart = id.minorPart();
int pos = -1;
for (int i = 0; i != it->subItems.size(); ++i) {
if (it->subItems.at(i).id.minorPart() == minorPart) {
pos = i;
break;
}
}
if (pos == -1) {
// This is a new sub-breakpoint.
QModelIndex idx = createIndex(row, 0, id.toInternalId()); QModelIndex idx = createIndex(row, 0, id.toInternalId());
beginInsertRows(idx, it->subItems.size(), it->subItems.size()); beginInsertRows(idx, it->subItems.size(), it->subItems.size());
it->subItems.append(data); it->subItems.append(data);
endInsertRows(); endInsertRows();
} else {
// This modifies an existing sub-breakpoint.
it->subItems[pos] = data;
layoutChanged();
}
} }
void BreakHandler::saveSessionData() void BreakHandler::saveSessionData()
@@ -1364,7 +1378,7 @@ QString BreakHandler::BreakpointItem::toToolTip() const
} }
if (!response.pending) { if (!response.pending) {
str << "<tr><td>" << tr("Breakpoint Number:") str << "<tr><td>" << tr("Breakpoint Number:")
<< "</td><td>" << response.number << "</td></tr>"; << "</td><td>" << response.id.toString() << "</td></tr>";
} }
str << "<tr><td>" << tr("Breakpoint Type:") str << "<tr><td>" << tr("Breakpoint Type:")
<< "</td><td>" << typeToString(data.type) << "</td></tr>"; << "</td><td>" << typeToString(data.type) << "</td></tr>";
@@ -1380,7 +1394,7 @@ QString BreakHandler::BreakpointItem::toToolTip() const
<< "</th><th>" << tr("Requested") << "</th><th>" << tr("Requested")
<< "</th><th>" << tr("Obtained") << "</th></tr>" << "</th><th>" << tr("Obtained") << "</th></tr>"
<< "<tr><td>" << tr("Internal Number:") << "<tr><td>" << tr("Internal Number:")
<< "</td><td>&mdash;</td><td>" << response.number << "</td></tr>"; << "</td><td>&mdash;</td><td>" << response.id.toString() << "</td></tr>";
if (data.type == BreakpointByFunction) { if (data.type == BreakpointByFunction) {
str << "<tr><td>" << tr("Function Name:") str << "<tr><td>" << tr("Function Name:")
<< "</td><td>" << data.functionName << "</td><td>" << data.functionName
@@ -1413,12 +1427,8 @@ QString BreakHandler::BreakpointItem::toToolTip() const
str << "</td></tr>"; str << "</td></tr>";
if (response.multiple) { if (response.multiple) {
str << "<tr><td>" << tr("Multiple Addresses:") str << "<tr><td>" << tr("Multiple Addresses:")
<< "</td><td>"; << "</td><td>"
foreach (quint64 address, response.addresses) { << "</td></tr>";
formatAddress(str, address);
str << " ";
}
str << "</td></tr>";
} }
if (!data.command.isEmpty() || !response.command.isEmpty()) { if (!data.command.isEmpty() || !response.command.isEmpty()) {
str << "<tr><td>" << tr("Command:") str << "<tr><td>" << tr("Command:")

View File

@@ -70,7 +70,7 @@ 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 appendSubBreakpoint(BreakpointId id, const BreakpointResponse &data); void insertSubBreakpoint(const BreakpointResponse &data);
BreakpointIds allBreakpointIds() const; BreakpointIds allBreakpointIds() const;
BreakpointIds engineBreakpointIds(DebuggerEngine *engine) const; BreakpointIds engineBreakpointIds(DebuggerEngine *engine) const;

View File

@@ -46,12 +46,36 @@ namespace Internal {
// //
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
BreakpointId::BreakpointId(const QByteArray &ba)
{
int pos = ba.indexOf('.');
if (pos == -1) {
m_majorPart = ba.toInt();
m_minorPart = 0;
} else {
m_majorPart = ba.left(pos).toInt();
m_minorPart = ba.mid(pos + 1).toInt();
}
}
QDebug operator<<(QDebug d, const BreakpointId &id) QDebug operator<<(QDebug d, const BreakpointId &id)
{ {
d << qPrintable(id.toString()); d << qPrintable(id.toString());
return d; return d;
} }
QByteArray BreakpointId::toByteArray() const
{
if (!isValid())
return "<invalid bkpt>";
QByteArray ba = QByteArray::number(m_majorPart);
if (isMinor()) {
ba.append('.');
ba.append(QByteArray::number(m_minorPart));
}
return ba;
}
QString BreakpointId::toString() const QString BreakpointId::toString() const
{ {
if (!isValid()) if (!isValid())
@@ -199,9 +223,8 @@ QString BreakpointParameters::toString() const
BreakpointResponse::BreakpointResponse() BreakpointResponse::BreakpointResponse()
{ {
number = 0;
subNumber = 0;
pending = true; pending = true;
hitCount = 0;
multiple = false; multiple = false;
correctedLineNumber = 0; correctedLineNumber = 0;
} }
@@ -210,9 +233,7 @@ QString BreakpointResponse::toString() const
{ {
QString result = BreakpointParameters::toString(); QString result = BreakpointParameters::toString();
QTextStream ts(&result); QTextStream ts(&result);
ts << " Number: " << number; ts << " Number: " << id.toString();
if (subNumber)
ts << "." << subNumber;
if (pending) if (pending)
ts << " [pending]"; ts << " [pending]";
if (!fullName.isEmpty()) if (!fullName.isEmpty())
@@ -225,6 +246,7 @@ QString BreakpointResponse::toString() const
ts << " Extra: " << extra; ts << " Extra: " << extra;
if (correctedLineNumber) if (correctedLineNumber)
ts << " CorrectedLineNumber: " << correctedLineNumber; ts << " CorrectedLineNumber: " << correctedLineNumber;
ts << " Hit: " << hitCount << " times";
ts << ' '; ts << ' ';
return result + BreakpointParameters::toString(); return result + BreakpointParameters::toString();
} }
@@ -232,12 +254,12 @@ QString BreakpointResponse::toString() const
void BreakpointResponse::fromParameters(const BreakpointParameters &p) void BreakpointResponse::fromParameters(const BreakpointParameters &p)
{ {
BreakpointParameters::operator=(p); BreakpointParameters::operator=(p);
number = 0; id = BreakpointId();
subNumber = 0;
fullName.clear(); fullName.clear();
multiple = false; multiple = false;
extra.clear(); extra.clear();
correctedLineNumber = 0; correctedLineNumber = 0;
hitCount = 0;
} }
} // namespace Internal } // namespace Internal

View File

@@ -47,6 +47,7 @@ public:
BreakpointId() { m_majorPart = m_minorPart = 0; } BreakpointId() { m_majorPart = m_minorPart = 0; }
explicit BreakpointId(quint16 ma) { m_majorPart = ma; m_minorPart = 0; } explicit BreakpointId(quint16 ma) { m_majorPart = ma; m_minorPart = 0; }
BreakpointId(quint16 ma, quint16 mi) { m_majorPart = ma; m_minorPart = mi; } BreakpointId(quint16 ma, quint16 mi) { m_majorPart = ma; m_minorPart = mi; }
explicit BreakpointId(const QByteArray &ba); // "21.2"
bool isValid() const { return m_majorPart != 0; } bool isValid() const { return m_majorPart != 0; }
bool isMajor() const { return m_majorPart != 0 && m_minorPart == 0; } bool isMajor() const { return m_majorPart != 0 && m_minorPart == 0; }
@@ -54,6 +55,7 @@ public:
bool operator!() const { return !isValid(); } bool operator!() const { return !isValid(); }
operator const void*() const { return isValid() ? this : 0; } operator const void*() const { return isValid() ? this : 0; }
quint32 toInternalId() const { return m_majorPart | (m_minorPart << 16); } quint32 toInternalId() const { return m_majorPart | (m_minorPart << 16); }
QByteArray toByteArray() const;
QString toString() const; QString toString() const;
bool operator==(const BreakpointId &id) const bool operator==(const BreakpointId &id) const
{ return m_majorPart == id.m_majorPart && m_minorPart == id.m_minorPart; } { return m_majorPart == id.m_majorPart && m_minorPart == id.m_minorPart; }
@@ -194,13 +196,12 @@ public:
public: public:
void fromParameters(const BreakpointParameters &p); void fromParameters(const BreakpointParameters &p);
int number; //!< Breakpoint number assigned by the debugger engine. BreakpointId id; //!< Breakpoint number assigned by the debugger engine.
int subNumber; //!< Breakpoint sub-number assigned by the engine.
bool pending; //!< Breakpoint not fully resolved. bool pending; //!< Breakpoint not fully resolved.
int hitCount; //!< Number of times this has been hit.
QString fullName; //!< Full file name acknowledged by the debugger engine. QString fullName; //!< Full file name acknowledged by the debugger engine.
bool multiple; //!< Happens in constructors/gdb. bool multiple; //!< Happens in constructors/gdb.
QByteArray extra; //!< gdb: <PENDING>, <MULTIPLE> QByteArray extra; //!< gdb: <PENDING>, <MULTIPLE>
QList<quint64> addresses;//!< Extra addresses for templated code.
int correctedLineNumber; //!< Line number as seen by gdb. int correctedLineNumber; //!< Line number as seen by gdb.
}; };

View File

@@ -1864,7 +1864,7 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason,
if (id && breakHandler()->engineBreakpointIds(this).contains(id)) { if (id && breakHandler()->engineBreakpointIds(this).contains(id)) {
const BreakpointResponse parameters = breakHandler()->response(id); const BreakpointResponse parameters = breakHandler()->response(id);
// Trace point? Just report. // Trace point? Just report.
number = parameters.number; number = parameters.id.majorPart();
if (parameters.tracepoint) { if (parameters.tracepoint) {
*message = msgTracePointTriggered(id, number, QString::number(threadId)); *message = msgTracePointTriggered(id, number, QString::number(threadId));
return StopReportLog|StopIgnoreContinue; return StopReportLog|StopIgnoreContinue;
@@ -2786,7 +2786,7 @@ void CdbEngine::handleWidgetAt(const CdbExtensionCommandPtr &reply)
static inline void formatCdbBreakPointResponse(BreakpointId id, const BreakpointResponse &r, static inline void formatCdbBreakPointResponse(BreakpointId id, const BreakpointResponse &r,
QTextStream &str) QTextStream &str)
{ {
str << "Obtained breakpoint " << id << " (#" << r.number << ')'; str << "Obtained breakpoint " << id << " (#" << r.id.majorPart() << ')';
if (r.pending) { if (r.pending) {
str << ", pending"; str << ", pending";
} else { } else {
@@ -2840,7 +2840,7 @@ void CdbEngine::handleBreakPoints(const GdbMi &value)
if (it != m_pendingBreakpointMap.end()) { if (it != m_pendingBreakpointMap.end()) {
// Complete the response and set on handler. // Complete the response and set on handler.
BreakpointResponse &currentResponse = it.value(); BreakpointResponse &currentResponse = it.value();
currentResponse.number = reportedResponse.number; currentResponse.id = reportedResponse.id;
currentResponse.address = reportedResponse.address; currentResponse.address = reportedResponse.address;
currentResponse.module = reportedResponse.module; currentResponse.module = reportedResponse.module;
currentResponse.pending = reportedResponse.pending; currentResponse.pending = reportedResponse.pending;

View File

@@ -302,9 +302,11 @@ BreakpointId parseBreakPoint(const GdbMi &gdbmi, BreakpointResponse *r,
QString *expression /* = 0 */) QString *expression /* = 0 */)
{ {
BreakpointId id = BreakpointId(-1); BreakpointId id = BreakpointId(-1);
gdbmiChildToInt(gdbmi, "number", &(r->number)); int majorPart = 0;
gdbmiChildToInt(gdbmi, "number", &majorPart);
gdbmiChildToBool(gdbmi, "enabled", &(r->enabled)); gdbmiChildToBool(gdbmi, "enabled", &(r->enabled));
gdbmiChildToBool(gdbmi, "deferred", &(r->pending)); gdbmiChildToBool(gdbmi, "deferred", &(r->pending));
r->id = BreakpointId(majorPart);
const GdbMi idG = gdbmi.findChild("id"); const GdbMi idG = gdbmi.findChild("id");
if (idG.isValid()) { // Might not be valid if there is not id if (idG.isValid()) { // Might not be valid if there is not id
bool ok; bool ok;

View File

@@ -147,7 +147,7 @@ QDataStream &operator>>(QDataStream &stream, StackFrames &frames)
QDataStream &operator<<(QDataStream &stream, const BreakpointResponse &s) QDataStream &operator<<(QDataStream &stream, const BreakpointResponse &s)
{ {
stream << s.number; stream << s.id.majorPart();
stream << s.condition; stream << s.condition;
stream << s.ignoreCount; stream << s.ignoreCount;
stream << s.fileName; stream << s.fileName;
@@ -157,12 +157,15 @@ QDataStream &operator<<(QDataStream &stream, const BreakpointResponse &s)
stream << s.threadSpec; stream << s.threadSpec;
stream << s.functionName; stream << s.functionName;
stream << s.address; stream << s.address;
stream << s.hitCount;
return stream; return stream;
} }
QDataStream &operator>>(QDataStream &stream, BreakpointResponse &s) QDataStream &operator>>(QDataStream &stream, BreakpointResponse &s)
{ {
stream >> s.number; int majorPart;
stream >> majorPart;
s.id = BreakpointId(majorPart);
stream >> s.condition; stream >> s.condition;
stream >> s.ignoreCount; stream >> s.ignoreCount;
stream >> s.fileName; stream >> s.fileName;
@@ -172,6 +175,7 @@ QDataStream &operator>>(QDataStream &stream, BreakpointResponse &s)
stream >> s.threadSpec; stream >> s.threadSpec;
stream >> s.functionName; stream >> s.functionName;
stream >> s.address; stream >> s.address;
stream >> s.hitCount;
return stream; return stream;
} }

View File

@@ -498,16 +498,14 @@ void GdbEngine::handleResponse(const QByteArray &buff)
BreakpointResponse br; BreakpointResponse br;
foreach (const GdbMi &bkpt, result.children()) { foreach (const GdbMi &bkpt, result.children()) {
const QByteArray nr = bkpt.findChild("number").data(); const QByteArray nr = bkpt.findChild("number").data();
if (nr.contains(".")) { if (nr.contains('.')) {
// A sub-breakpoint. // A sub-breakpoint.
int subNumber = nr.mid(nr.indexOf('.') + 1).toInt();
BreakpointResponse sub; BreakpointResponse sub;
updateResponse(sub, bkpt); updateResponse(sub, bkpt);
sub.number = br.number; sub.id = BreakpointId(nr);
sub.type = br.type; sub.type = br.type;
sub.subNumber = subNumber;
sub.extra.clear(); sub.extra.clear();
handler->appendSubBreakpoint(id, sub); handler->insertSubBreakpoint(sub);
} else { } else {
// A primary breakpoint. // A primary breakpoint.
id = handler->findBreakpointByNumber(nr.toInt()); id = handler->findBreakpointByNumber(nr.toInt());
@@ -515,7 +513,7 @@ void GdbEngine::handleResponse(const QByteArray &buff)
updateResponse(br, bkpt); updateResponse(br, bkpt);
} }
} }
if (!isQmlStepBreakpoint(br.number)) { if (!isQmlStepBreakpoint(br.id.majorPart())) {
handler->setResponse(id, br); handler->setResponse(id, br);
attemptAdjustBreakpointLocation(id); attemptAdjustBreakpointLocation(id);
} }
@@ -2291,7 +2289,7 @@ void GdbEngine::updateResponse(BreakpointResponse &response, const GdbMi &bkpt)
QByteArray file, fullName; QByteArray file, fullName;
foreach (const GdbMi &child, bkpt.children()) { foreach (const GdbMi &child, bkpt.children()) {
if (child.hasName("number")) { if (child.hasName("number")) {
response.number = child.data().toInt(); response.id = BreakpointId(child.data());
} else if (child.hasName("func")) { } else if (child.hasName("func")) {
response.functionName = _(child.data()); response.functionName = _(child.data());
} else if (child.hasName("addr")) { } else if (child.hasName("addr")) {
@@ -2419,7 +2417,7 @@ void GdbEngine::handleWatchInsert(const GdbResponse &response)
if (wpt.isValid()) { if (wpt.isValid()) {
// Mac yields: // Mac yields:
//>32^done,wpt={number="4",exp="*4355182176"} //>32^done,wpt={number="4",exp="*4355182176"}
br.number = wpt.findChild("number").data().toInt(); br.id = BreakpointId(wpt.findChild("number").data());
QByteArray exp = wpt.findChild("exp").data(); QByteArray exp = wpt.findChild("exp").data();
if (exp.startsWith('*')) if (exp.startsWith('*'))
br.address = exp.mid(1).toULongLong(0, 0); br.address = exp.mid(1).toULongLong(0, 0);
@@ -2432,7 +2430,7 @@ void GdbEngine::handleWatchInsert(const GdbResponse &response)
const int end = ba.indexOf(':'); const int end = ba.indexOf(':');
const int begin = ba.lastIndexOf(' ', end) + 1; const int begin = ba.lastIndexOf(' ', end) + 1;
const QByteArray address = ba.mid(end + 2).trimmed(); const QByteArray address = ba.mid(end + 2).trimmed();
br.number = ba.mid(begin, end - begin).toInt(); br.id = BreakpointId(ba.mid(begin, end - begin));
if (address.startsWith('*')) if (address.startsWith('*'))
br.address = address.mid(1).toULongLong(0, 0); br.address = address.mid(1).toULongLong(0, 0);
handler->setResponse(id, br); handler->setResponse(id, br);
@@ -2489,8 +2487,8 @@ void GdbEngine::handleBreakInsert1(const GdbResponse &response)
} }
br = handler->response(id); br = handler->response(id);
attemptAdjustBreakpointLocation(id); attemptAdjustBreakpointLocation(id);
if (br.multiple && br.addresses.isEmpty()) if (br.multiple)
postCommand("info break " + QByteArray::number(br.number), postCommand("info break " + QByteArray::number(br.id.majorPart()),
NeedsStop, CB(handleBreakListMultiple), QVariant(id)); NeedsStop, CB(handleBreakListMultiple), QVariant(id));
} else if (response.data.findChild("msg").data().contains("Unknown option")) { } else if (response.data.findChild("msg").data().contains("Unknown option")) {
// Older version of gdb don't know the -a option to set tracepoints // Older version of gdb don't know the -a option to set tracepoints
@@ -2583,10 +2581,10 @@ void GdbEngine::handleBreakList(const GdbMi &table)
BreakHandler *handler = breakHandler(); BreakHandler *handler = breakHandler();
foreach (const GdbMi &bkpt, bkpts) { foreach (const GdbMi &bkpt, bkpts) {
BreakpointResponse needle; BreakpointResponse needle;
needle.number = bkpt.findChild("number").data().toInt(); needle.id = BreakpointId(bkpt.findChild("number").data());
if (isQmlStepBreakpoint2(needle.number)) if (isQmlStepBreakpoint2(needle.id.majorPart()))
continue; continue;
if (isQFatalBreakpoint(needle.number)) if (isQFatalBreakpoint(needle.id.majorPart()))
continue; continue;
BreakpointId id = handler->findSimilarBreakpoint(needle); BreakpointId id = handler->findSimilarBreakpoint(needle);
if (id.isValid()) { if (id.isValid()) {
@@ -2595,8 +2593,8 @@ void GdbEngine::handleBreakList(const GdbMi &table)
handler->setResponse(id, response); handler->setResponse(id, response);
attemptAdjustBreakpointLocation(id); attemptAdjustBreakpointLocation(id);
response = handler->response(id); response = handler->response(id);
if (response.multiple && response.addresses.isEmpty()) if (response.multiple)
postCommand("info break " + QByteArray::number(response.number), postCommand("info break " + response.id.toString().toLatin1(),
NeedsStop, CB(handleBreakListMultiple), NeedsStop, CB(handleBreakListMultiple),
QVariant::fromValue(id)); QVariant::fromValue(id));
} else { } else {
@@ -2720,43 +2718,108 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointId id)
// 2.1 y 0x0040168e in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7 // 2.1 y 0x0040168e in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7
// 2.2 y 0x00401792 in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7 // 2.2 y 0x00401792 in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7
// tested in ../../../tests/auto/debugger/ // "Num Type Disp Enb Address What
QRegExp re(_("MULTIPLE.*(0x[0-9a-f]+) in (.*)\\s+at (.*):([\\d]+)([^\\d]|$)")); // 3 breakpoint keep y <MULTIPLE> \n"
re.setMinimal(true); // 3.1 y 0x0806094e in Vector<int>::Vector(int) at simple.cpp:141
// 3.2 y 0x08060994 in Vector<float>::Vector(int) at simple.cpp:141
// 3.3 y 0x080609da in Vector<double>::Vector(int) at simple.cpp:141
// 3.4 y 0x08060a1d in Vector<char>::Vector(int) at simple.cpp:141
BreakpointResponse response = breakHandler()->response(id); BreakHandler *handler = breakHandler();
response.fileName = _("<MULTIPLE>"); BreakpointResponse response = handler->response(id);
int posMultiple = output.indexOf(_("<MULTIPLE>"));
if (posMultiple != -1) {
QByteArray data = output.toUtf8();
data.replace('\n', ' ');
data.replace(" ", " ");
data.replace(" ", " ");
data.replace(" ", " ");
int majorPart = 0;
int minorPart = 0;
int hitCount = 0;
bool hitCountComing = false;
bool functionComing = false;
bool locationComing = false;
QByteArray location;
QByteArray function;
qulonglong address;
foreach (const QByteArray &part, data.split(' ')) {
if (part.isEmpty())
continue;
//qDebug() << "PART: " << part;
if (majorPart == 0) {
majorPart = part.toInt();
if (majorPart > 0)
continue;
}
if (part == "hit") {
hitCountComing = true;
continue;
}
if (hitCountComing) {
hitCountComing = false;
hitCount = part.toInt();
continue;
}
if (part == "at") {
locationComing = true;
continue;
}
if (locationComing) {
locationComing = false;
location = part;
continue;
}
if (part == "in") {
functionComing = true;
continue;
}
if (functionComing) {
functionComing = false;
function = part;
continue;
}
if (part.startsWith("0x")) {
address = part.toInt(0, 0);
continue;
}
if (part.size() >= 3 && part.count('.') == 1) {
BreakpointId subId(part);
int tmpMajor = subId.majorPart();
int tmpMinor = subId.minorPart();
if (tmpMajor == majorPart) {
if (minorPart) {
// Commit what we had before.
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.id = subId;
sub.type = response.type;
sub.address = address;
sub.extra.clear();
handler->insertSubBreakpoint(sub);
location.clear();
function.clear();
address = 0;
}
QString requestedFileName = breakHandler()->fileName(id); // Now start new.
minorPart = tmpMinor;
if (re.indexIn(output) != -1) { continue;
response.address = re.cap(1).toULongLong(0, 16);
response.functionName = re.cap(2).trimmed();
response.lineNumber = re.cap(4).toInt();
QString full = fullName(re.cap(3));
if (full.isEmpty()) {
// FIXME: This happens without UsePreciseBreakpoints regularly.
// We need to revive that "fill full name mapping bit by bit"
// approach of 1.2.x
//qDebug() << "NO FULL NAME KNOWN FOR" << re.cap(3);
full = cleanupFullName(re.cap(3));
if (full.isEmpty()) {
qDebug() << "FILE IS NOT RESOLVABLE" << re.cap(3);
full = re.cap(3); // FIXME: wrong, but prevents recursion
} }
} }
// The variable full could still contain, say "foo.cpp" when we asked }
// for "/full/path/to/foo.cpp". In this case, using the requested // Commit main data.
// instead of the acknowledged name makes sense as it will allow setting
// the marker in more cases.
if (requestedFileName.endsWith(full))
full = requestedFileName;
response.fileName = full;
} else { } else {
qDebug() << "COULD NOT MATCH " << re.pattern() << " AND " << output; qDebug() << "COULD NOT MATCH" << output;
response.number = -1; // <unavailable> response.id = BreakpointId(); // Unavailable.
} }
breakHandler()->setResponse(id, response); //handler->setResponse(id, response);
} }
void GdbEngine::handleInfoLine(const GdbResponse &response) void GdbEngine::handleInfoLine(const GdbResponse &response)
@@ -2874,9 +2937,8 @@ void GdbEngine::changeBreakpoint(BreakpointId id)
const BreakpointParameters &data = handler->breakpointData(id); const BreakpointParameters &data = handler->breakpointData(id);
QTC_ASSERT(data.type != UnknownType, return); QTC_ASSERT(data.type != UnknownType, return);
const BreakpointResponse &response = handler->response(id); const BreakpointResponse &response = handler->response(id);
QTC_ASSERT(response.number > 0, return); QTC_ASSERT(response.id.isValid(), return);
const QByteArray bpnr = QByteArray::number(response.number); const QByteArray bpnr = response.id.toByteArray();
QTC_ASSERT(response.number > 0, return);
const BreakpointState state = handler->state(id); const BreakpointState state = handler->state(id);
if (state == BreakpointChangeRequested) if (state == BreakpointChangeRequested)
handler->notifyBreakpointChangeProceeding(id); handler->notifyBreakpointChangeProceeding(id);
@@ -2938,9 +3000,9 @@ void GdbEngine::removeBreakpoint(BreakpointId id)
QTC_ASSERT(handler->state(id) == BreakpointRemoveRequested, /**/); QTC_ASSERT(handler->state(id) == BreakpointRemoveRequested, /**/);
handler->notifyBreakpointRemoveProceeding(id); handler->notifyBreakpointRemoveProceeding(id);
BreakpointResponse br = handler->response(id); BreakpointResponse br = handler->response(id);
showMessage(_("DELETING BP %1 IN %2").arg(br.number) showMessage(_("DELETING BP %1 IN %2").arg(br.id.toString())
.arg(handler->fileName(id))); .arg(handler->fileName(id)));
postCommand("-break-delete " + QByteArray::number(br.number), postCommand("-break-delete " + br.id.toByteArray(),
NeedsStop | RebuildBreakpointModel); NeedsStop | RebuildBreakpointModel);
// Pretend it succeeds without waiting for response. Feels better. // Pretend it succeeds without waiting for response. Feels better.
// FIXME: Really? // FIXME: Really?

View File

@@ -365,7 +365,7 @@ void PdbEngine::handleBreakInsert(const PdbResponse &response)
QByteArray file = response.data.mid(pos1 + 4, pos2 - pos1 - 4); QByteArray file = response.data.mid(pos1 + 4, pos2 - pos1 - 4);
QByteArray line = response.data.mid(pos2 + 1); QByteArray line = response.data.mid(pos2 + 1);
BreakpointResponse br; BreakpointResponse br;
br.number = bpnr.toInt(); br.id = BreakpointId(bpnr);
br.fileName = _(file); br.fileName = _(file);
br.lineNumber = line.toInt(); br.lineNumber = line.toInt();
handler->setResponse(id, br); handler->setResponse(id, br);
@@ -377,9 +377,9 @@ void PdbEngine::removeBreakpoint(BreakpointId id)
QTC_ASSERT(handler->state(id) == BreakpointRemoveRequested, /**/); QTC_ASSERT(handler->state(id) == BreakpointRemoveRequested, /**/);
handler->notifyBreakpointRemoveProceeding(id); handler->notifyBreakpointRemoveProceeding(id);
BreakpointResponse br = handler->response(id); BreakpointResponse br = handler->response(id);
showMessage(_("DELETING BP %1 IN %2").arg(br.number) showMessage(_("DELETING BP %1 IN %2").arg(br.id.toString())
.arg(handler->fileName(id))); .arg(handler->fileName(id)));
postCommand("clear " + QByteArray::number(br.number)); postCommand("clear " + br.id.toByteArray());
// Pretend it succeeds without waiting for response. // Pretend it succeeds without waiting for response.
handler->notifyBreakpointRemoveOk(id); handler->notifyBreakpointRemoveOk(id);
} }

View File

@@ -131,7 +131,7 @@ Q_DECLARE_METATYPE(QMap<uint COMMA QStringList>)
// tests multiple breakpoints // tests multiple breakpoints
namespace multiple_breakpoints { namespace multibp {
template <typename T> class Vector template <typename T> class Vector
{ {
@@ -155,7 +155,8 @@ namespace multiple_breakpoints {
Vector<char> vc(10); Vector<char> vc(10);
return vi.size() + vf.size() + vd.size() + vc.size(); return vi.size() + vf.size() + vd.size() + vc.size();
} }
} // namespace multiple_breakpoints
} // namespace multibp
#if USE_PRIVATE #if USE_PRIVATE
@@ -2775,7 +2776,7 @@ int main(int argc, char *argv[])
{ {
qc41700::test(); qc41700::test();
qc42170::test(); qc42170::test();
multiple_breakpoints::test(); multibp::test();
test842(); test842();
test842(); test842();
test3611(); test3611();