forked from qt-creator/qt-creator
debugger: add support for temporary breakpoints
Change-Id: I841c37d21932da0ef354dbbe2fd75cec2fae86d6 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -321,6 +321,8 @@ void BreakHandler::saveBreakpoints()
|
|||||||
map.insert(_("threadspec"), data.threadSpec);
|
map.insert(_("threadspec"), data.threadSpec);
|
||||||
if (!data.enabled)
|
if (!data.enabled)
|
||||||
map.insert(_("disabled"), one);
|
map.insert(_("disabled"), one);
|
||||||
|
if (data.oneShot)
|
||||||
|
map.insert(_("oneshot"), one);
|
||||||
if (data.pathUsage != BreakpointPathUsageEngineDefault)
|
if (data.pathUsage != BreakpointPathUsageEngineDefault)
|
||||||
map.insert(_("usefullpath"), QString::number(data.pathUsage));
|
map.insert(_("usefullpath"), QString::number(data.pathUsage));
|
||||||
if (data.tracepoint)
|
if (data.tracepoint)
|
||||||
@@ -373,6 +375,9 @@ void BreakHandler::loadBreakpoints()
|
|||||||
v = map.value(_("disabled"));
|
v = map.value(_("disabled"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data.enabled = !v.toInt();
|
data.enabled = !v.toInt();
|
||||||
|
v = map.value(_("oneshot"));
|
||||||
|
if (v.isValid())
|
||||||
|
data.oneShot = v.toInt();
|
||||||
v = map.value(_("usefullpath"));
|
v = map.value(_("usefullpath"));
|
||||||
if (v.isValid())
|
if (v.isValid())
|
||||||
data.pathUsage = static_cast<BreakpointPathUsage>(v.toInt());
|
data.pathUsage = static_cast<BreakpointPathUsage>(v.toInt());
|
||||||
@@ -768,6 +773,13 @@ bool BreakHandler::isTracepoint(BreakpointModelId id) const
|
|||||||
return it->data.tracepoint;
|
return it->data.tracepoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BreakHandler::isOneShot(BreakpointModelId id) const
|
||||||
|
{
|
||||||
|
ConstIterator it = m_storage.find(id);
|
||||||
|
BREAK_ASSERT(it != m_storage.end(), return false);
|
||||||
|
return it->data.oneShot;
|
||||||
|
}
|
||||||
|
|
||||||
bool BreakHandler::needsChildren(BreakpointModelId id) const
|
bool BreakHandler::needsChildren(BreakpointModelId id) const
|
||||||
{
|
{
|
||||||
ConstIterator it = m_storage.find(id);
|
ConstIterator it = m_storage.find(id);
|
||||||
|
@@ -136,6 +136,7 @@ public:
|
|||||||
void updateLineNumberFromMarker(BreakpointModelId id, int lineNumber);
|
void updateLineNumberFromMarker(BreakpointModelId id, int lineNumber);
|
||||||
void setMarkerFileAndLine(BreakpointModelId id,
|
void setMarkerFileAndLine(BreakpointModelId id,
|
||||||
const QString &fileName, int lineNumber);
|
const QString &fileName, int lineNumber);
|
||||||
|
bool isOneShot(BreakpointModelId id) const;
|
||||||
bool isWatchpoint(BreakpointModelId id) const;
|
bool isWatchpoint(BreakpointModelId id) const;
|
||||||
bool isTracepoint(BreakpointModelId id) const;
|
bool isTracepoint(BreakpointModelId id) const;
|
||||||
void setTracepoint(BreakpointModelId, bool on);
|
void setTracepoint(BreakpointModelId, bool on);
|
||||||
|
@@ -180,7 +180,7 @@ BreakpointParameters::BreakpointParameters(BreakpointType t)
|
|||||||
: type(t), enabled(true), pathUsage(BreakpointPathUsageEngineDefault),
|
: type(t), enabled(true), pathUsage(BreakpointPathUsageEngineDefault),
|
||||||
ignoreCount(0), lineNumber(0), address(0), size(0),
|
ignoreCount(0), lineNumber(0), address(0), size(0),
|
||||||
bitpos(0), bitsize(0), threadSpec(-1),
|
bitpos(0), bitsize(0), threadSpec(-1),
|
||||||
tracepoint(false)
|
tracepoint(false), oneShot(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
BreakpointParts BreakpointParameters::differencesTo
|
BreakpointParts BreakpointParameters::differencesTo
|
||||||
@@ -215,31 +215,33 @@ BreakpointParts BreakpointParameters::differencesTo
|
|||||||
parts |= CommandPart;
|
parts |= CommandPart;
|
||||||
if (message != rhs.message)
|
if (message != rhs.message)
|
||||||
parts |= MessagePart;
|
parts |= MessagePart;
|
||||||
|
if (oneShot != rhs.oneShot)
|
||||||
|
parts |= OneShotPart;
|
||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BreakpointParameters::isValid() const
|
bool BreakpointParameters::isValid() const
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Debugger::Internal::BreakpointByFileAndLine:
|
case BreakpointByFileAndLine:
|
||||||
return !fileName.isEmpty() && lineNumber > 0;
|
return !fileName.isEmpty() && lineNumber > 0;
|
||||||
case Debugger::Internal::BreakpointByFunction:
|
case BreakpointByFunction:
|
||||||
return !functionName.isEmpty();
|
return !functionName.isEmpty();
|
||||||
case Debugger::Internal::WatchpointAtAddress:
|
case WatchpointAtAddress:
|
||||||
case Debugger::Internal::BreakpointByAddress:
|
case BreakpointByAddress:
|
||||||
return address != 0;
|
return address != 0;
|
||||||
case Debugger::Internal::BreakpointAtThrow:
|
case BreakpointAtThrow:
|
||||||
case Debugger::Internal::BreakpointAtCatch:
|
case BreakpointAtCatch:
|
||||||
case Debugger::Internal::BreakpointAtMain:
|
case BreakpointAtMain:
|
||||||
case Debugger::Internal::BreakpointAtFork:
|
case BreakpointAtFork:
|
||||||
case Debugger::Internal::BreakpointAtExec:
|
case BreakpointAtExec:
|
||||||
case Debugger::Internal::BreakpointAtSysCall:
|
case BreakpointAtSysCall:
|
||||||
case Debugger::Internal::BreakpointOnQmlSignalEmit:
|
case BreakpointOnQmlSignalEmit:
|
||||||
case Debugger::Internal::BreakpointAtJavaScriptThrow:
|
case BreakpointAtJavaScriptThrow:
|
||||||
break;
|
break;
|
||||||
case Debugger::Internal::WatchpointAtExpression:
|
case WatchpointAtExpression:
|
||||||
return !expression.isEmpty();
|
return !expression.isEmpty();
|
||||||
case Debugger::Internal::UnknownType:
|
case UnknownType:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@@ -174,7 +174,6 @@ enum BreakpointParts
|
|||||||
ConditionPart = 0x10,
|
ConditionPart = 0x10,
|
||||||
IgnoreCountPart = 0x20,
|
IgnoreCountPart = 0x20,
|
||||||
ThreadSpecPart = 0x40,
|
ThreadSpecPart = 0x40,
|
||||||
AllConditionParts = ConditionPart|IgnoreCountPart|ThreadSpecPart,
|
|
||||||
ModulePart = 0x80,
|
ModulePart = 0x80,
|
||||||
TracePointPart = 0x100,
|
TracePointPart = 0x100,
|
||||||
|
|
||||||
@@ -183,11 +182,16 @@ enum BreakpointParts
|
|||||||
PathUsagePart = 0x800,
|
PathUsagePart = 0x800,
|
||||||
CommandPart = 0x1000,
|
CommandPart = 0x1000,
|
||||||
MessagePart = 0x2000,
|
MessagePart = 0x2000,
|
||||||
|
OneShotPart = 0x4000,
|
||||||
|
|
||||||
|
AllConditionParts = ConditionPart|IgnoreCountPart|ThreadSpecPart
|
||||||
|
|OneShotPart,
|
||||||
|
|
||||||
AllParts = FileAndLinePart|FunctionPart
|
AllParts = FileAndLinePart|FunctionPart
|
||||||
|ExpressionPart|AddressPart|ConditionPart
|
|ExpressionPart|AddressPart|ConditionPart
|
||||||
|IgnoreCountPart|ThreadSpecPart|ModulePart|TracePointPart
|
|IgnoreCountPart|ThreadSpecPart|ModulePart|TracePointPart
|
||||||
|EnabledPart|TypePart|PathUsagePart|CommandPart|MessagePart
|
|EnabledPart|TypePart|PathUsagePart|CommandPart|MessagePart
|
||||||
|
|OneShotPart
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void operator|=(BreakpointParts &p, BreakpointParts r)
|
inline void operator|=(BreakpointParts &p, BreakpointParts r)
|
||||||
@@ -234,6 +238,7 @@ public:
|
|||||||
QString command; //!< command to execute
|
QString command; //!< command to execute
|
||||||
QString message; //!< message
|
QString message; //!< message
|
||||||
bool tracepoint;
|
bool tracepoint;
|
||||||
|
bool oneShot; //!< Should this breakpoint trigger only once?
|
||||||
};
|
};
|
||||||
|
|
||||||
class BreakpointResponse : public BreakpointParameters
|
class BreakpointResponse : public BreakpointParameters
|
||||||
|
@@ -128,6 +128,8 @@ private:
|
|||||||
QLineEdit *m_lineEditFunction;
|
QLineEdit *m_lineEditFunction;
|
||||||
QLabel *m_labelTracepoint;
|
QLabel *m_labelTracepoint;
|
||||||
QCheckBox *m_checkBoxTracepoint;
|
QCheckBox *m_checkBoxTracepoint;
|
||||||
|
QLabel *m_labelOneShot;
|
||||||
|
QCheckBox *m_checkBoxOneShot;
|
||||||
QLabel *m_labelUseFullPath;
|
QLabel *m_labelUseFullPath;
|
||||||
QLabel *m_labelModule;
|
QLabel *m_labelModule;
|
||||||
QLineEdit *m_lineEditModule;
|
QLineEdit *m_lineEditModule;
|
||||||
@@ -206,6 +208,10 @@ BreakpointDialog::BreakpointDialog(BreakpointModelId id, QWidget *parent)
|
|||||||
m_labelTracepoint = new QLabel(tr("T&racepoint only:"), groupBoxAdvanced);
|
m_labelTracepoint = new QLabel(tr("T&racepoint only:"), groupBoxAdvanced);
|
||||||
m_labelTracepoint->setBuddy(m_checkBoxTracepoint);
|
m_labelTracepoint->setBuddy(m_checkBoxTracepoint);
|
||||||
|
|
||||||
|
m_checkBoxOneShot = new QCheckBox(groupBoxAdvanced);
|
||||||
|
m_labelOneShot = new QLabel(tr("&One shot only:"), groupBoxAdvanced);
|
||||||
|
m_labelOneShot->setBuddy(m_checkBoxOneShot);
|
||||||
|
|
||||||
const QString pathToolTip =
|
const QString pathToolTip =
|
||||||
tr("<html><head/><body><p>Determines how the path is specified "
|
tr("<html><head/><body><p>Determines how the path is specified "
|
||||||
"when setting breakpoints:</p><ul>"
|
"when setting breakpoints:</p><ul>"
|
||||||
@@ -288,6 +294,7 @@ BreakpointDialog::BreakpointDialog(BreakpointModelId id, QWidget *parent)
|
|||||||
basicLayout->addRow(m_labelAddress, m_lineEditAddress);
|
basicLayout->addRow(m_labelAddress, m_lineEditAddress);
|
||||||
basicLayout->addRow(m_labelExpression, m_lineEditExpression);
|
basicLayout->addRow(m_labelExpression, m_lineEditExpression);
|
||||||
basicLayout->addRow(m_labelFunction, m_lineEditFunction);
|
basicLayout->addRow(m_labelFunction, m_lineEditFunction);
|
||||||
|
basicLayout->addRow(m_labelOneShot, m_checkBoxOneShot);
|
||||||
|
|
||||||
QFormLayout *advancedLeftLayout = new QFormLayout();
|
QFormLayout *advancedLeftLayout = new QFormLayout();
|
||||||
advancedLeftLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
advancedLeftLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||||
@@ -364,6 +371,9 @@ void BreakpointDialog::setPartsEnabled(unsigned partsMask)
|
|||||||
m_labelFunction->setEnabled(partsMask & FunctionPart);
|
m_labelFunction->setEnabled(partsMask & FunctionPart);
|
||||||
m_lineEditFunction->setEnabled(partsMask & FunctionPart);
|
m_lineEditFunction->setEnabled(partsMask & FunctionPart);
|
||||||
|
|
||||||
|
m_labelOneShot->setEnabled(partsMask & OneShotPart);
|
||||||
|
m_checkBoxOneShot->setEnabled(partsMask & OneShotPart);
|
||||||
|
|
||||||
m_labelAddress->setEnabled(partsMask & AddressPart);
|
m_labelAddress->setEnabled(partsMask & AddressPart);
|
||||||
m_lineEditAddress->setEnabled(partsMask & AddressPart);
|
m_lineEditAddress->setEnabled(partsMask & AddressPart);
|
||||||
m_labelExpression->setEnabled(partsMask & ExpressionPart);
|
m_labelExpression->setEnabled(partsMask & ExpressionPart);
|
||||||
@@ -415,6 +425,8 @@ void BreakpointDialog::clearOtherParts(unsigned partsMask)
|
|||||||
if (invertedPartsMask & ModulePart)
|
if (invertedPartsMask & ModulePart)
|
||||||
m_lineEditModule->clear();
|
m_lineEditModule->clear();
|
||||||
|
|
||||||
|
if (partsMask & OneShotPart)
|
||||||
|
m_checkBoxOneShot->setChecked(false);
|
||||||
if (invertedPartsMask & TracePointPart) {
|
if (invertedPartsMask & TracePointPart) {
|
||||||
m_checkBoxTracepoint->setChecked(false);
|
m_checkBoxTracepoint->setChecked(false);
|
||||||
m_textEditCommands->clear();
|
m_textEditCommands->clear();
|
||||||
@@ -449,6 +461,8 @@ void BreakpointDialog::getParts(unsigned partsMask, BreakpointParameters *data)
|
|||||||
if (partsMask & ModulePart)
|
if (partsMask & ModulePart)
|
||||||
data->module = m_lineEditModule->text();
|
data->module = m_lineEditModule->text();
|
||||||
|
|
||||||
|
if (partsMask & OneShotPart)
|
||||||
|
data->oneShot = m_checkBoxOneShot->isChecked();
|
||||||
if (partsMask & TracePointPart) {
|
if (partsMask & TracePointPart) {
|
||||||
data->tracepoint = m_checkBoxTracepoint->isChecked();
|
data->tracepoint = m_checkBoxTracepoint->isChecked();
|
||||||
data->command = m_textEditCommands->toPlainText().trimmed();
|
data->command = m_textEditCommands->toPlainText().trimmed();
|
||||||
@@ -498,6 +512,8 @@ void BreakpointDialog::setParts(unsigned mask, const BreakpointParameters &data)
|
|||||||
if (mask & ModulePart)
|
if (mask & ModulePart)
|
||||||
m_lineEditModule->setText(data.module);
|
m_lineEditModule->setText(data.module);
|
||||||
|
|
||||||
|
if (mask & OneShotPart)
|
||||||
|
m_checkBoxOneShot->setChecked(data.oneShot);
|
||||||
if (mask & TracePointPart)
|
if (mask & TracePointPart)
|
||||||
m_checkBoxTracepoint->setChecked(data.tracepoint);
|
m_checkBoxTracepoint->setChecked(data.tracepoint);
|
||||||
}
|
}
|
||||||
|
@@ -633,8 +633,13 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
|||||||
QByteArray nr = result.findChild("id").data();
|
QByteArray nr = result.findChild("id").data();
|
||||||
BreakpointResponseId rid(nr);
|
BreakpointResponseId rid(nr);
|
||||||
BreakpointModelId id = handler->findBreakpointByResponseId(rid);
|
BreakpointModelId id = handler->findBreakpointByResponseId(rid);
|
||||||
if (id.isValid())
|
if (id.isValid()) {
|
||||||
|
// This also triggers when a temporary breakpoint is hit.
|
||||||
|
// We do not really want that, as this loses all information.
|
||||||
|
// FIXME: Use a special marker for this case?
|
||||||
|
if (!handler->isOneShot(id))
|
||||||
handler->removeAlienBreakpoint(id);
|
handler->removeAlienBreakpoint(id);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "IGNORED ASYNC OUTPUT"
|
qDebug() << "IGNORED ASYNC OUTPUT"
|
||||||
<< asyncClass << result.toString();
|
<< asyncClass << result.toString();
|
||||||
@@ -3140,6 +3145,10 @@ void GdbEngine::insertBreakpoint(BreakpointModelId id)
|
|||||||
} else {
|
} else {
|
||||||
cmd = "-break-insert ";
|
cmd = "-break-insert ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (handler->isOneShot(id))
|
||||||
|
cmd += "-t ";
|
||||||
|
|
||||||
//if (!data->condition.isEmpty())
|
//if (!data->condition.isEmpty())
|
||||||
// cmd += "-c " + data->condition + ' ';
|
// cmd += "-c " + data->condition + ' ';
|
||||||
cmd += breakpointLocation(id);
|
cmd += breakpointLocation(id);
|
||||||
|
Reference in New Issue
Block a user