diff --git a/src/plugins/debugger/commonoptionspage.ui b/src/plugins/debugger/commonoptionspage.ui index c7cbc68b28d..821c930252d 100644 --- a/src/plugins/debugger/commonoptionspage.ui +++ b/src/plugins/debugger/commonoptionspage.ui @@ -55,6 +55,16 @@ + + + + Enable reverse debugging + + + + + + diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index e6358718bde..568e922c2d6 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -294,6 +294,12 @@ DebuggerSettings *DebuggerSettings::instance() item->setCheckable(true); instance->insertItem(SkipKnownFrames, item); + item = new SavedAction(instance); + item->setSettingsKey(debugModeGroup, QLatin1String("EnableReverseDebugging")); + item->setText(tr("Enable reverse debugging")); + item->setCheckable(true); + instance->insertItem(EnableReverseDebugging, item); + item = new SavedAction(instance); item->setSettingsKey(debugModeGroup, QLatin1String("AllPluginBreakpoints")); item->setDefaultValue(true); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index a45a60e32b3..b65981957bf 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -112,6 +112,7 @@ enum DebuggerActionCode // Running SkipKnownFrames, + EnableReverseDebugging, // Breakpoints SynchronizeBreakpoints, diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h index 119b6afe2a0..720df8aca6f 100644 --- a/src/plugins/debugger/debuggerconstants.h +++ b/src/plugins/debugger/debuggerconstants.h @@ -47,6 +47,7 @@ const char * const STEPOUT = "Debugger.StepOut"; const char * const NEXT = "Debugger.NextLine"; const char * const STEPI = "Debugger.StepInstruction"; const char * const NEXTI = "Debugger.NextInstruction"; +const char * const REVERSE = "Debugger.ReverseDirection"; const char * const M_DEBUG_VIEWS = "Debugger.Menu.View.Debug"; diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp index 6768c63d025..b2a19fe8b1e 100644 --- a/src/plugins/debugger/debuggermanager.cpp +++ b/src/plugins/debugger/debuggermanager.cpp @@ -411,6 +411,12 @@ void DebuggerManager::init() m_watchAction = new QAction(this); m_watchAction->setText(tr("Add to Watch Window")); + m_reverseDirectionAction = new QAction(this); + m_reverseDirectionAction->setText(tr("Reverse Direction")); + m_reverseDirectionAction->setCheckable(true); + m_reverseDirectionAction->setChecked(false); + //m_reverseDirectionAction->setIcon(QIcon(":/debugger/images/debugger_stepoverproc_small.png")); + // For usuage hints oin focus{In,Out} connect(m_continueAction, SIGNAL(triggered()), this, SLOT(continueExec())); @@ -1504,6 +1510,11 @@ void DebuggerManager::reloadFullStack() m_engine->reloadFullStack(); } +bool DebuggerManager::isReverseDebugging() const +{ + return m_reverseDirectionAction->isChecked(); +} + ////////////////////////////////////////////////////////////////////// // diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h index c28b8d45ffd..00b339cda87 100644 --- a/src/plugins/debugger/debuggermanager.h +++ b/src/plugins/debugger/debuggermanager.h @@ -220,6 +220,7 @@ private: virtual bool qtDumperLibraryEnabled() const = 0; virtual QString qtDumperLibraryName() const = 0; virtual void showQtDumperLibraryWarning(const QString &details = QString()) = 0; + virtual bool isReverseDebugging() const = 0; virtual qint64 inferiorPid() const = 0; @@ -288,6 +289,7 @@ public slots: void nextIExec(); void continueExec(); void detachDebugger(); + void reverseDirection(); void addToWatchWindow(); void updateWatchModel(); @@ -358,6 +360,7 @@ private: virtual bool qtDumperLibraryEnabled() const; virtual QString qtDumperLibraryName() const; virtual void showQtDumperLibraryWarning(const QString &details = QString()); + virtual bool isReverseDebugging() const; // // internal implementation @@ -461,6 +464,7 @@ private: QAction *m_sepAction; QAction *m_stepIAction; QAction *m_nextIAction; + QAction *m_reverseDirectionAction; QWidget *m_breakWindow; QWidget *m_disassemblerWindow; diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 250a065f736..09f61b81e4b 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -120,6 +120,7 @@ const char * const STEPOUT_KEY = "Shift+F7"; const char * const NEXT_KEY = "F6"; const char * const STEPI_KEY = "Shift+F9"; const char * const NEXTI_KEY = "Shift+F6"; +const char * const REVERSE_KEY = ""; const char * const RUN_TO_LINE_KEY = "Shift+F8"; const char * const RUN_TO_FUNCTION_KEY = "Ctrl+F6"; const char * const JUMP_TO_LINE_KEY = "Alt+D,Alt+L"; @@ -135,6 +136,7 @@ const char * const STEPOUT_KEY = "Shift+F11"; const char * const NEXT_KEY = "F10"; const char * const STEPI_KEY = ""; const char * const NEXTI_KEY = ""; +const char * const REVERSE_KEY = "F12"; const char * const RUN_TO_LINE_KEY = ""; const char * const RUN_TO_FUNCTION_KEY = ""; const char * const JUMP_TO_LINE_KEY = ""; @@ -284,7 +286,9 @@ QWidget *CommonOptionsPage::createPage(QWidget *parent) m_ui.checkBoxSkipKnownFrames); m_group.insert(theDebuggerAction(UseToolTips), m_ui.checkBoxUseToolTips); - m_group.insert(theDebuggerAction(MaximalStackDepth), + m_group.insert(theDebuggerAction(EnableReverseDebugging), + m_ui.checkBoxEnableReverseDebugging); + m_group.insert(theDebuggerAction(MaximalStackDepth), m_ui.spinBoxMaximalStackDepth); return w; @@ -671,6 +675,11 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess Constants::JUMP_TO_LINE, debuggercontext); mdebug->addAction(cmd); + cmd = am->registerAction(m_manager->m_reverseDirectionAction, + Constants::REVERSE, debuggercontext); + cmd->setDefaultKeySequence(QKeySequence(Constants::REVERSE_KEY)); + mdebug->addAction(cmd); + sep = new QAction(this); sep->setSeparator(true); cmd = am->registerAction(sep, QLatin1String("Debugger.Sep3"), globalcontext); @@ -816,6 +825,8 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess debugToolBar->addAction(am->command(Constants::STEPI)->action()); debugToolBar->addAction(am->command(Constants::NEXTI)->action()); debugToolBar->addSeparator(); + debugToolBar->addAction(am->command(Constants::REVERSE)->action()); + debugToolBar->addSeparator(); debugToolBar->addWidget(new QLabel(tr("Threads:"))); QComboBox *threadBox = new QComboBox; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index a3eb6f0c7e4..8f578bfead8 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -928,6 +928,10 @@ void GdbEngine::handleAqcuiredInferior() if (theDebuggerBoolSetting(ListSourceFiles)) reloadSourceFiles(); + // Reverse debugging. FIXME: Should only be used when available. + if (theDebuggerBoolSetting(EnableReverseDebugging)) + postCommand(_("target record")); + tryLoadDebuggingHelpers(); #ifndef Q_OS_MAC @@ -1664,14 +1668,20 @@ void GdbEngine::stepExec() { setTokenBarrier(); qq->notifyInferiorRunningRequested(); - postCommand(_("-exec-step"), CB(handleExecRun)); + if (qq->isReverseDebugging()) + postCommand(_("reverse-step"), CB(handleExecRun)); + else + postCommand(_("-exec-step"), CB(handleExecRun)); } void GdbEngine::stepIExec() { setTokenBarrier(); qq->notifyInferiorRunningRequested(); - postCommand(_("-exec-step-instruction"), CB(handleExecRun)); + if (qq->isReverseDebugging()) + postCommand(_("reverse-stepi"), CB(handleExecRun)); + else + postCommand(_("-exec-step-instruction"), CB(handleExecRun)); } void GdbEngine::stepOutExec() @@ -1685,14 +1695,20 @@ void GdbEngine::nextExec() { setTokenBarrier(); qq->notifyInferiorRunningRequested(); - postCommand(_("-exec-next"), CB(handleExecRun)); + if (qq->isReverseDebugging()) + postCommand(_("reverse-next"), CB(handleExecRun)); + else + postCommand(_("-exec-next"), CB(handleExecRun)); } void GdbEngine::nextIExec() { setTokenBarrier(); qq->notifyInferiorRunningRequested(); - postCommand(_("-exec-next-instruction"), CB(handleExecRun)); + if (qq->isReverseDebugging()) + postCommand(_("reverse-nexti"), CB(handleExecRun)); + else + postCommand(_("exec-next-instruction"), CB(handleExecRun)); } void GdbEngine::runToLineExec(const QString &fileName, int lineNumber) diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index 12adff1b833..ae4569ad504 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -945,6 +945,13 @@ void testQVectorOfQList() Q_UNUSED(pv); } + +void testNoArgumentName(int i, int, int k) +{ + i = 1; + k = 2; +} + void foo() {} void foo(int) {} void foo(QList) {} @@ -1082,6 +1089,8 @@ int main(int argc, char *argv[]) QString hallo = "hallo"; QStringList list; list << "aaa" << "bbb" << "cc"; + + testNoArgumentName(1, 2, 3); testIO(); testHidden(); testArray();