diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py index 24a9b4f0d4b3218f1d547d1eb102fcaa94fce398..9082a752f05b9c1616be675347b9ebe9e2d60700 100644 --- a/share/qtcreator/gdbmacros/dumper.py +++ b/share/qtcreator/gdbmacros/dumper.py @@ -110,6 +110,7 @@ def listOfBreakpoints(d): #4.1 y 0x08056673 in Foo at ../app.cpp:126\n" #4.2 y 0x0805678b in Foo at ../app.cpp:126\n" #5 hw watchpoint keep y &main\n" + #6 breakpoint keep y 0xb6cf18e5 <__cxa_throw+5>\n" lines = catchCliOutput("info break") lines.reverse() @@ -128,10 +129,15 @@ def listOfBreakpoints(d): number = line[0:5] pos0x = line.find(" 0x") posin = line.find(" in ", pos0x) + poslt = line.find(" <", pos0x) posat = line.find(" at ", posin) poscol = line.find(":", posat) - if pos0x < posin and pos0x != -1: - bp.address.append(line[pos0x + 1 : posin]) + if pos0x != -1: + if pos0x < posin: + bp.address.append(line[pos0x + 1 : posin]) + elif pos0x < poslt: + bp.address.append(line[pos0x + 1 : poslt]) + bp.function = line[poslt + 2 : line.find('>', poslt)] # Take "no address" as indication that the bp is pending. #if line.find("<PENDING>") >= 0: # bp.address.append("<PENDING>") diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 478beb5b23303ad83873d080fc21235664d741a7..07b78a74e36b629969998927d5772772c4811315 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -335,13 +335,15 @@ void BreakHandler::clear() int BreakHandler::findBreakpoint(const BreakpointData &needle) { - // looks for a breakpoint we might refer to + // Search a breakpoint we might refer to. + qDebug() << "NEEDLE: " << needle.toString(); for (int index = 0; index != size(); ++index) { const BreakpointData *data = at(index); - // clear hit. + // Clear hit. + qDebug() << " TEST: " << data->toString(); if (data->bpNumber == needle.bpNumber) return index; - // at least at a position we were looking for + // At least at a position we were looking for. // FIXME: breaks multiple breakpoints at the same location if (fileNameMatch(data->fileName, needle.bpFileName) && data->lineNumber == needle.bpLineNumber) diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index 05809ff5937def8203af3b06190aa9692499d8a6..634b5927b19ba945d62eac3b2f2391c1ad4f5fff 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -79,8 +79,8 @@ public: // /////////////////////////////////////////////////////////////////////// -BreakWindow::BreakWindow(QWidget *parent) - : QTreeView(parent), m_alwaysResizeColumnsToContents(false) +BreakWindow::BreakWindow(DebuggerManager *manager) + : m_manager(manager), m_alwaysResizeColumnsToContents(false) { QAction *act = theDebuggerAction(UseAlternatingRowColors); setWindowTitle(tr("Breakpoints")); @@ -143,6 +143,7 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) si = normalizeIndexes(si); const int rowCount = itemModel->rowCount(); + const unsigned engineCapabilities = m_manager->debuggerCapabilities(); QAction *deleteAction = new QAction(tr("Delete breakpoint"), &menu); deleteAction->setEnabled(si.size() > 0); @@ -190,12 +191,18 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) toggleEnabledAction->setEnabled(si.size() > 0); const bool fullpath = si.isEmpty() || itemModel->data(idx2, Qt::UserRole).toBool(); - const QString str6 = fullpath ? tr("Use short path") : tr("Use full path"); + const QString str6 = fullpath ? tr("Use Short Path") : tr("Use Full Path"); QAction *pathAction = new QAction(str6, &menu); pathAction->setEnabled(si.size() > 0); - QAction *breakAtFunctionAction = new QAction(tr("Set Breakpoint at Function..."), this); - QAction *breakAtMainAction = new QAction(tr("Set Breakpoint at Function \"main\""), this); + QAction *breakAtFunctionAction = + new QAction(tr("Set Breakpoint at Function..."), this); + QAction *breakAtMainAction = + new QAction(tr("Set Breakpoint at Function \"main\""), this); + QAction *breakAtThrowAction = + new QAction(tr("Set Breakpoint at \"throw\""), this); + QAction *breakAtCatchAction = + new QAction(tr("Set Breakpoint at \"catch\""), this); menu.addAction(deleteAction); menu.addAction(editConditionAction); @@ -209,6 +216,10 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) menu.addSeparator(); menu.addAction(breakAtFunctionAction); menu.addAction(breakAtMainAction); + if (engineCapabilities & BreakOnThrowAndCatchCapability) { + menu.addAction(breakAtThrowAction); + menu.addAction(breakAtCatchAction); + } menu.addSeparator(); menu.addAction(theDebuggerAction(UseToolTipsInBreakpointsView)); menu.addAction(theDebuggerAction(UseAddressInBreakpointsView)); @@ -246,6 +257,10 @@ void BreakWindow::contextMenuEvent(QContextMenuEvent *ev) emit breakByFunctionRequested(dlg.functionName()); } else if (act == breakAtMainAction) emit breakByFunctionMainRequested(); + else if (act == breakAtThrowAction) + emit breakByFunctionRequested("__cxa_throw"); + else if (act == breakAtCatchAction) + emit breakByFunctionRequested("__cxa_begin_catch"); } void BreakWindow::setBreakpointsEnabled(const QModelIndexList &list, bool enabled) diff --git a/src/plugins/debugger/breakwindow.h b/src/plugins/debugger/breakwindow.h index 18a39ba7ba2ef854f238306b292242083db37631..9233d6f15a902b61f6adf3cc86e2311e9cdb2897 100644 --- a/src/plugins/debugger/breakwindow.h +++ b/src/plugins/debugger/breakwindow.h @@ -33,6 +33,9 @@ #include <QtGui/QTreeView> namespace Debugger { + +class DebuggerManager; + namespace Internal { class BreakWindow : public QTreeView @@ -40,7 +43,7 @@ class BreakWindow : public QTreeView Q_OBJECT public: - BreakWindow(QWidget *parent = 0); + explicit BreakWindow(DebuggerManager *manager); public slots: void resizeColumnsToContents(); @@ -70,6 +73,7 @@ private: void setBreakpointsEnabled(const QModelIndexList &list, bool enabled); void setBreakpointsFullPath(const QModelIndexList &list, bool fullpath); + DebuggerManager *m_manager; bool m_alwaysResizeColumnsToContents; }; diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index b5d01f00d881eee42558bc7d66b9765cc45f506b..a5d824cd19558fec1c80e48eb9c1f5404f67a43e 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -279,6 +279,22 @@ DebuggerSettings *DebuggerSettings::instance() item->setSettingsKey(debugModeGroup, QLatin1String("UsePreciseBreakpoints")); instance->insertItem(UsePreciseBreakpoints, item); + item = new SavedAction(instance); + item->setText(tr("Break on \"throw\"")); + item->setCheckable(true); + item->setDefaultValue(false); + item->setValue(false); + item->setSettingsKey(debugModeGroup, QLatin1String("BreakOnThrow")); + instance->insertItem(BreakOnThrow, item); + + item = new SavedAction(instance); + item->setText(tr("Break on \"catch\"")); + item->setCheckable(true); + item->setDefaultValue(false); + item->setValue(false); + item->setSettingsKey(debugModeGroup, QLatin1String("BreakOnCatch")); + instance->insertItem(BreakOnCatch, item); + // // Settings // diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index a22eea601e02a691555a2c3c53eafd1009a03fa0..b8a60faba9f8d65f34f1ba20d091c1c75f1a709e 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -130,7 +130,9 @@ enum DebuggerActionCode SelectedPluginBreakpoints, NoPluginBreakpoints, SelectedPluginBreakpointsPattern, - UsePreciseBreakpoints + UsePreciseBreakpoints, + BreakOnThrow, + BreakOnCatch }; // singleton access diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index 2f9b2554434eeaf8e9162047f159202d58c0e6b5..9b6cdb636c720979a31aea0616f700391b82baee 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -120,6 +120,7 @@ enum DebuggerCapabilities JumpToLineCapability = 0x40, ReloadModuleCapability = 0x80, ReloadModuleSymbolsCapability = 0x100, + BreakOnThrowAndCatchCapability = 0x200, }; enum LogChannel diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index f44f5761f4badcaf993f5717d6827ab27a5a0cdb..61d0ba1ce74279e749b4277c921f20dd375b9c1b 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -351,7 +351,7 @@ void DebuggerManager::init() d->m_statusLabel = new QLabel; d->m_statusLabel->setMinimumSize(QSize(30, 10)); - d->m_breakWindow = new BreakWindow; + d->m_breakWindow = new BreakWindow(this); d->m_modulesWindow = new ModulesWindow(this); d->m_outputWindow = new DebuggerOutputWindow; d->m_registerWindow = new RegisterWindow(this); diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 3aaf948e0eb416eadb5556d81bfb3fec4095651a..54a70bbbee7a760519ce3cc0374b92cf6dbb850c 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -368,6 +368,8 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent) m_group.insert(theDebuggerAction(LogTimeStamps), 0); m_group.insert(theDebuggerAction(VerboseLog), 0); m_group.insert(theDebuggerAction(UsePreciseBreakpoints), 0); + m_group.insert(theDebuggerAction(BreakOnThrow), 0); + m_group.insert(theDebuggerAction(BreakOnCatch), 0); #ifdef USE_REVERSE_DEBUGGING m_ui.checkBoxEnableReverseDebugging->hide(); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 79ba31c3f15303e72a8cafe2797fedada6dbc2a9..7203927c61b3b3d34254d578ef3e0269f06f6959 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1708,7 +1708,7 @@ unsigned GdbEngine::debuggerCapabilities() const | AutoDerefPointersCapability | DisassemblerCapability | RegisterCapability | ShowMemoryCapability | JumpToLineCapability | ReloadModuleCapability - | ReloadModuleSymbolsCapability; + | ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability; } void GdbEngine::continueInferiorInternal() diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp index d51cfa8dc496666f672458df6e631b5660fc6028..2fb02fc00ea5398a47d5debea05563918bb24418 100644 --- a/src/plugins/debugger/gdb/pythongdbengine.cpp +++ b/src/plugins/debugger/gdb/pythongdbengine.cpp @@ -169,7 +169,7 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response) && bp->fileName != bp->bpFileName) bp->markerFileName = bp->fileName; } else { - QTC_ASSERT(false, qDebug() << child.toString()); + QTC_ASSERT(false, qDebug() << child.toString() << bpNumber); //bp->bpNumber = "<unavailable>"; } } diff --git a/src/plugins/debugger/registerwindow.h b/src/plugins/debugger/registerwindow.h index 3e7da419cf8166613f151377edce3f5b163b8eb8..9d960d789e50ed641b6ea8f97294b062216524c9 100644 --- a/src/plugins/debugger/registerwindow.h +++ b/src/plugins/debugger/registerwindow.h @@ -33,9 +33,11 @@ #include <QtGui/QTreeView> namespace Debugger { + class DebuggerManager; namespace Internal { + class RegisterWindow : public QTreeView { Q_OBJECT diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 4133b0c7993a753c11ba493f21fa04b735eb0c6b..204990ca3a534c25a27d9ea68c950a87be95437a 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -230,6 +230,27 @@ void testQByteArray() ba += 2; } +static void throwit1() +{ + throw 14; +} + +static void throwit() +{ + throwit1(); +} + +int testCatchThrow() +{ + int gotit = 0; + try { + throwit(); + } catch (int what) { + gotit = what; + } + return gotit; +} + void testQDateTime() { QDateTime date; @@ -1422,6 +1443,7 @@ int main(int argc, char *argv[]) testIO(); testHidden(); testArray(); + testCatchThrow(); testQByteArray(); testStdDeque();