From d6fc1193ed4b4c2ea5ca83fbcab055367af43de0 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 15 Jul 2010 13:23:44 +0200 Subject: [PATCH] debugger: more linear state handling in core adapter --- src/plugins/debugger/debuggerengine.cpp | 5 +- src/plugins/debugger/gdb/coregdbadapter.cpp | 150 ++++++++++---------- src/plugins/debugger/gdb/coregdbadapter.h | 6 +- src/plugins/debugger/gdb/gdbengine.cpp | 13 +- src/plugins/debugger/gdb/gdbengine.h | 1 + src/plugins/debugger/snapshothandler.cpp | 6 +- 6 files changed, 96 insertions(+), 85 deletions(-) diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 41131870d3d..92bdc24c8fd 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -976,7 +976,10 @@ static bool isAllowedTransition(DebuggerState from, DebuggerState to) case EngineSetupRequested: return to == EngineSetupOk || to == EngineSetupFailed; case EngineSetupFailed: - return to == DebuggerFinished; + // FIXME: In therory it's the engine's task to go into a + // proper "Shutdown" state before calling notifyEngineSetupFailed + //return to == DebuggerFinished; + return to == EngineShutdownRequested; case EngineSetupOk: return to == InferiorSetupRequested || to == EngineShutdownRequested; diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp index 6bbd641a6f5..7b01c53ab97 100644 --- a/src/plugins/debugger/gdb/coregdbadapter.cpp +++ b/src/plugins/debugger/gdb/coregdbadapter.cpp @@ -56,11 +56,18 @@ namespace Internal { // /////////////////////////////////////////////////////////////////////// -CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent) - : AbstractGdbAdapter(engine, parent), m_round(1) +static QByteArray coreName(const DebuggerStartParameters &sp) { + QFileInfo fi(sp.coreFile); + return fi.absoluteFilePath().toLocal8Bit(); } +CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine, QObject *parent) + : AbstractGdbAdapter(engine, parent), + m_executable(startParameters().executable), + m_coreName(coreName(startParameters())) +{} + void CoreGdbAdapter::startAdapter() { QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); @@ -69,34 +76,67 @@ void CoreGdbAdapter::startAdapter() if (!m_engine->startGdb()) return; +#ifndef EXE_FROM_CORE + if (m_executable.isEmpty()) { + showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"), + tr("No executable to load symbols from specified.")); + } m_engine->handleAdapterStarted(); +#else + // Extra round trip to get executable name from core file. + // This is sometimes not the full name, so it can't be used + // as the generic solution. + + // Quoting core name below fails in gdb 6.8-debian. + m_engine->postCommand("target core " + m_coreName, + CB(handleTemporaryTargetCore)); +#endif +} + +void CoreGdbAdapter::handleTemporaryTargetCore(const GdbResponse &response) +{ + QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); + if (response.resultClass != GdbResultDone) { + showMessage(tr("Attach to core failed."), StatusBar); + m_engine->notifyEngineSetupFailed(); + return; + } + + GdbMi console = response.data.findChild("consolestreamoutput"); + int pos1 = console.data().indexOf('`'); + int pos2 = console.data().indexOf('\''); + if (pos1 == -1 || pos2 == -1) { + showMessage(tr("Attach to core failed."), StatusBar); + m_engine->notifyEngineSetupFailed(); + return; + } + + m_executable = console.data().mid(pos1 + 1, pos2 - pos1 - 1); + // Strip off command line arguments. FIXME: make robust. + int idx = m_executable.indexOf(_c(' ')); + if (idx >= 0) + m_executable.truncate(idx); + if (m_executable.isEmpty()) { + m_engine->postCommand("detach"); + m_engine->notifyEngineSetupFailed(); + return; + } + m_executable = QFileInfo(startParameters().coreFile).absoluteDir() + .absoluteFilePath(m_executable); + showMessage(tr("Attached to core temporarily."), StatusBar); + m_engine->postCommand("detach", CB(handleTemporaryDetach)); +} + +void CoreGdbAdapter::handleTemporaryDetach(const GdbResponse &response) +{ + QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state()); + if (response.resultClass == GdbResultDone) + m_engine->notifyEngineSetupOk(); + else + m_engine->notifyEngineSetupFailed(); } void CoreGdbAdapter::setupInferior() -{ - QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); - m_executable = startParameters().executable; - if (m_executable.isEmpty()) { -#ifdef EXE_FROM_CORE - // Extra round trip to get executable name from core file. - // This is sometimes not the full name, so it can't be used - // as the generic solution. - - m_round = 1; - loadCoreFile(); -#else - showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"), - tr("No executable to load symbols from specified.")); -#endif - return; - } -#ifdef EXE_FROM_CORE - m_round = 2; -#endif - loadExeAndSyms(); -} - -void CoreGdbAdapter::loadExeAndSyms() { QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); // Do that first, otherwise no symbols are loaded. @@ -111,63 +151,27 @@ void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response) QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); if (response.resultClass == GdbResultDone) { showMessage(tr("Symbols found."), StatusBar); - } else { - QString msg = tr("Loading symbols from \"%1\" failed:\n").arg(m_executable) - + QString::fromLocal8Bit(response.data.findChild("msg").data()); - showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"), msg); + m_engine->postCommand("target core " + m_coreName, + CB(handleTargetCore)); + return; } - loadCoreFile(); -} - -void CoreGdbAdapter::loadCoreFile() -{ - QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); - // Quoting core name below fails in gdb 6.8-debian. - QFileInfo fi(startParameters().coreFile); - QByteArray coreName = fi.absoluteFilePath().toLocal8Bit(); - m_engine->postCommand("target core " + coreName, CB(handleTargetCore)); + m_engine->notifyInferiorSetupFailed(_("File or symbols not found")); } void CoreGdbAdapter::handleTargetCore(const GdbResponse &response) { QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state()); if (response.resultClass == GdbResultDone) { -#ifdef EXE_FROM_CORE - if (m_round == 1) { - m_round = 2; - GdbMi console = response.data.findChild("consolestreamoutput"); - int pos1 = console.data().indexOf('`'); - int pos2 = console.data().indexOf('\''); - if (pos1 != -1 && pos2 != -1) { - m_executable = console.data().mid(pos1 + 1, pos2 - pos1 - 1); - // Strip off command line arguments. FIXME: make robust. - int idx = m_executable.indexOf(_c(' ')); - if (idx >= 0) - m_executable.truncate(idx); - if (!m_executable.isEmpty()) { - m_executable = QFileInfo(startParameters().coreFile).absoluteDir() - .absoluteFilePath(m_executable); - if (QFile::exists(m_executable)) { - // Finish extra round ... - showMessage(tr("Attached to core temporarily."), StatusBar); - m_engine->postCommand("detach"); - // ... and retry. - loadExeAndSyms(); - return; - } - } - } - showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"), - tr("Unable to determine executable from core file.")); - } -#endif + // HACK: The namespace is not accessible in the initial run. + m_engine->loadPythonDumpers(); showMessage(tr("Attached to core."), StatusBar); m_engine->handleInferiorPrepared(); - } else { - QString msg = tr("Attach to core \"%1\" failed:\n").arg(startParameters().coreFile) - + QString::fromLocal8Bit(response.data.findChild("msg").data()); - m_engine->notifyInferiorSetupFailed(msg); + return; } + QString msg = tr("Attach to core \"%1\" failed:\n") + .arg(startParameters().coreFile) + + QString::fromLocal8Bit(response.data.findChild("msg").data()); + m_engine->notifyInferiorSetupFailed(msg); } void CoreGdbAdapter::runEngine() diff --git a/src/plugins/debugger/gdb/coregdbadapter.h b/src/plugins/debugger/gdb/coregdbadapter.h index f2ea1d18f26..3b122f000e5 100644 --- a/src/plugins/debugger/gdb/coregdbadapter.h +++ b/src/plugins/debugger/gdb/coregdbadapter.h @@ -63,13 +63,13 @@ private: AbstractGdbProcess *gdbProc() { return &m_gdbProc; } - void loadExeAndSyms(); - void loadCoreFile(); + void handleTemporaryDetach(const GdbResponse &response); + void handleTemporaryTargetCore(const GdbResponse &response); void handleFileExecAndSymbols(const GdbResponse &response); void handleTargetCore(const GdbResponse &response); - int m_round; // Round 1: read executable name from core, Round 2: use it. QString m_executable; + const QByteArray m_coreName; LocalGdbProcess m_gdbProc; }; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index bd86a6c64ec..16a055a9282 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -4047,9 +4047,6 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr return false; } - const QByteArray dumperSourcePath = - Core::ICore::instance()->resourcePath().toLocal8Bit() + "/gdbmacros/"; - showMessage(_("GDB STARTED, INITIALIZING IT")); m_commandTimer->setInterval(commandTimeoutTime()); @@ -4134,6 +4131,14 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr ).arg(scriptFileName)); } } + loadPythonDumpers(); + return true; +} + +void GdbEngine::loadPythonDumpers() +{ + const QByteArray dumperSourcePath = + Core::ICore::instance()->resourcePath().toLocal8Bit() + "/gdbmacros/"; postCommand("python execfile('" + dumperSourcePath + "dumper.py')", ConsoleCommand|NonCriticalResponse); @@ -4141,8 +4146,6 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr ConsoleCommand|NonCriticalResponse); postCommand("bbsetup", ConsoleCommand, CB(handleHasPython)); - - return true; } bool GdbEngine::checkDebuggingHelpers() diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 7728e2b3d54..d47fef51d1f 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -136,6 +136,7 @@ private: ////////// Gdb Process Management ////////// void handleAdapterStarted(); void defaultInferiorShutdown(const char *cmd); + void loadPythonDumpers(); // Something went wrong with the adapter *before* adapterStarted() was emitted. // Make sure to clean up everything before emitting this signal. diff --git a/src/plugins/debugger/snapshothandler.cpp b/src/plugins/debugger/snapshothandler.cpp index 62bf616c6b5..2477f0c40e7 100644 --- a/src/plugins/debugger/snapshothandler.cpp +++ b/src/plugins/debugger/snapshothandler.cpp @@ -256,7 +256,6 @@ void SnapshotHandler::removeAll() void SnapshotHandler::appendSnapshot(DebuggerRunControl *rc) { - //return; // FIXME m_snapshots.append(rc); m_currentIndex = size() - 1; reset(); @@ -264,9 +263,10 @@ void SnapshotHandler::appendSnapshot(DebuggerRunControl *rc) void SnapshotHandler::removeSnapshot(DebuggerRunControl *rc) { + // Could be that the run controls died before it was appended. int index = m_snapshots.indexOf(rc); - QTC_ASSERT(index != -1, return); - removeSnapshot(index); + if (index != -1) + removeSnapshot(index); } void SnapshotHandler::removeSnapshot(int index)