From 332889aec25d45ca65870ad7f87294465a0de9da Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Tue, 21 Sep 2010 14:26:45 +0200 Subject: [PATCH] Debugger: Sanitize Datatypes, part 1: Breakpoints. Make address a quint64, linnumber and ignoreCounts int. Reviewed-by: hjk --- src/plugins/debugger/breakhandler.cpp | 94 +++++++++++------ src/plugins/debugger/breakhandler.h | 5 +- src/plugins/debugger/breakpoint.cpp | 102 ++++++++++--------- src/plugins/debugger/breakpoint.h | 16 +-- src/plugins/debugger/breakwindow.cpp | 2 + src/plugins/debugger/cdb/cdbbreakpoint.cpp | 18 +--- src/plugins/debugger/debuggeragents.cpp | 14 +++ src/plugins/debugger/debuggeragents.h | 3 + src/plugins/debugger/debuggerengine.cpp | 26 +++-- src/plugins/debugger/gdb/gdbengine.cpp | 51 ++++++---- src/plugins/debugger/pdb/pdbengine.cpp | 6 +- src/plugins/debugger/qml/qmlengine.cpp | 2 +- src/plugins/debugger/script/scriptengine.cpp | 6 +- src/plugins/debugger/watchhandler.cpp | 6 +- 14 files changed, 206 insertions(+), 145 deletions(-) diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 9160dd22e0a..8b6762c6800 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -139,11 +139,11 @@ BreakpointData *BreakHandler::findBreakpointByNumber(int bpNumber) const return 0; } -int BreakHandler::findWatchPointIndexByAddress(const QByteArray &a) const +int BreakHandler::findWatchPointIndexByAddress(quint64 address) const { for (int index = size() - 1; index >= 0; --index) { BreakpointData *bd = at(index); - if (bd->type == BreakpointData::WatchpointType && bd->address == a) + if (bd->type == BreakpointData::WatchpointType && bd->address == address) return index; } return -1; @@ -151,8 +151,7 @@ int BreakHandler::findWatchPointIndexByAddress(const QByteArray &a) const bool BreakHandler::watchPointAt(quint64 address) const { - const QByteArray addressBA = QByteArray("0x") + QByteArray::number(address, 16); - return findWatchPointIndexByAddress(addressBA) != -1; + return findWatchPointIndexByAddress(address) != -1; } void BreakHandler::saveBreakpoints() @@ -170,16 +169,16 @@ void BreakHandler::saveBreakpoints() map.insert(_("type"), data->type); if (!data->fileName.isEmpty()) map.insert(_("filename"), data->fileName); - if (!data->lineNumber.isEmpty()) - map.insert(_("linenumber"), data->lineNumber); + if (data->lineNumber) + map.insert(_("linenumber"), QVariant(data->lineNumber)); if (!data->funcName.isEmpty()) map.insert(_("funcname"), data->funcName); - if (!data->address.isEmpty()) + if (data->address) map.insert(_("address"), data->address); if (!data->condition.isEmpty()) map.insert(_("condition"), data->condition); - if (!data->ignoreCount.isEmpty()) - map.insert(_("ignorecount"), data->ignoreCount); + if (data->ignoreCount) + map.insert(_("ignorecount"), QVariant(data->ignoreCount)); if (!data->threadSpec.isEmpty()) map.insert(_("threadspec"), data->threadSpec); if (!data->enabled) @@ -207,16 +206,16 @@ void BreakHandler::loadBreakpoints() data->fileName = v.toString(); v = map.value(_("linenumber")); if (v.isValid()) - data->lineNumber = v.toString().toLatin1(); + data->lineNumber = v.toString().toInt(); v = map.value(_("condition")); if (v.isValid()) data->condition = v.toString().toLatin1(); v = map.value(_("address")); if (v.isValid()) - data->address = v.toString().toLatin1(); + data->address = v.toString().toULongLong(); v = map.value(_("ignorecount")); if (v.isValid()) - data->ignoreCount = v.toString().toLatin1(); + data->ignoreCount = v.toString().toInt(); v = map.value(_("threadspec")); if (v.isValid()) data->threadSpec = v.toString().toLatin1(); @@ -233,7 +232,7 @@ void BreakHandler::loadBreakpoints() if (v.isValid()) data->type = BreakpointData::Type(v.toInt()); data->setMarkerFileName(data->fileName); - data->setMarkerLineNumber(data->lineNumber.toInt()); + data->setMarkerLineNumber(data->lineNumber); append(data); } //qDebug() << "LOADED BREAKPOINTS" << this << list.size(); @@ -302,7 +301,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const return data->condition; if (role == BreakpointIgnoreCountRole) - return data->ignoreCount; + return data->ignoreCount ? QVariant(data->ignoreCount) : QVariant(QString()); if (role == BreakpointThreadSpecRole) return data->threadSpec; @@ -345,8 +344,8 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const // FIXME: better? //if (data->bpMultiple && str.isEmpty() && !data->markerFileName.isEmpty()) // str = data->markerLineNumber; - const QString str = data->pending ? data->lineNumber : data->bpLineNumber; - return str.isEmpty() ? empty : str; + const int nr = data->pending ? data->lineNumber : data->bpLineNumber; + return nr ? QString::number(nr) : empty; } if (role == Qt::UserRole + 1) return data->lineNumber; @@ -360,8 +359,10 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const return data->condition; break; case 5: - if (role == Qt::DisplayRole) - return data->pending ? data->ignoreCount : data->bpIgnoreCount; + if (role == Qt::DisplayRole) { + const int ignoreCount = data->pending ? data->ignoreCount : data->bpIgnoreCount; + return ignoreCount ? QVariant(ignoreCount) : QVariant(QString()); + } if (role == Qt::ToolTipRole) return tr("Breakpoint will only be hit after being ignored so many times."); if (role == Qt::UserRole + 1) @@ -381,9 +382,17 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const break; case 7: if (role == Qt::DisplayRole) { - if (data->type == BreakpointData::WatchpointType) - return data->address; - return data->bpAddress; + QString displayValue; + const quint64 effectiveAddress = data->type == BreakpointData::WatchpointType ? + data->address : data->bpAddress; + if (effectiveAddress) + displayValue += QString::fromAscii("0x%1").arg(effectiveAddress, 0, 16); + if (!data->bpState.isEmpty()) { + if (!displayValue.isEmpty()) + displayValue += QLatin1Char(' '); + displayValue += QString::fromAscii(data->bpState); + } + return displayValue; } break; } @@ -462,9 +471,9 @@ bool BreakHandler::setData(const QModelIndex &index, const QVariant &value, int return true; case BreakpointIgnoreCountRole: { - QByteArray val = value.toString().toLatin1(); - if (val != data->ignoreCount) { - data->ignoreCount = val; + const int ignoreCount = value.toInt(); + if (ignoreCount != data->ignoreCount) { + data->ignoreCount = ignoreCount; emit layoutChanged(); } } @@ -580,6 +589,14 @@ void BreakHandler::removeAllBreakpoints() updateMarkers(); } +BreakpointData *BreakHandler::findBreakpoint(quint64 address) const +{ + foreach (BreakpointData *data, m_bp) + if (data->address == address) + return data; + return 0; +} + BreakpointData *BreakHandler::findBreakpoint(const QString &fileName, int lineNumber, bool useMarkerPosition) { @@ -589,17 +606,30 @@ BreakpointData *BreakHandler::findBreakpoint(const QString &fileName, return 0; } -void BreakHandler::toggleBreakpoint(const QString &fileName, int lineNumber) +void BreakHandler::toggleBreakpoint(const QString &fileName, int lineNumber, + quint64 address /* = 0 */) { - BreakpointData *data = findBreakpoint(fileName, lineNumber, true); - if (!data) - data = findBreakpoint(fileName, lineNumber, false); + BreakpointData *data = 0; + do { + if (address) { + data = findBreakpoint(address); + break; + } + data = findBreakpoint(fileName, lineNumber, true); + if (!data) + data = findBreakpoint(fileName, lineNumber, false); + } while (false); + if (data) { removeBreakpoint(data); } else { data = new BreakpointData; - data->fileName = fileName; - data->lineNumber = QByteArray::number(lineNumber); + if (address) { + data->address = address; + } else { + data->fileName = fileName; + data->lineNumber = lineNumber; + } data->pending = true; data->setMarkerFileName(fileName); data->setMarkerLineNumber(lineNumber); @@ -629,7 +659,7 @@ void BreakHandler::breakByFunction(const QString &functionName) const BreakpointData *data = at(index); QTC_ASSERT(data, break); if (data->funcName == functionName && data->condition.isEmpty() - && data->ignoreCount.isEmpty()) + && data->ignoreCount == 0) return; } BreakpointData *data = new BreakpointData; @@ -658,7 +688,7 @@ void BreakHandler::initializeFromTemplate(BreakHandler *other) void BreakHandler::storeToTemplate(BreakHandler *other) { other->removeAllBreakpoints(); - foreach (BreakpointData *data, m_bp) + foreach (const BreakpointData *data, m_bp) other->append(data->clone()); removeAllBreakpoints(); other->updateMarkers(); diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 4afa1408ef1..432bf0a27a8 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -73,7 +73,7 @@ public: // Find a breakpoint matching approximately the data in needle. BreakpointData *findSimilarBreakpoint(const BreakpointData *needle) const; BreakpointData *findBreakpointByNumber(int bpNumber) const; - int findWatchPointIndexByAddress(const QByteArray &a) const; + int findWatchPointIndexByAddress(quint64 address) const; bool watchPointAt(quint64 address) const; void updateMarkers(); bool isActive() const; @@ -91,10 +91,11 @@ public: void initializeFromTemplate(BreakHandler *other); void storeToTemplate(BreakHandler *other); - void toggleBreakpoint(const QString &fileName, int lineNumber); + void toggleBreakpoint(const QString &fileName, int lineNumber, quint64 address = 0); void toggleBreakpointEnabled(const QString &fileName, int lineNumber); BreakpointData *findBreakpoint(const QString &fileName, int lineNumber, bool useMarkerPosition = true); + BreakpointData *findBreakpoint(quint64 address) const; public slots: void appendBreakpoint(BreakpointData *data); diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp index cef7f4ada9e..3d45c972b59 100644 --- a/src/plugins/debugger/breakpoint.cpp +++ b/src/plugins/debugger/breakpoint.cpp @@ -130,7 +130,7 @@ public: // FIXME: Should we tell gdb about the change? // Ignore it for now, as we would require re-compilation // and debugger re-start anyway. - if (0 && !m_data->bpLineNumber.isEmpty()) { + if (0 && m_data->bpLineNumber) { if (!m_data->bpNumber.trimmed().isEmpty()) { m_data->pending = true; } @@ -141,7 +141,7 @@ public: // the next line that generated code. // FIXME: Do we need yet another data member? if (m_data->bpNumber.trimmed().isEmpty()) { - m_data->lineNumber = QByteArray::number(lineNumber); + m_data->lineNumber = lineNumber; m_data->handler()->updateMarkers(); } } @@ -159,17 +159,16 @@ private: // ////////////////////////////////////////////////////////////////// -BreakpointData::BreakpointData() +BreakpointData::BreakpointData() : + m_handler(0), enabled(true), + pending(true), type(BreakpointType), + ignoreCount(0), lineNumber(0), address(0), + useFullPath(false), + bpIgnoreCount(0), bpLineNumber(0), + bpCorrectedLineNumber(0), bpAddress(0), + bpMultiple(false), bpEnabled(true), + m_markerLineNumber(0), marker(0) { - m_handler = 0; - enabled = true; - pending = true; - type = BreakpointType; - marker = 0; - m_markerLineNumber = 0; - bpMultiple = false; - bpEnabled = true; - useFullPath = false; } BreakpointData *BreakpointData::clone() const @@ -193,7 +192,7 @@ BreakpointData *BreakpointData::clone() const data->m_markerLineNumber = m_markerLineNumber; } else { data->m_markerFileName = fileName; - data->m_markerLineNumber = lineNumber.toInt(); + data->m_markerLineNumber = lineNumber; } return data; } @@ -233,6 +232,16 @@ void BreakpointData::setMarkerLineNumber(int lineNumber) m_markerLineNumber = lineNumber; } +static inline void formatAddress(QTextStream &str, quint64 address) +{ + if (address) { + str << "0x"; + str.setIntegerBase(16); + str << address; + str.setIntegerBase(10); + } +} + QString BreakpointData::toToolTip() const { QString rc; @@ -250,6 +259,8 @@ QString BreakpointData::toToolTip() const : type == WatchpointType ? BreakHandler::tr("Watchpoint") : BreakHandler::tr("Unknown breakpoint type")) << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("State:") + << "</td><td>" << bpState << "</td></tr>" << "</table><br><hr><table>" << "<tr><th>" << BreakHandler::tr("Property") << "</th><th>" << BreakHandler::tr("Requested") @@ -260,54 +271,46 @@ QString BreakpointData::toToolTip() const << "</td><td>" << fileName << "</td><td>" << QDir::toNativeSeparators(bpFileName) << "</td></tr>" << "<tr><td>" << BreakHandler::tr("Function Name:") << "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Line Number:") - << "</td><td>" << lineNumber << "</td><td>" << bpLineNumber << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Line Number:") << "</td><td>"; + if (lineNumber) + str << lineNumber; + str << "</td><td>"; + if (bpLineNumber) + str << bpLineNumber; + str << "</td></tr>" << "<tr><td>" << BreakHandler::tr("Breakpoint Address:") - << "</td><td>" << address << "</td><td>" << bpAddress << "</td></tr>" + << "</td><td>"; + formatAddress(str, address); + str << "</td><td>"; + formatAddress(str, bpAddress); + str << "</td></tr>" << "<tr><td>" << BreakHandler::tr("Corrected Line Number:") - << "</td><td>-</td><td>" << bpCorrectedLineNumber << "</td></tr>" + << "</td><td>-</td><td>"; + if (bpCorrectedLineNumber > 0) { + str << bpCorrectedLineNumber; + } else { + str << '-'; + } + str << "</td></tr>" << "<tr><td>" << BreakHandler::tr("Condition:") << "</td><td>" << condition << "</td><td>" << bpCondition << "</td></tr>" - << "<tr><td>" << BreakHandler::tr("Ignore Count:") - << "</td><td>" << ignoreCount << "</td><td>" << bpIgnoreCount << "</td></tr>" + << "<tr><td>" << BreakHandler::tr("Ignore Count:") << "</td><td>"; + if (ignoreCount) + str << ignoreCount; + str << "</td><td>"; + if (bpIgnoreCount) + str << bpIgnoreCount; + str << "</td></tr>" << "<tr><td>" << BreakHandler::tr("Thread Specification:") << "</td><td>" << threadSpec << "</td><td>" << bpThreadSpec << "</td></tr>" << "</table></body></html>"; return rc; } -QString BreakpointData::toString() const -{ - QString rc; - QTextStream str(&rc); - str << BreakHandler::tr("Marker File:") << ' ' << m_markerFileName << '\n' - << BreakHandler::tr("Marker Line:") << ' ' << m_markerLineNumber << '\n' - << BreakHandler::tr("Breakpoint Number:") << ' ' << bpNumber << '\n' - << BreakHandler::tr("Breakpoint Type:") << ' ' - << (type == BreakpointType ? BreakHandler::tr("Breakpoint") - : type == WatchpointType ? BreakHandler::tr("Watchpoint") - : BreakHandler::tr("Unknown breakpoint type")) << '\n' - << BreakHandler::tr("File Name:") << ' ' - << fileName << " -- " << bpFileName << '\n' - << BreakHandler::tr("Function Name:") << ' ' - << funcName << " -- " << bpFuncName << '\n' - << BreakHandler::tr("Line Number:") << ' ' - << lineNumber << " -- " << bpLineNumber << '\n' - << BreakHandler::tr("Breakpoint Address:") << ' ' - << address << " -- " << bpAddress << '\n' - << BreakHandler::tr("Condition:") << ' ' - << condition << " -- " << bpCondition << '\n' - << BreakHandler::tr("Ignore Count:") << ' ' - << ignoreCount << " -- " << bpIgnoreCount << '\n' - << BreakHandler::tr("Thread Specification:") << ' ' - << threadSpec << " -- " << bpThreadSpec << '\n'; - return rc; -} - bool BreakpointData::isLocatedAt(const QString &fileName_, int lineNumber_, bool useMarkerPosition) const { - int line = useMarkerPosition ? m_markerLineNumber : lineNumber.toInt(); + int line = useMarkerPosition ? m_markerLineNumber : lineNumber; return lineNumber_ == line && fileNameMatch(fileName_, m_markerFileName); } @@ -331,6 +334,9 @@ bool BreakpointData::isSimilarTo(const BreakpointData *needle) const && !needle->bpNumber.startsWith(bpNumber)) return false; + if (address && needle->address && address == needle->address) + return true; + // At least at a position we were looking for. // FIXME: breaks multiple breakpoints at the same location if (!fileName.isEmpty() diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index 0ff1f4b8ef0..ffe6a654dd4 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -55,7 +55,6 @@ public: void removeMarker(); void updateMarker(); QString toToolTip() const; - QString toString() const; BreakHandler *handler() { return m_handler; } bool isLocatedAt(const QString &fileName, int lineNumber, @@ -86,9 +85,9 @@ public: // This "user requested information" will get stored in the session. QString fileName; // Short name of source file. QByteArray condition; // Condition associated with breakpoint. - QByteArray ignoreCount; // Ignore count associated with breakpoint. - QByteArray lineNumber; // Line in source file. - QByteArray address; // Address for watchpoints. + int ignoreCount; // Ignore count associated with breakpoint. + int lineNumber; // Line in source file. + quint64 address; // Address for watchpoints. QByteArray threadSpec; // Thread specification. QString funcName; // Name of containing function. bool useFullPath; // Should we use the full path when setting the bp? @@ -96,16 +95,17 @@ public: // This is what gdb produced in response. QByteArray bpNumber; // Breakpoint number assigned by the debugger engine. QByteArray bpCondition; // Condition acknowledged by the debugger engine. - QByteArray bpIgnoreCount;// Ignore count acknowledged by the debugger engine. + int bpIgnoreCount; // Ignore count acknowledged by the debugger engine. QString bpFileName; // File name acknowledged by the debugger engine. QString bpFullName; // Full file name acknowledged by the debugger engine. - QByteArray bpLineNumber; // Line number acknowledged by the debugger engine. - QByteArray bpCorrectedLineNumber; // Acknowledged by the debugger engine. + int bpLineNumber; // Line number acknowledged by the debugger engine. + int bpCorrectedLineNumber; // Acknowledged by the debugger engine. QByteArray bpThreadSpec; // Thread spec acknowledged by the debugger engine. QString bpFuncName; // Function name acknowledged by the debugger engine. - QByteArray bpAddress; // Address acknowledged by the debugger engine. + quint64 bpAddress; // Address acknowledged by the debugger engine. bool bpMultiple; // Happens in constructors/gdb. bool bpEnabled; // Enable/disable command sent. + QByteArray bpState; // gdb: <PENDING>, <MULTIPLE> void setMarkerFileName(const QString &fileName); QString markerFileName() const { return m_markerFileName; } diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index ff5c1a13992..8725f8456a7 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -47,6 +47,7 @@ #include <QtGui/QItemSelectionModel> #include <QtGui/QToolButton> #include <QtGui/QTreeView> +#include <QtGui/QIntValidator> namespace Debugger { @@ -362,6 +363,7 @@ void BreakWindow::editBreakpoint(const QModelIndexList &list) QAbstractItemModel *m = model(); ui.lineEditCondition->setText( m->data(idx, BreakpointConditionRole).toString()); + ui.lineEditIgnoreCount->setValidator(new QIntValidator(0, 2147483647, ui.lineEditIgnoreCount)); ui.lineEditIgnoreCount->setText( m->data(idx, BreakpointIgnoreCountRole).toString()); ui.lineEditThreadSpec->setText( diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp index 6c4898e6eac..5dbe1f62196 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp +++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp @@ -44,26 +44,18 @@ CdbCore::BreakPoint breakPointFromBreakPointData(const Debugger::Internal::Break rc.type = bpd.type == Debugger::Internal::BreakpointData::BreakpointType ? CdbCore::BreakPoint::Code : CdbCore::BreakPoint::Data; - if (rc.type == CdbCore::BreakPoint::Data) { - QByteArray addressBA = bpd.address; - if (addressBA.startsWith("0x")) - addressBA.remove(0, 2); - bool ok; - rc.address = addressBA.toULongLong(&ok, 16); - if (!ok) - qWarning("Cdb: Cannot convert watchpoint address '%s'", bpd.address.constData()); - } + rc.address = bpd.address; if (!bpd.threadSpec.isEmpty()) { bool ok; rc.threadId = bpd.threadSpec.toInt(&ok); if (!ok) - qWarning("Cdb: Cannot convert breakpoint thread specification '%s'", bpd.address.constData()); + qWarning("Cdb: Cannot convert breakpoint thread specification '%s'", bpd.threadSpec.constData()); } rc.fileName = QDir::toNativeSeparators(bpd.fileName); rc.condition = bpd.condition; rc.funcName = bpd.funcName; - rc.ignoreCount = bpd.ignoreCount.isEmpty() ? 0 : bpd.ignoreCount.toInt(); - rc.lineNumber = bpd.lineNumber.isEmpty() ? -1 : bpd.lineNumber.toInt(); + rc.ignoreCount = bpd.ignoreCount; + rc.lineNumber = bpd.lineNumber; rc.oneShot = false; rc.enabled = bpd.enabled; return rc; @@ -129,7 +121,7 @@ bool synchronizeBreakPoints(CIDebugControl* debugControl, updateMarkers = true; nbd->pending = false; nbd->bpNumber = QByteArray::number(uint(id)); - nbd->bpAddress = "0x" + QByteArray::number(address, 16); + nbd->bpAddress = address; // Take over rest as is nbd->bpCondition = nbd->condition; nbd->bpIgnoreCount = nbd->ignoreCount; diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp index aeb703e647a..d802a741315 100644 --- a/src/plugins/debugger/debuggeragents.cpp +++ b/src/plugins/debugger/debuggeragents.cpp @@ -394,5 +394,19 @@ QString DisassemblerViewAgent::address() const return d->frame.address; } +// Return address of an assembly line "0x0dfd bla" +quint64 DisassemblerViewAgent::addressFromDisassemblyLine(const QString &line) +{ + const int pos = line.indexOf(QLatin1Char(' ')); + if (pos < 0) + return 0; + QString addressS = line.left(pos); + if (addressS.startsWith(QLatin1String("0x"))) + addressS.remove(0, 2); + bool ok; + const quint64 address = addressS.toULongLong(&ok, 16); + return ok ? address : quint64(0); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/debuggeragents.h b/src/plugins/debugger/debuggeragents.h index 6a4172c0cae..cd2480d06a1 100644 --- a/src/plugins/debugger/debuggeragents.h +++ b/src/plugins/debugger/debuggeragents.h @@ -97,6 +97,9 @@ public: void cleanup(); bool isMixed() const; + // Return address of an assembly line "0x0dfd bla" + static quint64 addressFromDisassemblyLine(const QString &line); + private: DisassemblerViewAgentPrivate *d; }; diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 0df9936ee7d..c61682d6961 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -325,10 +325,11 @@ void DebuggerEnginePrivate::breakpointSetRemoveMarginActionTriggered() QAction *act = qobject_cast<QAction *>(sender()); QTC_ASSERT(act, return); QList<QVariant> list = act->data().toList(); - QTC_ASSERT(list.size() == 2, return); + QTC_ASSERT(list.size() >= 3, return); const QString fileName = list.at(0).toString(); const int lineNumber = list.at(1).toInt(); - m_breakHandler.toggleBreakpoint(fileName, lineNumber); + const quint64 address = list.at(2).toULongLong(); + m_breakHandler.toggleBreakpoint(fileName, lineNumber, address); } void DebuggerEnginePrivate::breakpointEnableDisableMarginActionTriggered() @@ -352,30 +353,30 @@ void DebuggerEnginePrivate::handleContextMenuRequest(const QVariant ¶meters) QMenu *menu = (QMenu *)(list.at(2).value<quint64>()); BreakpointData *data = 0; - QString position; QString fileName; + quint64 address = 0; if (editor->property("DisassemblerView").toBool()) { fileName = editor->file()->fileName(); QString line = editor->contents() .section('\n', lineNumber - 1, lineNumber - 1); - position = _("*") + fileName; BreakpointData needle; - needle.bpAddress = line.left(line.indexOf(QLatin1Char(' '))).toLatin1(); - needle.bpLineNumber = "-1"; + address = needle.address = DisassemblerViewAgent::addressFromDisassemblyLine(line); + needle.bpLineNumber = -1; data = m_breakHandler.findSimilarBreakpoint(&needle); } else { fileName = editor->file()->fileName(); - position = fileName + QString(":%1").arg(lineNumber); data = m_breakHandler.findBreakpoint(fileName, lineNumber); } QList<QVariant> args; args.append(fileName); args.append(lineNumber); + args.append(address); if (data) { // existing breakpoint - QAction *act = new QAction(tr("Remove Breakpoint"), menu); + const QString number = QString::fromAscii(data->bpNumber); + QAction *act = new QAction(tr("Remove Breakpoint %1").arg(number), menu); act->setData(args); connect(act, SIGNAL(triggered()), this, SLOT(breakpointSetRemoveMarginActionTriggered())); @@ -383,16 +384,19 @@ void DebuggerEnginePrivate::handleContextMenuRequest(const QVariant ¶meters) QAction *act2; if (data->enabled) - act2 = new QAction(tr("Disable Breakpoint"), menu); + act2 = new QAction(tr("Disable Breakpoint %1").arg(number), menu); else - act2 = new QAction(tr("Enable Breakpoint"), menu); + act2 = new QAction(tr("Enable Breakpoint %1").arg(number), menu); act2->setData(args); connect(act2, SIGNAL(triggered()), this, SLOT(breakpointEnableDisableMarginActionTriggered())); menu->addAction(act2); } else { // non-existing - QAction *act = new QAction(tr("Set Breakpoint"), menu); + const QString text = address ? + tr("Set Breakpoint at 0x%1").arg(address, 0, 16) : + tr("Set Breakpoint at line %1").arg(lineNumber); + QAction *act = new QAction(text, menu); act->setData(args); connect(act, SIGNAL(triggered()), this, SLOT(breakpointSetRemoveMarginActionTriggered())); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 22a7a51e800..b37717f0f99 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -2061,18 +2061,23 @@ void GdbEngine::setBreakpointDataFromOutput(BreakpointData *data, const GdbMi &b } else if (child.hasName("addr")) { // <MULTIPLE> happens in constructors. In this case there are // _two_ fields named "addr" in the response. On Linux that is... - if (child.data() == "<MULTIPLE>") - data->bpMultiple = true; - else - data->bpAddress = child.data(); + if (child.data().startsWith("0x")) { + data->bpAddress = child.data().mid(2).toULongLong(0, 16); + } else { + data->bpState = child.data(); + if (child.data() == "<MULTIPLE>") + data->bpMultiple = true; + } } else if (child.hasName("file")) { file = child.data(); } else if (child.hasName("fullname")) { fullName = child.data(); } else if (child.hasName("line")) { - data->bpLineNumber = child.data(); - if (child.data().toInt() && data->bpCorrectedLineNumber.isEmpty()) - data->setMarkerLineNumber(child.data().toInt()); + bool ok; + const int lineNumber = child.data().toInt(&ok); + data->bpLineNumber = lineNumber; + if (ok && data->bpCorrectedLineNumber <= 0) + data->setMarkerLineNumber(lineNumber); } else if (child.hasName("cond")) { data->bpCondition = child.data(); // gdb 6.3 likes to "rewrite" conditions. Just accept that fact. @@ -2127,18 +2132,25 @@ QString GdbEngine::breakLocation(const QString &file) const return where; } +static inline QByteArray bpAddressSpec(quint64 address) +{ + return "*0x" + QByteArray::number(address, 16); +} + QByteArray GdbEngine::breakpointLocation(const BreakpointData *data) { if (!data->funcName.isEmpty()) return data->funcName.toLatin1(); + if (data->address) + return bpAddressSpec(data->address); // In this case, data->funcName is something like '*0xdeadbeef' - if (data->lineNumber.toInt() == 0) + if (data->lineNumber == 0) return data->funcName.toLatin1(); QString loc = data->useFullPath ? data->fileName : breakLocation(data->fileName); // The argument is simply a C-quoted version of the argument to the // non-MI "break" command, including the "original" quoting it wants. return "\"\\\"" + GdbMi::escapeCString(loc).toLocal8Bit() + "\\\":" - + data->lineNumber + '"'; + + QByteArray::number(data->lineNumber) + '"'; } void GdbEngine::sendInsertBreakpoint(int index) @@ -2147,7 +2159,7 @@ void GdbEngine::sendInsertBreakpoint(int index) // Set up fallback in case of pending breakpoints which aren't handled // by the MI interface. if (data->type == BreakpointData::WatchpointType) { - postCommand("watch *" + data->address, + postCommand("watch " + bpAddressSpec(data->address), NeedsStop | RebuildBreakpointModel, CB(handleWatchInsert), index); return; @@ -2367,9 +2379,9 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData * re.setMinimal(true); if (re.indexIn(output) != -1) { - data->bpAddress = re.cap(1).toLatin1(); + data->bpAddress = re.cap(1).toULongLong(0, 16); data->bpFuncName = re.cap(2).trimmed(); - data->bpLineNumber = re.cap(4).toLatin1(); + data->bpLineNumber = re.cap(4).toInt(); QString full = fullName(re.cap(3)); if (full.isEmpty()) { // FIXME: This happens without UsePreciseBreakpoints regularly. @@ -2388,7 +2400,7 @@ void GdbEngine::extractDataFromInfoBreak(const QString &output, BreakpointData * // the marker in more cases. if (data->fileName.endsWith(full)) full = data->fileName; - data->setMarkerLineNumber(data->bpLineNumber.toInt()); + data->setMarkerLineNumber(data->bpLineNumber); if (data->markerFileName().isEmpty()) { qDebug() << "111"; data->setMarkerFileName(full); @@ -2428,9 +2440,9 @@ void GdbEngine::handleInfoLine(const GdbResponse &response) QByteArray ba = response.data.findChild("consolestreamoutput").data(); const int pos = ba.indexOf(' ', 5); if (ba.startsWith("Line ") && pos != -1) { - const QByteArray line = ba.mid(5, pos - 5); + const int line = ba.mid(5, pos - 5).toInt(); data->bpCorrectedLineNumber = line; - data->setMarkerLineNumber(line.toInt()); + data->setMarkerLineNumber(line); } } } @@ -2542,7 +2554,7 @@ void GdbEngine::attemptBreakpointSynchronization() else // Because gdb won't do both changes at a time anyway. if (data->ignoreCount != data->bpIgnoreCount) { // Update ignorecount if needed. - QByteArray ic = QByteArray::number(data->ignoreCount.toInt()); + QByteArray ic = QByteArray::number(data->ignoreCount); postCommand("ignore " + data->bpNumber + ' ' + ic, NeedsStop | RebuildBreakpointModel, CB(handleBreakIgnore), data->bpNumber.toInt()); @@ -2564,11 +2576,10 @@ void GdbEngine::attemptBreakpointSynchronization() sendInsertBreakpoint(index); continue; } - if (data->bpAddress.startsWith("0x") - && data->bpCorrectedLineNumber.isEmpty()) { + if (data->bpAddress && data->bpCorrectedLineNumber == 0) { // Prevent endless loop. - data->bpCorrectedLineNumber = " "; - postCommand("info line *" + data->bpAddress, + data->bpCorrectedLineNumber = -1; + postCommand("info line *0x" + QByteArray::number(data->bpAddress, 16), NeedsStop | RebuildBreakpointModel, CB(handleInfoLine), data->bpNumber.toInt()); } diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index 6d6c3cc5a7a..db8ea433281 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -332,14 +332,14 @@ static QByteArray breakpointLocation(const BreakpointData *data) if (!data->funcName.isEmpty()) return data->funcName.toLatin1(); // In this case, data->funcName is something like '*0xdeadbeef' - if (data->lineNumber.toInt() == 0) + if (data->lineNumber == 0) return data->funcName.toLatin1(); //QString loc = data->useFullPath ? data->fileName : breakLocation(data->fileName); // The argument is simply a C-quoted version of the argument to the // non-MI "break" command, including the "original" quoting it wants. //return "\"\\\"" + GdbMi::escapeCString(data->fileName).toLocal8Bit() + "\\\":" // + data->lineNumber + '"'; - return data->fileName.toLocal8Bit() + ":" + data->lineNumber; + return data->fileName.toLocal8Bit() + ':' + QByteArray::number(data->lineNumber); } void PdbEngine::attemptBreakpointSynchronization() @@ -388,7 +388,7 @@ void PdbEngine::handleBreakInsert(const PdbResponse &response) QByteArray line = response.data.mid(pos2 + 1); data->bpNumber = bpnr; data->bpFileName = _(file); - data->bpLineNumber = line; + data->bpLineNumber = line.toInt(); handler->updateMarkers(); } diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index f91c87627e7..e714f03c433 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -439,7 +439,7 @@ void QmlEngine::attemptBreakpointSynchronization() QString processedFilename = data->fileName; if (isShadowBuildProject()) processedFilename = toShadowBuildFilename(data->fileName); - breakList << qMakePair(processedFilename, data->lineNumber.toInt()); + breakList << qMakePair(processedFilename, data->lineNumber); } { diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp index 43b8cbd06e8..f5b36383bbc 100644 --- a/src/plugins/debugger/script/scriptengine.cpp +++ b/src/plugins/debugger/script/scriptengine.cpp @@ -462,7 +462,7 @@ void ScriptEngine::attemptBreakpointSynchronization() } if (!data->fileName.isEmpty() && data->markerFileName().isEmpty()) { data->setMarkerFileName(data->fileName); - data->setMarkerLineNumber(data->lineNumber.toInt()); + data->setMarkerLineNumber(data->lineNumber); updateNeeded = true; } } @@ -608,7 +608,7 @@ static BreakpointData *findBreakPointByFileName(BreakHandler *handler, const int count = handler->size(); for (int b = 0; b < count; b++) { BreakpointData *data = handler->at(b); - if (lineNumber == data->lineNumber.toInt() && fileName == data->fileName) + if (lineNumber == data->lineNumber && fileName == data->fileName) return data; } return 0; @@ -649,7 +649,7 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction) // We just run into a breakpoint. //SDEBUG("RESOLVING BREAKPOINT AT " << fileName << lineNumber); - data->bpLineNumber = QByteArray::number(lineNumber); + data->bpLineNumber = lineNumber; data->bpFileName = fileName; data->bpFuncName = functionName; data->setMarkerLineNumber(lineNumber); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 2871f2135ab..f5735b4b06e 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -769,13 +769,11 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro case RequestToggleWatchRole: { BreakHandler *handler = engine()->breakHandler(); const quint64 address = value.toULongLong(); - const QByteArray addressBA = - QByteArray("0x") + QByteArray::number(address, 16); - const int index = handler->findWatchPointIndexByAddress(addressBA); + const int index = handler->findWatchPointIndexByAddress(address); if (index == -1) { BreakpointData *data = new BreakpointData; data->type = BreakpointData::WatchpointType; - data->address = addressBA; + data->address = address; handler->appendBreakpoint(data); } else { handler->removeBreakpoint(index); -- GitLab