debugger: implement basic support for gdb's 'return' command

Returning a value is not yet supported.
This commit is contained in:
hjk
2010-02-15 16:02:41 +01:00
parent feb181ce5e
commit c6e88eec0e
8 changed files with 52 additions and 7 deletions

View File

@@ -154,6 +154,7 @@ struct DebuggerManagerActions
QAction *runToFunctionAction; QAction *runToFunctionAction;
QAction *jumpToLineAction1; // in the Debug menu QAction *jumpToLineAction1; // in the Debug menu
QAction *jumpToLineAction2; // in the text editor context menu QAction *jumpToLineAction2; // in the text editor context menu
QAction *returnFromFunctionAction;
QAction *nextAction; QAction *nextAction;
QAction *snapshotAction; QAction *snapshotAction;
QAction *watchAction1; // in the Debug menu QAction *watchAction1; // in the Debug menu

View File

@@ -53,9 +53,11 @@ const char * const C_GDBDEBUGGER = "Gdb Debugger";
const char * const GDBRUNNING = "Gdb.Running"; const char * const GDBRUNNING = "Gdb.Running";
const char * const DEBUGGER_COMMON_SETTINGS_ID = "A.Common"; const char * const DEBUGGER_COMMON_SETTINGS_ID = "A.Common";
const char * const DEBUGGER_COMMON_SETTINGS_NAME = QT_TRANSLATE_NOOP("Debugger", "Common"); const char * const DEBUGGER_COMMON_SETTINGS_NAME =
QT_TRANSLATE_NOOP("Debugger", "Common");
const char * const DEBUGGER_SETTINGS_CATEGORY = "O.Debugger"; const char * const DEBUGGER_SETTINGS_CATEGORY = "O.Debugger";
const char * const DEBUGGER_SETTINGS_TR_CATEGORY = QT_TRANSLATE_NOOP("Debugger", "Debugger"); const char * const DEBUGGER_SETTINGS_TR_CATEGORY =
QT_TRANSLATE_NOOP("Debugger", "Debugger");
namespace Internal { namespace Internal {
enum { debug = 0 }; enum { debug = 0 };
@@ -65,9 +67,10 @@ namespace Internal {
const char * const LD_PRELOAD_ENV_VAR = "LD_PRELOAD"; const char * const LD_PRELOAD_ENV_VAR = "LD_PRELOAD";
#endif #endif
} } // namespace Internal
} // namespace Constants } // namespace Constants
enum DebuggerState enum DebuggerState
{ {
DebuggerNotReady, // Debugger not started DebuggerNotReady, // Debugger not started
@@ -121,6 +124,7 @@ enum DebuggerCapabilities
ReloadModuleCapability = 0x80, ReloadModuleCapability = 0x80,
ReloadModuleSymbolsCapability = 0x100, ReloadModuleSymbolsCapability = 0x100,
BreakOnThrowAndCatchCapability = 0x200, BreakOnThrowAndCatchCapability = 0x200,
ReturnFromFunctionCapability = 0x400,
}; };
enum LogChannel enum LogChannel

View File

@@ -485,7 +485,11 @@ void DebuggerManager::init()
d->m_actions.runToLineAction1 = new QAction(tr("Run to Line"), this); d->m_actions.runToLineAction1 = new QAction(tr("Run to Line"), this);
d->m_actions.runToLineAction2 = new QAction(tr("Run to Line"), this); d->m_actions.runToLineAction2 = new QAction(tr("Run to Line"), this);
d->m_actions.runToFunctionAction = new QAction(tr("Run to Outermost Function"), this); d->m_actions.runToFunctionAction =
new QAction(tr("Run to Outermost Function"), this);
d->m_actions.returnFromFunctionAction =
new QAction(tr("Immediately Return From Inner Function"), this);
d->m_actions.jumpToLineAction1 = new QAction(tr("Jump to Line"), this); d->m_actions.jumpToLineAction1 = new QAction(tr("Jump to Line"), this);
d->m_actions.jumpToLineAction2 = new QAction(tr("Jump to Line"), this); d->m_actions.jumpToLineAction2 = new QAction(tr("Jump to Line"), this);
@@ -524,6 +528,8 @@ void DebuggerManager::init()
this, SLOT(jumpToLineExec())); this, SLOT(jumpToLineExec()));
connect(d->m_actions.jumpToLineAction2, SIGNAL(triggered()), connect(d->m_actions.jumpToLineAction2, SIGNAL(triggered()),
this, SLOT(jumpToLineExec())); this, SLOT(jumpToLineExec()));
connect(d->m_actions.returnFromFunctionAction, SIGNAL(triggered()),
this, SLOT(returnExec()));
connect(d->m_actions.watchAction1, SIGNAL(triggered()), connect(d->m_actions.watchAction1, SIGNAL(triggered()),
this, SLOT(addToWatchWindow())); this, SLOT(addToWatchWindow()));
connect(d->m_actions.watchAction2, SIGNAL(triggered()), connect(d->m_actions.watchAction2, SIGNAL(triggered()),
@@ -1185,6 +1191,13 @@ void DebuggerManager::nextExec()
d->m_engine->nextExec(); d->m_engine->nextExec();
} }
void DebuggerManager::returnExec()
{
QTC_ASSERT(d->m_engine, return);
resetLocation();
d->m_engine->returnExec();
}
void DebuggerManager::watchPoint() void DebuggerManager::watchPoint()
{ {
if (QAction *action = qobject_cast<QAction *>(sender())) if (QAction *action = qobject_cast<QAction *>(sender()))
@@ -1742,8 +1755,8 @@ void DebuggerManager::setState(DebuggerState state, bool forced)
d->m_actions.watchAction1->setEnabled(true); d->m_actions.watchAction1->setEnabled(true);
d->m_actions.watchAction2->setEnabled(true); d->m_actions.watchAction2->setEnabled(true);
d->m_actions.breakAction->setEnabled(true); d->m_actions.breakAction->setEnabled(true);
d->m_actions.snapshotAction->setEnabled( d->m_actions.snapshotAction->
stopped && (engineCapabilities & SnapshotCapability)); setEnabled(stopped && (engineCapabilities & SnapshotCapability));
const bool interruptIsExit = !running; const bool interruptIsExit = !running;
if (interruptIsExit) { if (interruptIsExit) {
@@ -1762,6 +1775,8 @@ void DebuggerManager::setState(DebuggerState state, bool forced)
d->m_actions.runToLineAction1->setEnabled(stopped); d->m_actions.runToLineAction1->setEnabled(stopped);
d->m_actions.runToLineAction2->setEnabled(stopped); d->m_actions.runToLineAction2->setEnabled(stopped);
d->m_actions.runToFunctionAction->setEnabled(stopped); d->m_actions.runToFunctionAction->setEnabled(stopped);
d->m_actions.returnFromFunctionAction->
setEnabled(stopped && (engineCapabilities & ReturnFromFunctionCapability));
const bool canJump = stopped && (engineCapabilities & JumpToLineCapability); const bool canJump = stopped && (engineCapabilities & JumpToLineCapability);
d->m_actions.jumpToLineAction1->setEnabled(canJump); d->m_actions.jumpToLineAction1->setEnabled(canJump);

View File

@@ -235,6 +235,7 @@ public slots:
void stepOutExec(); void stepOutExec();
void nextExec(); void nextExec();
void continueExec(); void continueExec();
void returnExec();
void detachDebugger(); void detachDebugger();
void makeSnapshot(); void makeSnapshot();

View File

@@ -119,6 +119,7 @@ const char * const RUN_TO_LINE2 = "Debugger.RunToLine2";
const char * const RUN_TO_FUNCTION = "Debugger.RunToFunction"; const char * const RUN_TO_FUNCTION = "Debugger.RunToFunction";
const char * const JUMP_TO_LINE1 = "Debugger.JumpToLine1"; const char * const JUMP_TO_LINE1 = "Debugger.JumpToLine1";
const char * const JUMP_TO_LINE2 = "Debugger.JumpToLine2"; const char * const JUMP_TO_LINE2 = "Debugger.JumpToLine2";
const char * const RETURN_FROM_FUNCTION = "Debugger.ReturnFromFunction";
const char * const SNAPSHOT = "Debugger.Snapshot"; const char * const SNAPSHOT = "Debugger.Snapshot";
const char * const TOGGLE_BREAK = "Debugger.ToggleBreak"; const char * const TOGGLE_BREAK = "Debugger.ToggleBreak";
const char * const BREAK_BY_FUNCTION = "Debugger.BreakByFunction"; const char * const BREAK_BY_FUNCTION = "Debugger.BreakByFunction";
@@ -799,6 +800,10 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
Constants::JUMP_TO_LINE1, debuggercontext); Constants::JUMP_TO_LINE1, debuggercontext);
mdebug->addAction(cmd); mdebug->addAction(cmd);
cmd = am->registerAction(actions.returnFromFunctionAction,
Constants::RETURN_FROM_FUNCTION, debuggercontext);
mdebug->addAction(cmd);
#ifdef USE_REVERSE_DEBUGGING #ifdef USE_REVERSE_DEBUGGING
cmd = am->registerAction(actions.reverseDirectionAction, cmd = am->registerAction(actions.reverseDirectionAction,
Constants::REVERSE, debuggercontext); Constants::REVERSE, debuggercontext);

View File

@@ -1711,7 +1711,8 @@ unsigned GdbEngine::debuggerCapabilities() const
| AutoDerefPointersCapability | DisassemblerCapability | AutoDerefPointersCapability | DisassemblerCapability
| RegisterCapability | ShowMemoryCapability | RegisterCapability | ShowMemoryCapability
| JumpToLineCapability | ReloadModuleCapability | JumpToLineCapability | ReloadModuleCapability
| ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability; | ReloadModuleSymbolsCapability | BreakOnThrowAndCatchCapability
| ReturnFromFunctionCapability;
} }
void GdbEngine::continueInferiorInternal() void GdbEngine::continueInferiorInternal()
@@ -1902,6 +1903,21 @@ void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber)
#endif #endif
} }
void GdbEngine::returnExec()
{
QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
setTokenBarrier();
setState(InferiorRunningRequested);
showStatusMessage(tr("Immediate return from function requested..."), 5000);
postCommand("-exec-finish", RunRequest, CB(handleExecReturn));
}
void GdbEngine::handleExecReturn(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
updateAll();
}
}
/*! /*!
\fn void GdbEngine::setTokenBarrier() \fn void GdbEngine::setTokenBarrier()
\brief Discard the results of all pending watch-updating commands. \brief Discard the results of all pending watch-updating commands.

View File

@@ -296,10 +296,12 @@ private: ////////// Inferior Management //////////
virtual void runToFunctionExec(const QString &functionName); virtual void runToFunctionExec(const QString &functionName);
// void handleExecRunToFunction(const GdbResponse &response); // void handleExecRunToFunction(const GdbResponse &response);
virtual void jumpToLineExec(const QString &fileName, int lineNumber); virtual void jumpToLineExec(const QString &fileName, int lineNumber);
virtual void returnExec();
void handleExecContinue(const GdbResponse &response); void handleExecContinue(const GdbResponse &response);
void handleExecStep(const GdbResponse &response); void handleExecStep(const GdbResponse &response);
void handleExecNext(const GdbResponse &response); void handleExecNext(const GdbResponse &response);
void handleExecReturn(const GdbResponse &response);
qint64 inferiorPid() const { return m_manager->inferiorPid(); } qint64 inferiorPid() const { return m_manager->inferiorPid(); }
void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); } void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); }

View File

@@ -82,6 +82,7 @@ public:
virtual void nextExec() = 0; virtual void nextExec() = 0;
virtual void stepIExec() = 0; virtual void stepIExec() = 0;
virtual void nextIExec() = 0; virtual void nextIExec() = 0;
virtual void returnExec() {}
virtual void continueInferior() = 0; virtual void continueInferior() = 0;
virtual void interruptInferior() = 0; virtual void interruptInferior() = 0;