if (it->data.isWatchpoint()
&& it->data.address == data.address
&& it->data.size == data.size
+ && it->data.expression == data.expression
&& it->data.bitpos == data.bitpos)
return it.key();
return BreakpointId();
|| data.type == BreakpointAtSysCall)
return typeToString(data.type);
if (data.type == WatchpointAtAddress)
- return tr("Watchpoint at 0x%1").arg(data.address, 0, 16);
+ return tr("Data breakpoint at 0x%1").arg(data.address, 0, 16);
+ if (data.type == WatchpointAtExpression)
+ return tr("Data breakpoint at %1").arg(data.expression);
return empty;
}
break;
PROPERTY(QByteArray, condition, setCondition)
GETTER(int, lineNumber)
PROPERTY(quint64, address, setAddress)
-PROPERTY(QByteArray, expression, setExpression)
+PROPERTY(QString, expression, setExpression)
PROPERTY(int, ignoreCount, setIgnoreCount)
bool BreakHandler::isEnabled(BreakpointId id) const
return BreakHandler::tracepointIcon();
if (data.type == WatchpointAtAddress)
return BreakHandler::watchpointIcon();
+ if (data.type == WatchpointAtExpression)
+ return BreakHandler::watchpointIcon();
if (!data.enabled)
return BreakHandler::disabledBreakpointIcon();
if (state == BreakpointInserted)
void setFileName(BreakpointId, const QString &fileName);
QString functionName(BreakpointId id) const;
void setFunctionName(BreakpointId, const QString &functionName);
- QByteArray expression(BreakpointId id) const;
- void setExpression(BreakpointId, const QByteArray &expression);
+ QString expression(BreakpointId id) const;
+ void setExpression(BreakpointId, const QString &expression);
BreakpointType type(BreakpointId id) const;
void setType(BreakpointId id, const BreakpointType &type);
quint64 address(BreakpointId id) const;
int ignoreCount; //!< Ignore count associated with breakpoint.
int lineNumber; //!< Line in source file.
quint64 address; //!< Address for address based watchpoints.
- QByteArray expression; //!< Address for expression based watchpoints.
+ QString expression; //!< Expression for expression based watchpoints.
uint size; //!< Size of watched area for watchpoints.
uint bitpos; //!< Location of watched bitfield within watched area.
uint bitsize; //!< Size of watched bitfield within watched area.
QStringList types;
types << tr("File name and line number")
<< tr("Function name")
- << tr("Memory address")
+ << tr("Break on memory address")
<< tr("Break when C++ exception is thrown")
<< tr("Break when C++ exception is caught")
<< tr("Break when function \"main\" starts")
<< tr("Break when a new process is forked")
<< tr("Break when a new process is executed")
<< tr("Break when a system call is executed")
- << tr("Break on data access (Watchpoint at address)")
- << tr("Break on data access (Watchpoint at expression)");
+ << tr("Break on data access at fixed address)")
+ << tr("Break on data access at address given by expression)");
QTC_ASSERT(types.size() == WatchpointAtExpression, return; )
m_ui.comboBoxType->addItems(types);
m_ui.pathChooserFileName->setExpectedKind(Utils::PathChooser::File);
}
QString DebuggerEngine::msgWatchpointByExpressionTriggered(BreakpointId id,
- const int number, const QByteArray &expr)
+ const int number, const QString &expr)
{
return id
- ? tr("Watchpoint %1 (%2) at %3 %4 triggered.")
- .arg(id).arg(number).arg(_(expr))
- : tr("Internal watchpoint %1 at %2 %4 triggered.")
- .arg(number).arg(_(expr));
+ ? tr("Data breakpoint %1 (%2) at %3 triggered.")
+ .arg(id).arg(number).arg(expr)
+ : tr("Internal data breakpoint %1 at %2 triggered.")
+ .arg(number).arg(expr);
}
QString DebuggerEngine::msgWatchpointByExpressionTriggered(BreakpointId id,
- const int number, const QByteArray &expr, const QString &threadId)
+ const int number, const QString &expr, const QString &threadId)
{
return id
- ? tr("Watchpoint %1 (%2) at %3 in thread %4 triggered.")
- .arg(id).arg(number).arg(_(expr)).arg(threadId)
- : tr("Internal watchpoint %1 at %2 in thread %4 triggered.")
- .arg(number).arg(_(expr)).arg(threadId);
+ ? tr("Data breakpoint %1 (%2) at %3 in thread %4 triggered.")
+ .arg(id).arg(number).arg(expr).arg(threadId)
+ : tr("Internal data breakpoint %1 at %2 in thread %4 triggered.")
+ .arg(number).arg(expr).arg(threadId);
}
QString DebuggerEngine::msgWatchpointByAddressTriggered(BreakpointId id,
const int number, quint64 address)
{
return id
- ? tr("Watchpoint %1 (%2) at 0x%3 triggered.")
+ ? tr("Data breakpoint %1 (%2) at 0x%3 triggered.")
.arg(id).arg(number).arg(address, 0, 16)
- : tr("Internal watchpoint %1 at 0x%2 triggered.")
+ : tr("Internal data breakpoint %1 at 0x%2 triggered.")
.arg(number).arg(address, 0, 16);
}
const int number, quint64 address, const QString &threadId)
{
return id
- ? tr("Watchpoint %1 (%2) at 0x%3 in thread %4 triggered.")
+ ? tr("Data breakpoint %1 (%2) at 0x%3 in thread %4 triggered.")
.arg(id).arg(number).arg(address, 0, 16).arg(threadId)
- : tr("Internal watchpoint %1 at 0x%2 in thread %3 triggered.")
+ : tr("Internal data breakpoint %1 at 0x%2 in thread %3 triggered.")
.arg(id).arg(number).arg(address, 0, 16).arg(threadId);
}
static QString msgWatchpointByAddressTriggered(BreakpointId id,
int number, quint64 address, const QString &threadId);
static QString msgWatchpointByExpressionTriggered(BreakpointId id,
- int number, const QByteArray &expr);
+ int number, const QString &expr);
static QString msgWatchpointByExpressionTriggered(BreakpointId id,
- int number, const QByteArray &expr, const QString &threadId);
+ int number, const QString &expr, const QString &threadId);
static QString msgBreakpointTriggered(BreakpointId id,
int number, const QString &threadId);
static QString msgStopped(const QString &reason = QString());
LocalsINameRole,
LocalsEditTypeRole, // A QVariant::type describing the item
LocalsIntegerBaseRole, // Number base 16, 10, 8, 2
+ LocalsNameRole,
LocalsExpressionRole,
LocalsRawExpressionRole,
LocalsExpandedRole, // The preferred expanded state to the view
return;
}
if (type == WatchpointAtExpression) {
- postCommand("watch " + handler->expression(id),
+ postCommand("watch " + handler->expression(id).toLocal8Bit(),
NeedsStop | RebuildBreakpointModel,
CB(handleWatchInsert), id);
return;
case LocalsEditTypeRole:
return QVariant(editType(data));
+ case LocalsNameRole:
+ return QVariant(data.name);
+
case LocalsIntegerBaseRole:
if (isPointerType(data.type)) // Pointers using 0x-convention
return QVariant(16);
setFrameStyle(QFrame::NoFrame);
setAttribute(Qt::WA_MacShowFocusRect, false);
- setWindowTitle(tr("Locals and Watchers"));
+ setWindowTitle(tr("Locals and Expressions"));
setIndentation(indentation() * 9/10);
setUniformRowHeights(true);
setItemDelegate(new WatchDelegate(this));
static inline QString addWatchActionText(QString exp)
{
if (exp.isEmpty())
- return WatchWindow::tr("Watch Expression");
+ return WatchWindow::tr("Evaluate Expression");
if (exp.size() > 30) {
exp.truncate(30);
exp.append(QLatin1String("..."));
}
- return WatchWindow::tr("Watch Expression \"%1\"").arg(exp);
+ return WatchWindow::tr("Evaluate Expression \"%1\"").arg(exp);
}
// Text for add watch action with truncated expression
static inline QString removeWatchActionText(QString exp)
{
if (exp.isEmpty())
- return WatchWindow::tr("Remove Watch Expression");
+ return WatchWindow::tr("Remove Evaluated Expression");
if (exp.size() > 30) {
exp.truncate(30);
exp.append(QLatin1String("..."));
}
- return WatchWindow::tr("Remove Watch Expression \"%1\"").arg(exp);
+ return WatchWindow::tr("Remove Evaluated Expression \"%1\"").arg(exp);
}
static inline void copyToClipboard(const QString &clipboardText)
const uint size = sizeOf(mi0);
const quint64 pointerValue = pointerValueOf(mi0);
const QString exp = mi0.data(LocalsExpressionRole).toString();
+ const QString name = mi0.data(LocalsNameRole).toString();
const QString type = mi2.data().toString();
+ // Offer to open address pointed to or variable address.
+ const bool createPointerActions = pointerValue && pointerValue != address;
+
const QStringList alternativeFormats =
mi0.data(LocalsTypeFormatListRole).toStringList();
const int typeFormat =
const unsigned engineCapabilities = engine->debuggerCapabilities();
const bool canHandleWatches = engineCapabilities & AddWatcherCapability;
const DebuggerState state = engine->state();
- const bool canInsertWatches = (state==InferiorStopOk) || ((state==InferiorRunOk) && engine->acceptsWatchesWhileRunning());
-
- QMenu menu;
- QAction *actInsertNewWatchItem = menu.addAction(tr("Insert New Watch Item"));
- actInsertNewWatchItem->setEnabled(canHandleWatches && canInsertWatches);
- QAction *actSelectWidgetToWatch = menu.addAction(tr("Select Widget to Watch"));
- actSelectWidgetToWatch->setEnabled(canHandleWatches && (engine->canWatchWidgets()));
-
- // Offer to open address pointed to or variable address.
- const bool createPointerActions = pointerValue && pointerValue != address;
-
- menu.addSeparator();
+ const bool canInsertWatches = state == InferiorStopOk
+ || (state == InferiorRunOk && engine->acceptsWatchesWhileRunning());
+ QMenu breakpointMenu;
+ breakpointMenu.setTitle(tr("Add Data Breakpoint..."));
QAction *actSetWatchpointAtVariableAddress = 0;
QAction *actSetWatchpointAtPointerValue = 0;
const bool canSetWatchpoint = engineCapabilities & WatchpointByAddressCapability;
if (canSetWatchpoint && address) {
actSetWatchpointAtVariableAddress =
- new QAction(tr("Add Watchpoint at Object's Address (0x%1)")
- .arg(address, 0, 16), &menu);
+ new QAction(tr("Add Data Breakpoint at Object's Address (0x%1)")
+ .arg(address, 0, 16), &breakpointMenu);
actSetWatchpointAtVariableAddress->
setChecked(mi0.data(LocalsIsWatchpointAtAddressRole).toBool());
if (createPointerActions) {
actSetWatchpointAtPointerValue =
- new QAction(tr("Add Watchpoint at Referenced Address (0x%1)")
- .arg(pointerValue, 0, 16), &menu);
+ new QAction(tr("Add Data Breakpoint at Referenced Address (0x%1)")
+ .arg(pointerValue, 0, 16), &breakpointMenu);
actSetWatchpointAtPointerValue->setCheckable(true);
actSetWatchpointAtPointerValue->
setChecked(mi0.data(LocalsIsWatchpointAtPointerValueRole).toBool());
}
} else {
actSetWatchpointAtVariableAddress =
- new QAction(tr("Add Watchpoint"), &menu);
+ new QAction(tr("Add Data Breakpoint"), &breakpointMenu);
actSetWatchpointAtVariableAddress->setEnabled(false);
}
actSetWatchpointAtVariableAddress->setToolTip(
- tr("Setting a watchpoint on an address will cause the program "
- "to stop when the data at the address it modified."));
+ tr("Setting a data breakpoint on an address will cause the program "
+ "to stop when the data at the address is modified."));
+
+ QAction *actSetWatchpointAtExpression =
+ new QAction(tr("Add Data Breakpoint at Expression \"%1\"").arg(name),
+ &breakpointMenu);
+ actSetWatchpointAtExpression->setToolTip(
+ tr("Setting a data breakpoint on an expression will cause the program "
+ "to stop when the data at the address given by the expression "
+ "is modified."));
+
+ breakpointMenu.addAction(actSetWatchpointAtVariableAddress);
+ if (actSetWatchpointAtPointerValue)
+ breakpointMenu.addAction(actSetWatchpointAtPointerValue);
+ breakpointMenu.addAction(actSetWatchpointAtExpression);
+
+ QMenu menu;
+ QAction *actInsertNewWatchItem = menu.addAction(tr("Insert New Evaluated Expression"));
+ actInsertNewWatchItem->setEnabled(canHandleWatches && canInsertWatches);
+ QAction *actSelectWidgetToWatch = menu.addAction(tr("Select Widget to Watch"));
+ actSelectWidgetToWatch->setEnabled(canHandleWatches && (engine->canWatchWidgets()));
+
+ menu.addSeparator();
QAction *actWatchExpression = new QAction(addWatchActionText(exp), &menu);
actWatchExpression->setEnabled(canHandleWatches && !exp.isEmpty());
menu.addAction(actSelectWidgetToWatch);
menu.addMenu(&formatMenu);
menu.addMenu(&memoryMenu);
- menu.addAction(actSetWatchpointAtVariableAddress);
- if (actSetWatchpointAtPointerValue)
- menu.addAction(actSetWatchpointAtPointerValue);
+ menu.addMenu(&breakpointMenu);
menu.addAction(actCopy);
menu.addAction(actCopyValue);
menu.addSeparator();
} else if (act == actOpenMemoryEditorStackLayout) {
addStackLayoutMemoryView(currentEngine(), false, mi0.model(), ev->globalPos(), this);
} else if (act == actSetWatchpointAtVariableAddress) {
- setWatchpoint(address, size);
+ setWatchpointAtAddress(address, size);
} else if (act == actSetWatchpointAtPointerValue) {
- setWatchpoint(pointerValue, 1);
+ setWatchpointAtAddress(pointerValue, sizeof(void *)); // FIXME: an approximation..
+ } else if (act == actSetWatchpointAtExpression) {
+ setWatchpointAtExpression(name);
} else if (act == actSelectWidgetToWatch) {
grabMouse(Qt::CrossCursor);
m_grabbing = true;
model()->setData(index, value, role);
}
-void WatchWindow::setWatchpoint(quint64 address, unsigned size)
+void WatchWindow::setWatchpointAtAddress(quint64 address, unsigned size)
{
BreakpointParameters data(WatchpointAtAddress);
data.address = address;
breakHandler()->appendBreakpoint(data);
}
+void WatchWindow::setWatchpointAtExpression(const QString &exp)
+{
+ BreakpointParameters data(WatchpointAtExpression);
+ data.expression = exp;
+ BreakpointId id = breakHandler()->findWatchpoint(data);
+ if (id) {
+ qDebug() << "WATCHPOINT EXISTS";
+ // removeBreakpoint(index);
+ return;
+ }
+ breakHandler()->appendBreakpoint(data);
+}
+
} // namespace Internal
} // namespace Debugger
void editItem(const QModelIndex &idx);
void resetHelper(const QModelIndex &idx);
- void setWatchpoint(quint64 address, unsigned size);
+ void setWatchpointAtAddress(quint64 address, unsigned size);
+ void setWatchpointAtExpression(const QString &exp);
void setModelData(int role, const QVariant &value = QVariant(),
const QModelIndex &index = QModelIndex());