forked from qt-creator/qt-creator
debugger: first shot a implementing data watchpoints
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "debuggeractions.h"
|
||||
#include "debuggermanager.h"
|
||||
#include "debuggerstringutils.h"
|
||||
#include "stackframe.h"
|
||||
|
||||
#include <texteditor/basetextmark.h>
|
||||
@@ -53,13 +54,11 @@ using namespace Debugger::Internal;
|
||||
// Compare file names case insensitively on Windows.
|
||||
static inline bool fileNameMatch(const QString &f1, const QString &f2)
|
||||
{
|
||||
return f1.compare(f2,
|
||||
#ifdef Q_OS_WIN
|
||||
Qt::CaseInsensitive
|
||||
return f1.compare(f2, Qt::CaseInsensitive) == 0;
|
||||
#else
|
||||
Qt::CaseSensitive
|
||||
return f1 == f2;
|
||||
#endif
|
||||
) == 0;
|
||||
}
|
||||
|
||||
namespace Debugger {
|
||||
@@ -87,7 +86,7 @@ public:
|
||||
|
||||
QIcon icon() const
|
||||
{
|
||||
const BreakHandler *handler = DebuggerManager::instance()->breakHandler();
|
||||
const BreakHandler *handler = m_data->handler();
|
||||
if (!m_enabled)
|
||||
return handler->disabledBreakpointIcon();
|
||||
return m_pending ? handler->pendingBreakPointIcon() : handler->breakpointIcon();
|
||||
@@ -162,28 +161,21 @@ private:
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
BreakpointData::BreakpointData(BreakHandler *handler)
|
||||
BreakpointData::BreakpointData()
|
||||
{
|
||||
//qDebug() << "CREATE BREAKPOINTDATA" << this;
|
||||
m_handler = handler;
|
||||
m_handler = 0;
|
||||
enabled = true;
|
||||
pending = true;
|
||||
type = BreakpointType;
|
||||
marker = 0;
|
||||
m_markerLineNumber = 0;
|
||||
bpMultiple = false;
|
||||
//#if defined(Q_OS_MAC)
|
||||
// // full names do not work on Mac/MI
|
||||
useFullPath = false;
|
||||
//#else
|
||||
// //where = m_manager->shortName(data->fileName);
|
||||
// useFullPath = true;
|
||||
//#endif
|
||||
}
|
||||
|
||||
BreakpointData::~BreakpointData()
|
||||
{
|
||||
removeMarker();
|
||||
//qDebug() << "DESTROY BREAKPOINTDATA" << this;
|
||||
}
|
||||
|
||||
void BreakpointData::removeMarker()
|
||||
@@ -227,8 +219,6 @@ QString BreakpointData::toToolTip() const
|
||||
<< "</td><td>" << m_markerLineNumber << "</td></tr>"
|
||||
<< "<tr><td>" << BreakHandler::tr("Breakpoint Number:")
|
||||
<< "</td><td>" << bpNumber << "</td></tr>"
|
||||
<< "<tr><td>" << BreakHandler::tr("Breakpoint Address:")
|
||||
<< "</td><td>" << bpAddress << "</td></tr>"
|
||||
<< "</table><br><hr><table>"
|
||||
<< "<tr><th>" << BreakHandler::tr("Property")
|
||||
<< "</th><th>" << BreakHandler::tr("Requested")
|
||||
@@ -241,6 +231,8 @@ QString BreakpointData::toToolTip() const
|
||||
<< "</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("Breakpoint Address:")
|
||||
<< "</td><td>" << address << "</td><td>" << bpAddress << "</td></tr>"
|
||||
<< "<tr><td>" << BreakHandler::tr("Corrected Line Number:")
|
||||
<< "</td><td>-</td><td>" << bpCorrectedLineNumber << "</td></tr>"
|
||||
<< "<tr><td>" << BreakHandler::tr("Condition:")
|
||||
@@ -260,13 +252,14 @@ QString BreakpointData::toString() const
|
||||
str << BreakHandler::tr("Marker File:") << m_markerFileName << ' '
|
||||
<< BreakHandler::tr("Marker Line:") << m_markerLineNumber << ' '
|
||||
<< BreakHandler::tr("Breakpoint Number:") << bpNumber << ' '
|
||||
<< BreakHandler::tr("Breakpoint Address:") << bpAddress << '\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:")
|
||||
@@ -310,9 +303,10 @@ bool BreakpointData::conditionsMatch() const
|
||||
|
||||
BreakHandler::BreakHandler(DebuggerManager *manager, QObject *parent) :
|
||||
QAbstractTableModel(parent),
|
||||
m_breakpointIcon(QLatin1String(":/debugger/images/breakpoint_16.png")),
|
||||
m_disabledBreakpointIcon(QLatin1String(":/debugger/images/breakpoint_disabled_16.png")),
|
||||
m_pendingBreakPointIcon(QLatin1String(":/debugger/images/breakpoint_pending_16.png")),
|
||||
m_breakpointIcon(_(":/debugger/images/breakpoint_16.png")),
|
||||
m_disabledBreakpointIcon(_(":/debugger/images/breakpoint_disabled_16.png")),
|
||||
m_pendingBreakPointIcon(_(":/debugger/images/breakpoint_pending_16.png")),
|
||||
m_watchpointIcon(_(":/debugger/images/watchpoint.png")),
|
||||
m_manager(manager)
|
||||
{
|
||||
}
|
||||
@@ -412,22 +406,29 @@ void BreakHandler::saveBreakpoints()
|
||||
for (int index = 0; index != size(); ++index) {
|
||||
const BreakpointData *data = at(index);
|
||||
QMap<QString, QVariant> map;
|
||||
// Do not persist Watchpoints.
|
||||
//if (data->type == BreakpointData::WatchpointType)
|
||||
// continue;
|
||||
if (data->type != BreakpointData::BreakpointType)
|
||||
map.insert(_("type"), data->type);
|
||||
if (!data->fileName.isEmpty())
|
||||
map.insert(QLatin1String("filename"), data->fileName);
|
||||
map.insert(_("filename"), data->fileName);
|
||||
if (!data->lineNumber.isEmpty())
|
||||
map.insert(QLatin1String("linenumber"), data->lineNumber);
|
||||
map.insert(_("linenumber"), data->lineNumber);
|
||||
if (!data->funcName.isEmpty())
|
||||
map.insert(QLatin1String("funcname"), data->funcName);
|
||||
map.insert(_("funcname"), data->funcName);
|
||||
if (!data->address.isEmpty())
|
||||
map.insert(_("address"), data->address);
|
||||
if (!data->condition.isEmpty())
|
||||
map.insert(QLatin1String("condition"), data->condition);
|
||||
map.insert(_("condition"), data->condition);
|
||||
if (!data->ignoreCount.isEmpty())
|
||||
map.insert(QLatin1String("ignorecount"), data->ignoreCount);
|
||||
map.insert(_("ignorecount"), data->ignoreCount);
|
||||
if (!data->threadSpec.isEmpty())
|
||||
map.insert(QLatin1String("threadspec"), data->threadSpec);
|
||||
map.insert(_("threadspec"), data->threadSpec);
|
||||
if (!data->enabled)
|
||||
map.insert(QLatin1String("disabled"), QLatin1String("1"));
|
||||
map.insert(_("disabled"), _("1"));
|
||||
if (data->useFullPath)
|
||||
map.insert(QLatin1String("usefullpath"), QLatin1String("1"));
|
||||
map.insert(_("usefullpath"), _("1"));
|
||||
list.append(map);
|
||||
}
|
||||
m_manager->setSessionValue("Breakpoints", list);
|
||||
@@ -440,31 +441,37 @@ void BreakHandler::loadBreakpoints()
|
||||
clear();
|
||||
foreach (const QVariant &var, list) {
|
||||
const QMap<QString, QVariant> map = var.toMap();
|
||||
BreakpointData *data = new BreakpointData(this);
|
||||
QVariant v = map.value(QLatin1String("filename"));
|
||||
BreakpointData *data = new BreakpointData;
|
||||
QVariant v = map.value(_("filename"));
|
||||
if (v.isValid())
|
||||
data->fileName = v.toString();
|
||||
v = map.value(QLatin1String("linenumber"));
|
||||
v = map.value(_("linenumber"));
|
||||
if (v.isValid())
|
||||
data->lineNumber = v.toString().toLatin1();
|
||||
v = map.value(QLatin1String("condition"));
|
||||
v = map.value(_("condition"));
|
||||
if (v.isValid())
|
||||
data->condition = v.toString().toLatin1();
|
||||
v = map.value(QLatin1String("ignorecount"));
|
||||
v = map.value(_("address"));
|
||||
if (v.isValid())
|
||||
data->address = v.toString().toLatin1();
|
||||
v = map.value(_("ignorecount"));
|
||||
if (v.isValid())
|
||||
data->ignoreCount = v.toString().toLatin1();
|
||||
v = map.value(QLatin1String("threadspec"));
|
||||
v = map.value(_("threadspec"));
|
||||
if (v.isValid())
|
||||
data->threadSpec = v.toString().toLatin1();
|
||||
v = map.value(QLatin1String("funcname"));
|
||||
v = map.value(_("funcname"));
|
||||
if (v.isValid())
|
||||
data->funcName = v.toString();
|
||||
v = map.value(QLatin1String("disabled"));
|
||||
v = map.value(_("disabled"));
|
||||
if (v.isValid())
|
||||
data->enabled = !v.toInt();
|
||||
v = map.value(QLatin1String("usefullpath"));
|
||||
v = map.value(_("usefullpath"));
|
||||
if (v.isValid())
|
||||
data->useFullPath = bool(v.toInt());
|
||||
v = map.value(_("type"));
|
||||
if (v.isValid())
|
||||
data->type = BreakpointData::Type(v.toInt());
|
||||
data->setMarkerFileName(data->fileName);
|
||||
data->setMarkerLineNumber(data->lineNumber.toInt());
|
||||
append(data);
|
||||
@@ -538,6 +545,8 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
|
||||
if (role == Qt::UserRole)
|
||||
return data->enabled;
|
||||
if (role == Qt::DecorationRole) {
|
||||
if (data->type == BreakpointData::WatchpointType)
|
||||
return m_watchpointIcon;
|
||||
if (!data->enabled)
|
||||
return m_disabledBreakpointIcon;
|
||||
return data->pending ? m_pendingBreakPointIcon : m_breakpointIcon;
|
||||
@@ -606,8 +615,11 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const
|
||||
if (role == Qt::UserRole + 1)
|
||||
return data->threadSpec;
|
||||
case 7:
|
||||
if (role == Qt::DisplayRole)
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (data->type == BreakpointData::WatchpointType)
|
||||
return data->address;
|
||||
return data->bpAddress;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (role == Qt::ToolTipRole)
|
||||
@@ -706,6 +718,7 @@ bool BreakHandler::setData(const QModelIndex &mi, const QVariant &value, int rol
|
||||
|
||||
void BreakHandler::append(BreakpointData *data)
|
||||
{
|
||||
data->m_handler = this;
|
||||
m_bp.append(data);
|
||||
m_inserted.append(data);
|
||||
}
|
||||
@@ -823,7 +836,7 @@ void BreakHandler::breakByFunction(const QString &functionName)
|
||||
&& data->ignoreCount.isEmpty())
|
||||
return;
|
||||
}
|
||||
BreakpointData *data = new BreakpointData(this);
|
||||
BreakpointData *data = new BreakpointData;
|
||||
data->funcName = functionName;
|
||||
append(data);
|
||||
saveBreakpoints();
|
||||
|
||||
@@ -30,90 +30,15 @@
|
||||
#ifndef DEBUGGER_BREAKHANDLER_H
|
||||
#define DEBUGGER_BREAKHANDLER_H
|
||||
|
||||
#include "breakpoint.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QAbstractTableModel>
|
||||
#include <QtGui/QIcon>
|
||||
|
||||
namespace Debugger {
|
||||
class DebuggerManager;
|
||||
namespace Internal {
|
||||
|
||||
class BreakpointMarker;
|
||||
class BreakHandler;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakpointData
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
class BreakpointData
|
||||
{
|
||||
public:
|
||||
explicit BreakpointData(BreakHandler *handler);
|
||||
~BreakpointData();
|
||||
|
||||
void removeMarker();
|
||||
void updateMarker();
|
||||
QString toToolTip() const;
|
||||
QString toString() const;
|
||||
BreakHandler *handler() { return m_handler; }
|
||||
|
||||
bool isLocatedAt(const QString &fileName, int lineNumber) const;
|
||||
bool conditionsMatch() const;
|
||||
|
||||
private:
|
||||
// Intentionally unimplemented.
|
||||
// Making it copyable is tricky because of the markers.
|
||||
void operator=(const BreakpointData &);
|
||||
BreakpointData(const BreakpointData &);
|
||||
|
||||
// Our owner
|
||||
BreakHandler *m_handler; // Not owned.
|
||||
|
||||
public:
|
||||
bool enabled; // Should we talk to the debugger engine?
|
||||
bool pending; // Does the debugger engine know about us already?
|
||||
|
||||
// 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 threadSpec; // Thread specification.
|
||||
QString funcName; // Name of containing function.
|
||||
bool useFullPath; // Should we use the full path when setting the bp?
|
||||
|
||||
// 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.
|
||||
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.
|
||||
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.
|
||||
bool bpMultiple; // Happens in constructors/gdb.
|
||||
bool bpEnabled; // Enable/disable command sent.
|
||||
|
||||
void setMarkerFileName(const QString &fileName);
|
||||
QString markerFileName() const { return m_markerFileName; }
|
||||
|
||||
void setMarkerLineNumber(int lineNumber);
|
||||
int markerLineNumber() const { return m_markerLineNumber; }
|
||||
|
||||
private:
|
||||
// Taken from either user input or gdb responses.
|
||||
QString m_markerFileName; // Used to locate the marker.
|
||||
int m_markerLineNumber;
|
||||
|
||||
// Our red blob in the editor.
|
||||
BreakpointMarker *marker;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakHandler
|
||||
@@ -184,6 +109,7 @@ private:
|
||||
const QIcon m_breakpointIcon;
|
||||
const QIcon m_disabledBreakpointIcon;
|
||||
const QIcon m_pendingBreakPointIcon;
|
||||
const QIcon m_watchpointIcon;
|
||||
|
||||
DebuggerManager *m_manager; // Not owned.
|
||||
QList<BreakpointData *> m_bp;
|
||||
|
||||
123
src/plugins/debugger/breakpoint.h
Normal file
123
src/plugins/debugger/breakpoint.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef DEBUGGER_BREAKPOINT_H
|
||||
#define DEBUGGER_BREAKPOINT_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace Debugger {
|
||||
class DebuggerManager;
|
||||
namespace Internal {
|
||||
|
||||
class BreakpointMarker;
|
||||
class BreakHandler;
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakpointData
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
class BreakpointData
|
||||
{
|
||||
public:
|
||||
BreakpointData();
|
||||
~BreakpointData();
|
||||
|
||||
void removeMarker();
|
||||
void updateMarker();
|
||||
QString toToolTip() const;
|
||||
QString toString() const;
|
||||
BreakHandler *handler() { return m_handler; }
|
||||
|
||||
bool isLocatedAt(const QString &fileName, int lineNumber) const;
|
||||
bool conditionsMatch() const;
|
||||
|
||||
private:
|
||||
// Intentionally unimplemented.
|
||||
// Making it copyable is tricky because of the markers.
|
||||
void operator=(const BreakpointData &);
|
||||
BreakpointData(const BreakpointData &);
|
||||
|
||||
// Our owner
|
||||
BreakHandler *m_handler; // Not owned.
|
||||
friend class BreakHandler;
|
||||
|
||||
public:
|
||||
enum Type { BreakpointType, WatchpointType };
|
||||
|
||||
bool enabled; // Should we talk to the debugger engine?
|
||||
bool pending; // Does the debugger engine know about us already?
|
||||
Type type; // Type of breakpoint.
|
||||
|
||||
// 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.
|
||||
QByteArray threadSpec; // Thread specification.
|
||||
QString funcName; // Name of containing function.
|
||||
bool useFullPath; // Should we use the full path when setting the bp?
|
||||
|
||||
// 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.
|
||||
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.
|
||||
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.
|
||||
bool bpMultiple; // Happens in constructors/gdb.
|
||||
bool bpEnabled; // Enable/disable command sent.
|
||||
|
||||
void setMarkerFileName(const QString &fileName);
|
||||
QString markerFileName() const { return m_markerFileName; }
|
||||
|
||||
void setMarkerLineNumber(int lineNumber);
|
||||
int markerLineNumber() const { return m_markerLineNumber; }
|
||||
|
||||
private:
|
||||
// Taken from either user input or gdb responses.
|
||||
QString m_markerFileName; // Used to locate the marker.
|
||||
int m_markerLineNumber;
|
||||
|
||||
// Our red blob in the editor.
|
||||
BreakpointMarker *marker;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_BREAKPOINT_H
|
||||
@@ -355,29 +355,30 @@ void BreakWindow::editBreakpoint(const QModelIndexList &list)
|
||||
ui.labelFileName->hide();
|
||||
ui.lineEditLineNumber->hide();
|
||||
ui.labelLineNumber->hide();
|
||||
QAbstractItemModel *m = model();
|
||||
//ui.lineEditFunction->setText(
|
||||
// model()->data(idx.sibling(row, 1), role).toString());
|
||||
// m->data(idx.sibling(row, 1), role).toString());
|
||||
//ui.lineEditFileName->setText(
|
||||
// model()->data(idx.sibling(row, 2), role).toString());
|
||||
// m->data(idx.sibling(row, 2), role).toString());
|
||||
//ui.lineEditLineNumber->setText(
|
||||
// model()->data(idx.sibling(row, 3), role).toString());
|
||||
// m->data(idx.sibling(row, 3), role).toString());
|
||||
ui.lineEditCondition->setText(
|
||||
model()->data(idx.sibling(row, 4), role).toString());
|
||||
m->data(idx.sibling(row, 4), role).toString());
|
||||
ui.lineEditIgnoreCount->setText(
|
||||
model()->data(idx.sibling(row, 5), role).toString());
|
||||
m->data(idx.sibling(row, 5), role).toString());
|
||||
ui.lineEditThreadSpec->setText(
|
||||
model()->data(idx.sibling(row, 6), role).toString());
|
||||
m->data(idx.sibling(row, 6), role).toString());
|
||||
|
||||
if (dlg.exec() == QDialog::Rejected)
|
||||
return;
|
||||
|
||||
foreach (const QModelIndex &idx, list) {
|
||||
//model()->setData(idx.sibling(idx.row(), 1), ui.lineEditFunction->text());
|
||||
//model()->setData(idx.sibling(idx.row(), 2), ui.lineEditFileName->text());
|
||||
//model()->setData(idx.sibling(idx.row(), 3), ui.lineEditLineNumber->text());
|
||||
model()->setData(idx.sibling(idx.row(), 4), ui.lineEditCondition->text());
|
||||
model()->setData(idx.sibling(idx.row(), 5), ui.lineEditIgnoreCount->text());
|
||||
model()->setData(idx.sibling(idx.row(), 6), ui.lineEditThreadSpec->text());
|
||||
//m->setData(idx.sibling(idx.row(), 1), ui.lineEditFunction->text());
|
||||
//m->setData(idx.sibling(idx.row(), 2), ui.lineEditFileName->text());
|
||||
//m->setData(idx.sibling(idx.row(), 3), ui.lineEditLineNumber->text());
|
||||
m->setData(idx.sibling(idx.row(), 4), ui.lineEditCondition->text());
|
||||
m->setData(idx.sibling(idx.row(), 5), ui.lineEditIgnoreCount->text());
|
||||
m->setData(idx.sibling(idx.row(), 6), ui.lineEditThreadSpec->text());
|
||||
}
|
||||
emit breakpointSynchronizationRequested();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ QT += gui \
|
||||
script
|
||||
HEADERS += breakhandler.h \
|
||||
breakwindow.h \
|
||||
breakpoint.h \
|
||||
debuggeragents.h \
|
||||
debuggeractions.h \
|
||||
debuggerconstants.h \
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<file>images/debugger_stepoverproc_small.png</file>
|
||||
<file>images/debugger_stop.png</file>
|
||||
<file>images/debugger_stop_small.png</file>
|
||||
<file>images/watchpoint.png</file>
|
||||
<file>images/breakpoint_16.png</file>
|
||||
<file>images/breakpoint_24.png</file>
|
||||
<file>images/breakpoint_disabled_16.png</file>
|
||||
|
||||
@@ -132,7 +132,8 @@ enum DebuggerCapabilities
|
||||
BreakOnThrowAndCatchCapability = 0x200,
|
||||
ReturnFromFunctionCapability = 0x400,
|
||||
CreateFullBacktraceCapability = 0x800,
|
||||
AddWatcherCapability = 0x1000
|
||||
AddWatcherCapability = 0x1000,
|
||||
WatchpointCapability = 0x2000
|
||||
};
|
||||
|
||||
enum LogChannel
|
||||
|
||||
@@ -897,9 +897,9 @@ BreakpointData *DebuggerManager::findBreakpoint(const QString &fileName, int lin
|
||||
// FIXME: move further up the plugin where there's more specific context
|
||||
// information available.
|
||||
static BreakpointData *createBreakpointByFileAndLine
|
||||
(const QString &fileName, int lineNumber, BreakHandler *handler)
|
||||
(const QString &fileName, int lineNumber)
|
||||
{
|
||||
BreakpointData *data = new BreakpointData(handler);
|
||||
BreakpointData *data = new BreakpointData;
|
||||
if (lineNumber > 0) {
|
||||
data->fileName = fileName;
|
||||
data->lineNumber = QByteArray::number(lineNumber);
|
||||
@@ -934,7 +934,7 @@ void DebuggerManager::toggleBreakpoint(const QString &fileName, int lineNumber)
|
||||
int index = d->m_breakHandler->findBreakpoint(fileName, lineNumber);
|
||||
if (index == -1)
|
||||
d->m_breakHandler->appendBreakpoint(
|
||||
createBreakpointByFileAndLine(fileName, lineNumber, d->m_breakHandler));
|
||||
createBreakpointByFileAndLine(fileName, lineNumber));
|
||||
else
|
||||
d->m_breakHandler->removeBreakpoint(index);
|
||||
|
||||
@@ -1410,6 +1410,13 @@ void DebuggerManager::breakByFunction(const QString &functionName)
|
||||
attemptBreakpointSynchronization();
|
||||
}
|
||||
|
||||
void DebuggerManager::appendBreakpoint(BreakpointData *data)
|
||||
{
|
||||
QTC_ASSERT(d->m_breakHandler, return);
|
||||
d->m_breakHandler->appendBreakpoint(data);
|
||||
attemptBreakpointSynchronization();
|
||||
}
|
||||
|
||||
void DebuggerManager::setBusyCursor(bool busy)
|
||||
{
|
||||
//STATE_DEBUG("BUSY FROM: " << d->m_busy << " TO: " << d->m_busy);
|
||||
|
||||
@@ -289,6 +289,7 @@ public slots: // FIXME
|
||||
void reloadRegisters();
|
||||
void registerDockToggled(bool on);
|
||||
void clearStatusMessage();
|
||||
void appendBreakpoint(Internal::BreakpointData *data);
|
||||
void attemptBreakpointSynchronization();
|
||||
void reloadFullStack();
|
||||
void operateByInstructionTriggered();
|
||||
|
||||
@@ -1394,7 +1394,19 @@ void GdbEngine::handleStop1(const GdbMi &data)
|
||||
reloadBreakListInternal();
|
||||
}
|
||||
|
||||
if (reason == "breakpoint-hit") {
|
||||
if (reason == "watchpoint-trigger") {
|
||||
// *stopped,reason="watchpoint-trigger",wpt={number="2",exp="*0xbfffed40"},
|
||||
// value={old="1",new="0"},frame={addr="0x00451e1b",
|
||||
// func="QScopedPointer",args=[{name="this",value="0xbfffed40"},
|
||||
// {name="p",value="0x0"}],file="x.h",fullname="/home/.../x.h",line="95"},
|
||||
// thread-id="1",stopped-threads="all",core="2"
|
||||
GdbMi wpt = data.findChild("wpt");
|
||||
QByteArray bpNumber = wpt.findChild("number").data();
|
||||
QByteArray bpAddress = wpt.findChild("exp").data();
|
||||
//QByteArray threadId = data.findChild("thread-id").data();
|
||||
showStatusMessage(tr("Watchpoint %1 at %2 triggered:")
|
||||
.arg(_(bpNumber), _(bpAddress)));
|
||||
} else if (reason == "breakpoint-hit") {
|
||||
QByteArray bpNumber = data.findChild("bkptno").data();
|
||||
QByteArray threadId = data.findChild("thread-id").data();
|
||||
showStatusMessage(tr("Stopped at breakpoint %1 in thread %2")
|
||||
@@ -1825,6 +1837,7 @@ unsigned GdbEngine::debuggerCapabilities() const
|
||||
| ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability
|
||||
| ReturnFromFunctionCapability
|
||||
| CreateFullBacktraceCapability
|
||||
| WatchpointCapability
|
||||
| AddWatcherCapability;
|
||||
}
|
||||
|
||||
@@ -2174,6 +2187,13 @@ void GdbEngine::sendInsertBreakpoint(int index)
|
||||
const BreakpointData *data = manager()->breakHandler()->at(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,
|
||||
NeedsStop | RebuildBreakpointModel,
|
||||
CB(handleWatchInsert), index);
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray cmd;
|
||||
if (m_isMacGdb) {
|
||||
cmd = "-break-insert -l -1 -f ";
|
||||
@@ -2197,6 +2217,23 @@ void GdbEngine::sendInsertBreakpoint(int index)
|
||||
CB(handleBreakInsert1), index);
|
||||
}
|
||||
|
||||
void GdbEngine::handleWatchInsert(const GdbResponse &response)
|
||||
{
|
||||
int index = response.cookie.toInt();
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// "Hardware watchpoint 2: *0xbfffed40\n"
|
||||
QByteArray ba = response.data.findChild("consolestreamoutput").data();
|
||||
if (ba.startsWith("Hardware watchpoint ")) {
|
||||
const int pos = ba.indexOf(':', 20);
|
||||
BreakpointData *data = manager()->breakHandler()->at(index);
|
||||
data->bpNumber = ba.mid(20, pos - 20);
|
||||
manager()->breakHandler()->updateMarkers();
|
||||
} else {
|
||||
debugMessage(_("CANNOT PARSE WATCHPOINT FROM" + ba));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::handleBreakInsert1(const GdbResponse &response)
|
||||
{
|
||||
int index = response.cookie.toInt();
|
||||
@@ -2275,7 +2312,7 @@ void GdbEngine::handleBreakList(const GdbMi &table)
|
||||
|
||||
BreakHandler *handler = manager()->breakHandler();
|
||||
for (int index = 0; index != bkpts.size(); ++index) {
|
||||
BreakpointData temp(handler);
|
||||
BreakpointData temp;
|
||||
breakpointDataFromOutput(&temp, bkpts.at(index));
|
||||
int found = handler->findBreakpoint(temp);
|
||||
if (found != -1)
|
||||
@@ -2444,7 +2481,7 @@ void GdbEngine::attemptBreakpointSynchronization()
|
||||
{
|
||||
QTC_ASSERT(!m_sourcesListUpdating,
|
||||
qDebug() << "SOURCES LIST CURRENTLY UPDATING"; return);
|
||||
debugMessage(tr("ATTEMPT BREAKPOINT SYNC"));
|
||||
debugMessage(_("ATTEMPT BREAKPOINT SYNC"));
|
||||
|
||||
switch (state()) {
|
||||
case InferiorStarting:
|
||||
@@ -2455,6 +2492,7 @@ void GdbEngine::attemptBreakpointSynchronization()
|
||||
break;
|
||||
default:
|
||||
//qDebug() << "attempted breakpoint sync in state" << state();
|
||||
debugMessage(_("... NOT POSSIBLE IN CURRENT STATE"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -344,6 +344,7 @@ private: ////////// View & Data Stuff //////////
|
||||
void handleBreakInsert2(const GdbResponse &response);
|
||||
void handleBreakCondition(const GdbResponse &response);
|
||||
void handleBreakInfo(const GdbResponse &response);
|
||||
void handleWatchInsert(const GdbResponse &response);
|
||||
void handleInfoLine(const GdbResponse &response);
|
||||
void extractDataFromInfoBreak(const QString &output, BreakpointData *data);
|
||||
void breakpointDataFromOutput(BreakpointData *data, const GdbMi &bkpt);
|
||||
|
||||
BIN
src/plugins/debugger/images/watchpoint.png
Normal file
BIN
src/plugins/debugger/images/watchpoint.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 593 B |
@@ -30,6 +30,7 @@
|
||||
#include "watchwindow.h"
|
||||
#include "watchhandler.h"
|
||||
|
||||
#include "breakpoint.h"
|
||||
#include "debuggeractions.h"
|
||||
#include "debuggeragents.h"
|
||||
#include "debuggerdialogs.h"
|
||||
@@ -284,7 +285,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
|
||||
const QString address = model()->data(mi0, AddressRole).toString();
|
||||
QAction *actWatchKnownMemory = 0;
|
||||
QAction *actWatchUnknownMemory = new QAction(tr("Open Memory Editor..."), &menu);
|
||||
QAction *actWatchUnknownMemory =
|
||||
new QAction(tr("Open Memory Editor..."), &menu);
|
||||
const bool canShowMemory = engineCapabilities & ShowMemoryCapability;
|
||||
actWatchUnknownMemory->setEnabled(actionsEnabled && canShowMemory);
|
||||
|
||||
@@ -293,6 +295,17 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
new QAction(tr("Open Memory Editor at %1").arg(address), &menu);
|
||||
menu.addSeparator();
|
||||
|
||||
QAction *actSetWatchpoint = 0;
|
||||
const bool canSetWatchpoint = engineCapabilities & WatchpointCapability;
|
||||
if (canSetWatchpoint && !address.isEmpty()) {
|
||||
actSetWatchpoint =
|
||||
new QAction(tr("Break on changing %1").arg(address), &menu);
|
||||
} else {
|
||||
actSetWatchpoint =
|
||||
new QAction(tr("Break on changing contents"), &menu);
|
||||
actSetWatchpoint->setEnabled(false);
|
||||
}
|
||||
|
||||
QAction *actWatchOrRemove;
|
||||
if (m_type == LocalsType) {
|
||||
actWatchOrRemove = theDebuggerAction(WatchExpression)->updatedAction(exp);
|
||||
@@ -311,6 +324,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
if (actWatchKnownMemory)
|
||||
menu.addAction(actWatchKnownMemory);
|
||||
menu.addAction(actWatchUnknownMemory);
|
||||
menu.addAction(actSetWatchpoint);
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(theDebuggerAction(RecheckDebuggingHelpers));
|
||||
@@ -353,6 +367,11 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
(void) new MemoryViewAgent(m_manager, dialog.address());
|
||||
}
|
||||
} else if (act == actSetWatchpoint) {
|
||||
BreakpointData *data = new BreakpointData;
|
||||
data->type = BreakpointData::WatchpointType;
|
||||
data->address = address.toLatin1();
|
||||
m_manager->appendBreakpoint(data);
|
||||
} else if (act == actSelectWidgetToWatch) {
|
||||
grabMouse(Qt::CrossCursor);
|
||||
m_grabbing = true;
|
||||
|
||||
Reference in New Issue
Block a user