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 &parameters)
     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 &parameters)
 
         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