diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index 84860b07547..6526ffddfe8 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -1029,26 +1029,29 @@ bool BreakHandler::needsChange(BreakpointId id) const
return it->needsChange();
}
-void BreakHandler::setResponse(BreakpointId id, const BreakpointResponse &response, bool takeOver)
+void BreakHandler::setResponse(BreakpointId id,
+ const BreakpointResponse &response, bool takeOver)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
BreakpointItem &item = it.value();
item.response = response;
item.destroyMarker();
- // Take over corrected values from response
+ // Take over corrected values from response.
if (takeOver) {
if (item.data.type == BreakpointByFileAndLine
&& response.correctedLineNumber > 0)
item.data.lineNumber = response.correctedLineNumber;
- if ((item.data.type == BreakpointByFileAndLine || item.data.type == BreakpointByFunction)
- && !response.module.isEmpty())
+ if ((item.data.type == BreakpointByFileAndLine
+ || item.data.type == BreakpointByFunction)
+ && !response.module.isEmpty())
item.data.module = response.module;
}
updateMarker(id);
}
-void BreakHandler::setBreakpointData(BreakpointId id, const BreakpointParameters &data)
+void BreakHandler::setBreakpointData(BreakpointId id,
+ const BreakpointParameters &data)
{
Iterator it = m_storage.find(id);
QTC_ASSERT(it != m_storage.end(), return);
@@ -1178,6 +1181,18 @@ QString BreakHandler::BreakpointItem::toToolTip() const
case BreakpointAtCatch:
t = tr("Breakpoint at \"catch\"");
break;
+ case BreakpointAtFork:
+ t = tr("Breakpoint at \"fork\"");
+ break;
+ case BreakpointAtExec:
+ t = tr("Breakpoint at \"exec\"");
+ break;
+ case BreakpointAtVFork:
+ t = tr("Breakpoint at \"vfork\"");
+ break;
+ case BreakpointAtSysCall:
+ t = tr("Breakpoint at \"syscall\"");
+ break;
case BreakpointAtMain:
t = tr("Breakpoint at Function \"main()\"");
break;
diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h
index a6513b81a3f..6c85561cfa4 100644
--- a/src/plugins/debugger/breakpoint.h
+++ b/src/plugins/debugger/breakpoint.h
@@ -59,6 +59,10 @@ enum BreakpointType
BreakpointAtThrow,
BreakpointAtCatch,
BreakpointAtMain,
+ BreakpointAtFork,
+ BreakpointAtExec,
+ BreakpointAtVFork,
+ BreakpointAtSysCall,
Watchpoint
};
diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp
index 9a5415fc279..355a822299a 100644
--- a/src/plugins/debugger/breakwindow.cpp
+++ b/src/plugins/debugger/breakwindow.cpp
@@ -123,7 +123,10 @@ BreakpointDialog::BreakpointDialog(unsigned engineCapabilities, QWidget *parent)
m_ui.setupUi(this);
QStringList types;
types << tr("File and Line Number") << tr("Function Name") << tr("Address")
- << tr("throw") << tr("catch") << tr("Function \"main()\"")
+ << tr("throw") << tr("catch")
+ << tr("Function \"main()\"")
+ << tr("fork") << tr("exec")
+ << tr("vfork") << tr("syscall")
<< tr("Address (Watchpoint)");
QTC_ASSERT(types.size() == Watchpoint, return; )
m_ui.comboBoxType->addItems(types);
@@ -137,20 +140,26 @@ BreakpointDialog::BreakpointDialog(unsigned engineCapabilities, QWidget *parent)
m_ui.lineEditModule->setToolTip(moduleToolTip);
const QString commandToolTip =
tr("Debugger command to be executed when the breakpoint is hit.\n"
- "gdb allows for specifying a sequence of commands separated by the delimiter '\\n'.");
+ "gdb allows for specifying a sequence of commands separated by "
+ "the delimiter '\\n'.");
m_ui.lineEditCommand->setToolTip(commandToolTip);
m_ui.labelCommand->setToolTip(commandToolTip);
m_ui.spinBoxIgnoreCount->setMinimum(0);
m_ui.spinBoxIgnoreCount->setMaximum(2147483647);
const QString pathToolTip =
- tr("
Determines how the path is specified when setting breakpoints:
"
- "- Use Engine Default: Preferred setting of the debugger engine.
"
- "- Use Full Path: Pass full path, avoiding ambiguities should files of the same "
- "name exist in several modules. This is the engine default for CDB and LLDB.
"
- "- Use File Name: Pass the file name only. This is useful "
- "when using a source tree whose location does not match the one used when building the modules. "
- "It is the engine default for gdb as using full paths can be slow with this engine.
"
- "
");
+ tr("Determines how the path is specified "
+ "when setting breakpoints:
"
+ "- Use Engine Default: Preferred setting of the "
+ "debugger engine.
"
+ "- Use Full Path: Pass full path, avoiding ambiguities "
+ "should files of the same name exist in several modules. "
+ "This is the engine default for CDB and LLDB.
"
+ "- Use File Name: Pass the file name only. This is "
+ "useful when using a source tree whose location does "
+ "not match the one used when building the modules. "
+ "It is the engine default for gdb as using full paths can "
+ "be slow with this engine.
"
+ "
");
m_ui.labelUseFullPath->setToolTip(pathToolTip);
m_ui.comboBoxPathUsage->setToolTip(pathToolTip);
}
@@ -328,6 +337,10 @@ void BreakpointDialog::typeChanged(int)
case BreakpointAtThrow:
case BreakpointAtCatch:
case BreakpointAtMain:
+ case BreakpointAtFork:
+ case BreakpointAtExec:
+ case BreakpointAtVFork:
+ case BreakpointAtSysCall:
break;
case BreakpointByAddress:
case Watchpoint:
@@ -351,6 +364,10 @@ void BreakpointDialog::typeChanged(int)
break;
case BreakpointAtThrow:
case BreakpointAtCatch:
+ case BreakpointAtFork:
+ case BreakpointAtExec:
+ case BreakpointAtVFork:
+ case BreakpointAtSysCall:
clearOtherParts(AllConditionParts|ModulePart|TracePointPart);
setPartsEnabled(AllConditionParts|TracePointPart);
break;
@@ -384,10 +401,11 @@ bool BreakpointDialog::showDialog(BreakpointParameters *data)
}
// Dialog allowing changing properties of multiple breakpoints at a time.
-class MultiBreakPointsDialog : public QDialog {
+class MultiBreakPointsDialog : public QDialog
+{
Q_OBJECT
public:
- explicit MultiBreakPointsDialog(unsigned engineCapabilities = AllDebuggerCapabilities, QWidget *parent = 0);
+ MultiBreakPointsDialog(unsigned engineCapabilities, QWidget *parent = 0);
QString condition() const { return m_ui.lineEditCondition->text(); }
int ignoreCount() const { return m_ui.spinBoxIgnoreCount->value(); }
@@ -403,7 +421,7 @@ private:
Ui::BreakCondition m_ui;
};
-MultiBreakPointsDialog::MultiBreakPointsDialog(unsigned engineCapabilities,QWidget *parent) :
+MultiBreakPointsDialog::MultiBreakPointsDialog(unsigned engineCapabilities, QWidget *parent) :
QDialog(parent)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
@@ -577,10 +595,6 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
QAction *addBreakpointAction =
new QAction(tr("Add Breakpoint..."), this);
- QAction *breakAtThrowAction =
- new QAction(tr("Set Breakpoint at \"throw\""), this);
- QAction *breakAtCatchAction =
- new QAction(tr("Set Breakpoint at \"catch\""), this);
menu.addAction(addBreakpointAction);
menu.addAction(deleteAction);
@@ -592,11 +606,6 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
//menu.addAction(deleteByFileAction);
menu.addSeparator();
menu.addAction(synchronizeAction);
- if (engineCapabilities & BreakOnThrowAndCatchCapability) {
- menu.addSeparator();
- menu.addAction(breakAtThrowAction);
- menu.addAction(breakAtCatchAction);
- }
menu.addSeparator();
menu.addAction(debuggerCore()->action(UseToolTipsInBreakpointsView));
menu.addAction(debuggerCore()->action(UseAddressInBreakpointsView));
@@ -627,10 +636,6 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev)
setBreakpointsEnabled(selectedIds, !enabled);
else if (act == addBreakpointAction)
addBreakpoint();
- else if (act == breakAtThrowAction)
- handler->appendBreakpoint(BreakpointParameters(BreakpointAtThrow));
- else if (act == breakAtCatchAction)
- handler->appendBreakpoint(BreakpointParameters(BreakpointAtCatch));
}
void BreakWindow::setBreakpointsEnabled(const BreakpointIds &ids, bool enabled)
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index cf3775f7b26..3a9e6b46906 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -171,12 +171,13 @@ enum DebuggerCapabilities
BreakOnThrowAndCatchCapability = 0x200,
BreakConditionCapability = 0x400, //!< Conditional Breakpoints
BreakModuleCapability = 0x800, //!< Breakpoint specification includes module
- TracePointCapability = 0x1000, //!< Breakpoint specification includes module
+ TracePointCapability = 0x1000,
ReturnFromFunctionCapability = 0x2000,
CreateFullBacktraceCapability = 0x4000,
AddWatcherCapability = 0x8000,
WatchpointCapability = 0x10000,
ShowModuleSymbolsCapability = 0x20000,
+ CatchCapability = 0x40000, //!< fork, vfork, syscall
AllDebuggerCapabilities = 0xFFFFFFFF
};
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 3e0a8591764..ffe0230cbb8 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1873,7 +1873,8 @@ unsigned GdbEngine::debuggerCapabilities() const
| CreateFullBacktraceCapability
| WatchpointCapability
| AddWatcherCapability
- | ShowModuleSymbolsCapability;
+ | ShowModuleSymbolsCapability
+ | CatchCapability;
if (startParameters().startMode == AttachCore)
return caps;
@@ -2314,6 +2315,16 @@ void GdbEngine::attemptAdjustBreakpointLocation(BreakpointId id)
CB(handleInfoLine), id);
}
+void GdbEngine::handleCatchInsert(const GdbResponse &response)
+{
+ BreakHandler *handler = breakHandler();
+ BreakpointId id(response.cookie.toInt());
+ if (response.resultClass == GdbResultDone) {
+ handler->notifyBreakpointInsertOk(id);
+ attemptAdjustBreakpointLocation(id);
+ }
+}
+
void GdbEngine::handleBreakInsert1(const GdbResponse &response)
{
BreakHandler *handler = breakHandler();
@@ -2644,12 +2655,33 @@ void GdbEngine::insertBreakpoint(BreakpointId id)
BreakHandler *handler = breakHandler();
QTC_ASSERT(handler->state(id) == BreakpointInsertRequested, /**/);
handler->notifyBreakpointInsertProceeding(id);
- if (handler->type(id) == Watchpoint) {
+ BreakpointType type = handler->type(id);
+ if (type == Watchpoint) {
postCommand("watch " + addressSpec(handler->address(id)),
NeedsStop | RebuildBreakpointModel,
CB(handleWatchInsert), id);
return;
}
+ if (type == BreakpointAtFork) {
+ postCommand("catch fork", NeedsStop | RebuildBreakpointModel,
+ CB(handleCatchInsert), id);
+ return;
+ }
+ if (type == BreakpointAtVFork) {
+ postCommand("catch vfork", NeedsStop | RebuildBreakpointModel,
+ CB(handleCatchInsert), id);
+ return;
+ }
+ if (type == BreakpointAtExec) {
+ postCommand("catch exec", NeedsStop | RebuildBreakpointModel,
+ CB(handleCatchInsert), id);
+ return;
+ }
+ if (type == BreakpointAtSysCall) {
+ postCommand("catch syscall", NeedsStop | RebuildBreakpointModel,
+ CB(handleCatchInsert), id);
+ return;
+ }
QByteArray cmd = "xxx";
if (handler->isTracepoint(id)) {
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 82a9c9fa0ad..95ff06c09a3 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -370,6 +370,7 @@ private: ////////// View & Data Stuff //////////
void handleBreakInfo(const GdbResponse &response);
void handleBreakThreadSpec(const GdbResponse &response);
void handleWatchInsert(const GdbResponse &response);
+ void handleCatchInsert(const GdbResponse &response);
void handleInfoLine(const GdbResponse &response);
void extractDataFromInfoBreak(const QString &output, BreakpointId);
void updateBreakpointDataFromOutput(BreakpointId id, const GdbMi &bkpt);
diff --git a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp
index 9fa776d6168..64415556c93 100644
--- a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp
+++ b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp
@@ -44,6 +44,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -2397,6 +2398,16 @@ void testBoostSharedPtr()
#endif
}
+void testFork()
+{
+ QProcess proc;
+ proc.start("/bin/ls");
+ proc.waitForFinished();
+ QByteArray ba = proc.readAllStandardError();
+ ba.append('x');
+ ba.append('x');
+}
+
int main(int argc, char *argv[])
{
testPrivate();
@@ -2493,7 +2504,7 @@ int main(int argc, char *argv[])
testBoostOptional();
testBoostSharedPtr();
- //*(int *)0 = 0;
+ testFork();
testQObject(argc, argv);