debugger: first shot a implementing data watchpoints

This commit is contained in:
hjk
2010-05-07 15:16:31 +02:00
parent 4648a5b3a4
commit 6c0b947ec1
13 changed files with 269 additions and 137 deletions

View File

@@ -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();

View File

@@ -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;

View 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

View File

@@ -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();
}

View File

@@ -16,6 +16,7 @@ QT += gui \
script
HEADERS += breakhandler.h \
breakwindow.h \
breakpoint.h \
debuggeragents.h \
debuggeractions.h \
debuggerconstants.h \

View File

@@ -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>

View File

@@ -132,7 +132,8 @@ enum DebuggerCapabilities
BreakOnThrowAndCatchCapability = 0x200,
ReturnFromFunctionCapability = 0x400,
CreateFullBacktraceCapability = 0x800,
AddWatcherCapability = 0x1000
AddWatcherCapability = 0x1000,
WatchpointCapability = 0x2000
};
enum LogChannel

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

View File

@@ -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;