Commit 9e7a4564 authored by hjk's avatar hjk

debugger: refactor startup logic

parent f2c7d33f
......@@ -374,7 +374,7 @@ void CdbEngine::startupChecks()
syncDebuggerPaths();
}
void CdbEngine::startEngine()
void CdbEngine::setupEngine()
{
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
const DebuggerStartParameters &sp = startParameters();
......@@ -385,8 +385,6 @@ void CdbEngine::startEngine()
m_d->checkVersion();
if (m_d->m_hDebuggeeProcess) {
warning(QLatin1String("Internal error: Attempt to start debugger while another process is being debugged."));
setState(EngineStartFailed, Q_FUNC_INFO, __LINE__);
setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
notifyEngineStartFailed();
return;
}
......@@ -394,8 +392,6 @@ void CdbEngine::startEngine()
case AttachCore:
case AttachToRemote:
warning(QLatin1String("Internal error: Mode not supported."));
setState(EngineStartFailed, Q_FUNC_INFO, __LINE__);
setState(DebuggerNotReady, Q_FUNC_INFO, __LINE__);
notifyEngineStartFailed();
break;
default:
......@@ -404,7 +400,6 @@ void CdbEngine::startEngine()
m_d->m_mode = sp.startMode;
m_d->clearDisplay();
m_d->m_inferiorStartupComplete = false;
setState(EngineStarted, Q_FUNC_INFO, __LINE__);
// Options
QString errorMessage;
if (!m_d->setBreakOnThrow(theDebuggerBoolSetting(BreakOnThrow), &errorMessage))
......@@ -426,10 +421,19 @@ void CdbEngine::startEngine()
}
}
m_d->m_dumper->reset(dumperLibName, dumperEnabled);
notifyEngineStartOk();
}
setState(InferiorStarting, Q_FUNC_INFO, __LINE__);
showStatusMessage("Starting Debugger", messageTimeOut);
void CdbEngine::setupInferior()
{
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state());
notifyInferiorSetupOk();
}
void CdbEngine::runEngine()
{
QTC_ASSERT(m_state == InferiorSetupOk, qDebug() << m_state);
showStatusMessage("Starting Debugger", messageTimeOut);
bool rc = false;
bool needWatchTimer = false;
m_d->clearForRun();
......@@ -470,11 +474,10 @@ void CdbEngine::startEngine()
if (rc) {
if (needWatchTimer)
m_d->startWatchTimer();
notifyEngineStarted();
notifyInferiorSetupOk();
} else {
warning(errorMessage);
setState(InferiorStartFailed, Q_FUNC_INFO, __LINE__);
notifyEngineStartFailed();
notifyInferiorSetupFailed();
}
}
......
......@@ -57,7 +57,9 @@ public:
virtual void shutdown();
virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
virtual void startEngine();
virtual void setupEngine();
virtual void setupInferior();
virtual void runEngine();
virtual void exitDebugger();
virtual void detachDebugger();
virtual void updateWatchData(const WatchData &data);
......
......@@ -80,13 +80,13 @@ enum DebuggerState
DebuggerNotReady, // Debugger not started
EngineStarting, // Engine starts
EngineStarted,
EngineStartFailed,
EngineStarted,
InferiorUnrunnable, // Used in the core dump adapter
InferiorStarting,
// InferiorStarted, // Use InferiorRunningRequested or InferiorStopped
InferiorStartFailed,
InferiorSettingUp,
InferiorSetupFailed,
InferiorSetupOk,
InferiorRunningRequested, // Debuggee requested to run
InferiorRunningRequested_Kill, // Debuggee requested to run, but want to kill it
......
......@@ -146,8 +146,9 @@ const char *DebuggerEngine::stateName(int s)
SN(EngineStarting)
SN(EngineStarted)
SN(EngineStartFailed)
SN(InferiorStarting)
SN(InferiorStartFailed)
SN(InferiorSettingUp)
SN(InferiorSetupFailed)
SN(InferiorSetupOk)
SN(InferiorRunningRequested)
SN(InferiorRunningRequested_Kill)
SN(InferiorRunning)
......@@ -224,6 +225,10 @@ public slots:
void breakpointEnableDisableMarginActionTriggered();
void handleContextMenuRequest(const QVariant &parameters);
void doSetupInferior();
void doRunEngine();
void doShutdown();
public:
DebuggerEngine *m_engine; // Not owned.
DebuggerRunControl *m_runControl; // Not owned.
......@@ -636,7 +641,7 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
->setEnabled(engineCapabilities & DisassemblerCapability);
setState(EngineStarting);
startEngine();
setupEngine();
}
void DebuggerEngine::breakByFunctionMain()
......@@ -910,16 +915,18 @@ static bool isAllowedTransition(int from, int to)
case EngineStarting:
return to == EngineStarted || to == EngineStartFailed;
case EngineStarted:
return to == InferiorStarting || to == EngineShuttingDown;
case EngineStartFailed:
return to == DebuggerNotReady;
case EngineStarted:
return to == InferiorSettingUp || to == EngineShuttingDown;
case InferiorStarting:
return to == InferiorRunningRequested || to == InferiorStopped
|| to == InferiorStartFailed || to == InferiorUnrunnable;
case InferiorStartFailed:
case InferiorSettingUp:
return to == InferiorSetupOk || to == InferiorSetupFailed;
case InferiorSetupFailed:
return to == EngineShuttingDown;
case InferiorSetupOk:
return to == InferiorRunningRequested || to == InferiorStopped
|| to == InferiorUnrunnable;
case InferiorRunningRequested:
return to == InferiorRunning || to == InferiorStopped
......@@ -956,16 +963,66 @@ static bool isAllowedTransition(int from, int to)
return false;
}
void DebuggerEngine::notifyEngineStarted()
void DebuggerEngine::notifyEngineStartFailed()
{
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
setState(EngineStartFailed);
d->m_runControl->debuggingFinished();
d->m_runControl->startFailed();
QTimer::singleShot(0, this, SLOT(doShutdown()));
}
void DebuggerEngine::notifyEngineStartOk()
{
QTC_ASSERT(state() == EngineStarting, /**/);
QTC_ASSERT(state() == EngineStarting, qDebug() << state());
setState(EngineStarted);
d->m_runControl->startSuccessful();
QTimer::singleShot(0, d, SLOT(doSetupInferior()));
}
void DebuggerEngine::notifyEngineStartFailed()
void DebuggerEnginePrivate::doSetupInferior()
{
QTC_ASSERT(state() == EngineStarting, /**/);
setState(EngineStartFailed);
QTC_ASSERT(m_state == EngineStarted, qDebug() << m_state);
m_engine->setState(InferiorSettingUp);
m_engine->setupInferior();
}
// Default implemention, can be overridden.
void DebuggerEngine::setupInferior()
{
QTC_ASSERT(state() == EngineStarted, qDebug() << state());
notifyInferiorSetupOk();
}
void DebuggerEngine::notifyInferiorSetupFailed()
{
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state());
setState(InferiorSetupFailed);
QTimer::singleShot(0, d, SLOT(doShutdown()));
}
void DebuggerEngine::notifyInferiorSetupOk()
{
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state());
setState(InferiorSetupOk);
QTimer::singleShot(0, d, SLOT(doRunEngine()));
}
void DebuggerEnginePrivate::doRunEngine()
{
QTC_ASSERT(m_state == InferiorSetupOk, qDebug() << m_state);
m_engine->runEngine();
}
// Default implemention, can be overridden.
void DebuggerEngine::runEngine()
{
QTC_ASSERT(state() == InferiorSetupOk, qDebug() << state());
}
void DebuggerEnginePrivate::doShutdown()
{
m_engine->shutdown();
}
void DebuggerEngine::setState(DebuggerState state, bool forced)
......@@ -987,11 +1044,6 @@ void DebuggerEngine::setState(DebuggerState state, bool forced)
if (state != oldState) {
if (state == DebuggerNotReady) {
d->m_runControl->debuggingFinished();
} else if (state == EngineStarted) {
d->m_runControl->startSuccessful();
} else if (state == EngineStartFailed) {
d->m_runControl->debuggingFinished();
d->m_runControl->startFailed();
}
}
}
......@@ -1004,7 +1056,7 @@ bool DebuggerEngine::debuggerActionsEnabled() const
bool DebuggerEngine::debuggerActionsEnabled(DebuggerState state)
{
switch (state) {
case InferiorStarting:
case InferiorSettingUp:
case InferiorRunningRequested:
case InferiorRunning:
case InferiorUnrunnable:
......@@ -1015,7 +1067,8 @@ bool DebuggerEngine::debuggerActionsEnabled(DebuggerState state)
case EngineStarting:
case EngineStarted:
case EngineStartFailed:
case InferiorStartFailed:
case InferiorSetupOk:
case InferiorSetupFailed:
case InferiorRunningRequested_Kill:
case InferiorStopping_Kill:
case InferiorStopFailed:
......@@ -1023,7 +1076,7 @@ bool DebuggerEngine::debuggerActionsEnabled(DebuggerState state)
case InferiorShutDown:
case InferiorShutdownFailed:
case EngineShuttingDown:
break;
return false;
}
return false;
}
......
......@@ -125,11 +125,48 @@ public:
virtual void setToolTipExpression(const QPoint & /* mousePos */,
TextEditor::ITextEditor * /* editor */, int /* cursorPos */) { }
void initializeFromTemplate(DebuggerEngine *other);
virtual void updateWatchData(const WatchData & /* data */) { }
void startDebugger(DebuggerRunControl *runControl);
virtual void startEngine() {}
virtual bool isSessionEngine() const { return false; }
virtual void watchPoint(const QPoint &) {}
virtual void fetchMemory(MemoryViewAgent *, QObject *,
quint64 addr, quint64 length);
virtual void fetchDisassembler(DisassemblerViewAgent *) {}
virtual void activateFrame(int index) { Q_UNUSED(index); }
virtual void reloadModules() {}
virtual void loadSymbols(const QString &moduleName)
{ Q_UNUSED(moduleName); }
virtual void loadAllSymbols() {}
virtual void requestModuleSymbols(const QString &moduleName)
{ Q_UNUSED(moduleName); }
virtual void reloadRegisters() {}
virtual void reloadSourceFiles() {}
virtual void reloadFullStack() {}
virtual void setRegisterValue(int regnr, const QString &value);
virtual void addOptionPages(QList<Core::IOptionsPage*> *) const {}
virtual unsigned debuggerCapabilities() const { return 0; }
virtual bool isSynchroneous() const { return false; }
virtual QString qtNamespace() const { return QString(); }
virtual void makeSnapshot() {}
virtual void activateSnapshot(int index) { Q_UNUSED(index); }
virtual void attemptBreakpointSynchronization() {}
virtual void selectThread(int index) { Q_UNUSED(index); }
virtual void assignValueInDebugger(const QString &expr, const QString &value)
{ Q_UNUSED(expr); Q_UNUSED(value); }
protected:
virtual void setupEngine() {}
virtual void exitDebugger() {}
virtual void detachDebugger() {}
virtual void updateWatchData(const WatchData & /* data */) { }
virtual void executeStep() {}
virtual void executeStepOut() {}
virtual void executeNext() {}
......@@ -146,43 +183,11 @@ public:
{ Q_UNUSED(functionName); }
virtual void executeJumpToLine(const QString &fileName, int lineNumber)
{ Q_UNUSED(fileName); Q_UNUSED(lineNumber); }
virtual void assignValueInDebugger(const QString &expr, const QString &value)
{ Q_UNUSED(expr); Q_UNUSED(value); }
virtual void executeDebuggerCommand(const QString &command)
{ Q_UNUSED(command); }
virtual void activateFrame(int index) { Q_UNUSED(index); }
virtual void frameUp();
virtual void frameDown();
virtual void selectThread(int index) { Q_UNUSED(index); }
virtual void makeSnapshot() {}
virtual void activateSnapshot(int index) { Q_UNUSED(index); }
virtual void attemptBreakpointSynchronization() {}
virtual void reloadModules() {}
virtual void loadSymbols(const QString &moduleName)
{ Q_UNUSED(moduleName); }
virtual void loadAllSymbols() {}
virtual void requestModuleSymbols(const QString &moduleName)
{ Q_UNUSED(moduleName); }
virtual void reloadRegisters() {}
virtual void reloadSourceFiles() {}
virtual void reloadFullStack() {}
virtual void watchPoint(const QPoint &) {}
virtual void fetchMemory(MemoryViewAgent *, QObject *,
quint64 addr, quint64 length);
virtual void fetchDisassembler(DisassemblerViewAgent *) {}
virtual void setRegisterValue(int regnr, const QString &value);
virtual void addOptionPages(QList<Core::IOptionsPage*> *) const {}
virtual unsigned debuggerCapabilities() const { return 0; }
virtual bool isSynchroneous() const { return false; }
virtual bool isSessionEngine() const { return false; }
virtual QString qtNamespace() const { return QString(); }
public slots:
// Convenience
......@@ -252,9 +257,15 @@ public slots:
virtual void quitDebugger() { exitDebugger(); } // called by DebuggerRunControl
protected:
void notifyEngineStarted();
void notifyEngineStartOk();
void notifyEngineStartFailed();
void notifyInferiorSetupOk();
void notifyInferiorSetupFailed();
virtual void setupInferior();
virtual void runEngine();
//private: // FIXME. State transitions
void setState(DebuggerState state, bool forced = false);
......@@ -264,6 +275,7 @@ private:
void executeJumpToLine();
void addToWatchWindow();
friend class DebuggerEnginePrivate;
DebuggerEnginePrivate *d;
};
......
......@@ -162,7 +162,7 @@
//
// Transitions marked by '---' are done in the individual engines.
// Transitions marked by '+-+' are done in the base DebuggerEngine.
// The GdbEngine->startEngine() function is described in more detail below.
// The GdbEngine->setupEngine() function is described in more detail below.
//
// DebuggerNotReady
// +
......@@ -170,7 +170,11 @@
// EngineStarting
// +
// +
// (calls *Engine->startEngine())
// (calls *Engine->setupEngine())
// | |
// {notify- {notify-
// Engine- Engine-
// StartOk} StartFailed}
// | |
// | `---> EngineStartFailed
// | +
......@@ -182,14 +186,18 @@
// +
// [calls RunControl->StartSuccessful]
// +
// (calls *Engine->startInferior())
// (calls *Engine->setupInferior())
// | |
// {notify- {notify-
// Inferior- Inferior-
// SetupOk} SetupFailed}
// | |
// | ` ----> InferiorStartFailed +-+-+-+->.
// | ` ----> InferiorSetupFailed +-+-+-+->.
// | +
// v +
// InferiorStarted +
// +
// (calls *Engine->runInferior()) +
// InferiorSetupOk +
// + +
// (calls *Engine->runEngine()) +
// | +
// (core) | (attach) (term) (remote) (script) +
// .-----------------<-|->------------------. +
......@@ -219,7 +227,7 @@
// Transitions marked by '---' are done in the individual adapters.
// Transitions marked by '+-+' are done in the GdbEngine.
// GdbEngine::startEngine()
// GdbEngine::setupEngine()
// +
// +
// (calls *Adapter->startAdapter())
......@@ -2681,7 +2689,7 @@ bool DebuggerListener::coreAboutToClose()
case EngineStarted: // Most importantly, terminating a running
case EngineStartFailed: // debuggee can cause problems.
case InferiorUnrunnable:
case InferiorStartFailed:
case InferiorSetupFailed:
case InferiorStopped:
case InferiorShutDown:
cleanTermination = true;
......
......@@ -52,7 +52,7 @@ void AbstractGdbAdapter::shutdown()
{
}
void AbstractGdbAdapter::startInferiorPhase2()
void AbstractGdbAdapter::runAdapter()
{
qDebug() << "START INFERIOR PHASE 2";
}
......@@ -82,7 +82,7 @@ QString AbstractGdbAdapter::msgInferiorStopFailed(const QString &why)
return tr("Application process could not be stopped:\n%1").arg(why);
}
QString AbstractGdbAdapter::msgInferiorStarted()
QString AbstractGdbAdapter::msgInferiorSetupOk()
{
return tr("Application started");
}
......
......@@ -64,8 +64,8 @@ public:
virtual void write(const QByteArray &data);
virtual void startAdapter() = 0;
virtual void startInferior() = 0;
virtual void startInferiorPhase2();
virtual void setupInferior() = 0;
virtual void runAdapter();
virtual void interruptInferior() = 0;
virtual void shutdown();
virtual const char *inferiorShutdownCommand() const;
......@@ -76,7 +76,7 @@ public:
static QString msgGdbStopFailed(const QString &why);
static QString msgInferiorStopFailed(const QString &why);
static QString msgAttachedToStoppedInferior();
static QString msgInferiorStarted();
static QString msgInferiorSetupOk();
static QString msgInferiorRunning();
static QString msgConnectRemoteServerFailed(const QString &why);
......
......@@ -47,9 +47,9 @@ AbstractPlainGdbAdapter::AbstractPlainGdbAdapter(GdbEngine *engine,
{
}
void AbstractPlainGdbAdapter::startInferior()
void AbstractPlainGdbAdapter::setupInferior()
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state());
if (!startParameters().processArgs.isEmpty()) {
QString args = startParameters().processArgs.join(_(" "));
m_engine->postCommand("-exec-arguments " + toLocalEncoding(args));
......@@ -60,7 +60,7 @@ void AbstractPlainGdbAdapter::startInferior()
void AbstractPlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state());
if (response.resultClass == GdbResultDone) {
if (infoTargetNecessary()) {
// Old gdbs do not announce the PID for programs without pthreads.
......@@ -76,11 +76,11 @@ void AbstractPlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &respon
// Extend the message a bit in unknown cases.
if (!ba.endsWith("File format not recognized"))
msg = tr("Starting executable failed:\n") + msg;
m_engine->handleInferiorStartFailed(msg);
m_engine->handleInferiorSetupFailed(msg);
}
}
void AbstractPlainGdbAdapter::startInferiorPhase2()
void AbstractPlainGdbAdapter::runAdapter()
{
setState(InferiorRunningRequested);
m_engine->postCommand("-exec-run", GdbEngine::RunRequest, CB(handleExecRun));
......@@ -91,7 +91,7 @@ void AbstractPlainGdbAdapter::handleExecRun(const GdbResponse &response)
if (response.resultClass == GdbResultRunning) {
QTC_ASSERT(state() == InferiorRunning, qDebug() << state());
showMessage(_("INFERIOR STARTED"));
showMessage(msgInferiorStarted(), StatusBar);
showMessage(msgInferiorSetupOk(), StatusBar);
// FIXME: That's the wrong place for it.
if (theDebuggerBoolSetting(EnableReverseDebugging))
m_engine->postCommand("target record");
......@@ -100,7 +100,7 @@ void AbstractPlainGdbAdapter::handleExecRun(const GdbResponse &response)
QString msg = fromLocalEncoding(response.data.findChild("msg").data());
//QTC_ASSERT(status() == InferiorRunning, /**/);
//interruptInferior();
m_engine->handleInferiorStartFailed(msg);
m_engine->handleInferiorSetupFailed(msg);
}
}
......@@ -118,10 +118,10 @@ void AbstractPlainGdbAdapter::handleInfoTarget(const GdbResponse &response)
m_engine->postCommand("tbreak *0x" + needle.cap(1).toAscii());
// Do nothing here - inferiorPrepared handles the sequencing.
} else {
m_engine->handleInferiorStartFailed(_("Parsing start address failed"));
m_engine->handleInferiorSetupFailed(_("Parsing start address failed"));
}
} else if (response.resultClass == GdbResultError) {
m_engine->handleInferiorStartFailed(_("Fetching start address failed"));
m_engine->handleInferiorSetupFailed(_("Fetching start address failed"));
}
}
......
......@@ -41,8 +41,8 @@ class AbstractPlainGdbAdapter : public AbstractGdbAdapter
public:
AbstractPlainGdbAdapter(GdbEngine *engine, QObject *parent = 0);
virtual void startInferior();
virtual void startInferiorPhase2();
virtual void setupInferior();
virtual void runAdapter();
protected:
void handleInfoTarget(const GdbResponse &response);
......
......@@ -65,9 +65,9 @@ void AttachGdbAdapter::startAdapter()
m_engine->handleAdapterStarted();
}
void AttachGdbAdapter::startInferior()
void AttachGdbAdapter::setupInferior()
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state());
const qint64 pid = startParameters().attachPID;
m_engine->postCommand("attach " + QByteArray::number(pid), CB(handleAttach));
// Task 254674 does not want to remove them
......@@ -76,7 +76,7 @@ void AttachGdbAdapter::startInferior()
void AttachGdbAdapter::handleAttach(const GdbResponse &response)
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state());
if (response.resultClass == GdbResultDone) {
setState(InferiorStopped);
showMessage(_("INFERIOR ATTACHED"));
......@@ -85,7 +85,7 @@ void AttachGdbAdapter::handleAttach(const GdbResponse &response)
m_engine->updateAll();
} else {
QString msg = QString::fromLocal8Bit(response.data.findChild("msg").data());
m_engine->handleInferiorStartFailed(msg);
m_engine->handleInferiorSetupFailed(msg);
}
}
......
......@@ -53,7 +53,7 @@ public:
virtual DumperHandling dumperHandling() const { return DumperLoadedByGdb; }
void startAdapter();
void startInferior();
void setupInferior();
void interruptInferior();
const char *inferiorShutdownCommand() const { return "detach"; }
AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
......
......@@ -68,9 +68,9 @@ void CoreGdbAdapter::startAdapter()
m_engine->handleAdapterStarted();
}
void CoreGdbAdapter::startInferior()
void CoreGdbAdapter::setupInferior()
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state());
m_executable = startParameters().executable;
if (m_executable.isEmpty()) {
#ifdef EXE_FROM_CORE
......@@ -103,7 +103,7 @@ void CoreGdbAdapter::loadExeAndSyms()
void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
QTC_ASSERT(state() == InferiorSettingUp, qDebug() << state());
if (response.resultClass == GdbResultDone) {
showMessage(tr("Symbols found."), StatusBar);
} else {
......@@ -124,7 +124,7 @@ void CoreGdbAdapter::loadCoreFile()
void CoreGdbAdapter::handleTargetCore(const GdbResponse &response)
{