From 47fa65be6c26c04a484eb82d648587a155738b00 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 11 Feb 2010 17:29:10 +0100 Subject: [PATCH] debugger: some basic support for 'catch catch' and 'catch throw' Hidden in the Breakpoints context menu. --- share/qtcreator/gdbmacros/dumper.py | 10 ++++++-- src/plugins/debugger/breakhandler.cpp | 8 ++++--- src/plugins/debugger/breakwindow.cpp | 25 ++++++++++++++++---- src/plugins/debugger/breakwindow.h | 6 ++++- src/plugins/debugger/debuggeractions.cpp | 16 +++++++++++++ src/plugins/debugger/debuggeractions.h | 4 +++- src/plugins/debugger/debuggerconstants.h | 1 + src/plugins/debugger/debuggermanager.cpp | 2 +- src/plugins/debugger/debuggerplugin.cpp | 2 ++ src/plugins/debugger/gdb/gdbengine.cpp | 2 +- src/plugins/debugger/gdb/pythongdbengine.cpp | 2 +- src/plugins/debugger/registerwindow.h | 2 ++ tests/manual/gdbdebugger/simple/app.cpp | 22 +++++++++++++++++ 13 files changed, 87 insertions(+), 15 deletions(-) diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py index 24a9b4f0d4..9082a752f0 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("") >= 0: # bp.address.append("") diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 478beb5b23..07b78a74e3 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 05809ff593..634b5927b1 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 18a39ba7ba..9233d6f15a 100644 --- a/src/plugins/debugger/breakwindow.h +++ b/src/plugins/debugger/breakwindow.h @@ -33,6 +33,9 @@ #include 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 b5d01f00d8..a5d824cd19 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 a22eea601e..b8a60faba9 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 2f9b255443..9b6cdb636c 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 f44f5761f4..61d0ba1ce7 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 3aaf948e0e..54a70bbbee 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 79ba31c3f1..7203927c61 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 d51cfa8dc4..2fb02fc00e 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 = ""; } } diff --git a/src/plugins/debugger/registerwindow.h b/src/plugins/debugger/registerwindow.h index 3e7da419cf..9d960d789e 100644 --- a/src/plugins/debugger/registerwindow.h +++ b/src/plugins/debugger/registerwindow.h @@ -33,9 +33,11 @@ #include 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 4133b0c799..204990ca3a 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(); -- GitLab