From 93902e5d0a9fb0ec2ab7790a3aa272c5eaf87910 Mon Sep 17 00:00:00 2001
From: hjk <qtc-committer@nokia.com>
Date: Wed, 30 Sep 2009 12:27:03 +0200
Subject: [PATCH] debugger: make 'qtcreator -debug <corefile>' work

---
 src/plugins/debugger/Debugger.pluginspec     |  2 +-
 src/plugins/debugger/debuggermanager.cpp     |  4 +-
 src/plugins/debugger/debuggeroutputwindow.h  |  2 +-
 src/plugins/debugger/debuggerplugin.cpp      | 26 ++++++--
 src/plugins/debugger/debuggerplugin.h        |  3 +
 src/plugins/debugger/gdb/coregdbadapter.cpp  | 69 ++++++++++++--------
 src/plugins/debugger/gdb/coregdbadapter.h    |  1 +
 src/plugins/debugger/gdb/gdbengine.cpp       | 11 +++-
 src/plugins/debugger/gdb/gdbengine.h         |  1 +
 src/plugins/debugger/gdb/plaingdbadapter.cpp |  2 +-
 src/plugins/debugger/gdb/trkgdbadapter.cpp   |  2 +-
 11 files changed, 82 insertions(+), 41 deletions(-)

diff --git a/src/plugins/debugger/Debugger.pluginspec b/src/plugins/debugger/Debugger.pluginspec
index a410898c925..a1f207a13dd 100644
--- a/src/plugins/debugger/Debugger.pluginspec
+++ b/src/plugins/debugger/Debugger.pluginspec
@@ -29,7 +29,7 @@ will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.</license>
         <argument name="-disable-gdb">Disable Gdb debugger engine</argument>
         <argument name="-disable-sdb">Disable Qt Script debugger engine</argument>
         <argument name="-disable-tcf">Disable Tcf debugger engine</argument>
-        <argument name="-debug" parameter="process-id">Attach to Process-Id</argument>
+        <argument name="-debug" parameter="pid-or-corefile">Attach to Process-Id or Core file</argument>
         <argument name="-wincrashevent" parameter="event-handle">Event handle used for attaching to crashed processes</argument>
     </argumentList>
 </plugin>
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index f03afc166e8..76dfff70a4e 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -1698,7 +1698,9 @@ void DebuggerManager::setState(DebuggerState state)
     //showStatusMessage(QString("stoppable: %1, running: %2")
     // .arg(stoppable).arg(running));
     emit stateChanged(d->m_state);
-    const bool notbusy = stopped || state == DebuggerNotReady;
+    const bool notbusy = state == InferiorStopped
+        || state == DebuggerNotReady
+        || state == InferiorUnrunnable;
     setBusyCursor(!notbusy);
 }
 
diff --git a/src/plugins/debugger/debuggeroutputwindow.h b/src/plugins/debugger/debuggeroutputwindow.h
index be87d6d1f15..c67719a4bd9 100644
--- a/src/plugins/debugger/debuggeroutputwindow.h
+++ b/src/plugins/debugger/debuggeroutputwindow.h
@@ -31,8 +31,8 @@
 #define DEBUGGER_OUTPUTWINDOW_H
 
 #include <QtGui/QLineEdit>
-#include <QtGui/QSplitter>
 #include <QtGui/QPlainTextEdit>
+#include <QtGui/QSplitter>
 #include <QtGui/QWidget>
 
 namespace Debugger {
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index e8a71ee4df5..4efc857d1f1 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -478,8 +478,8 @@ bool DebuggerPlugin::parseArgument(QStringList::const_iterator &it,
         bool ok;
         m_cmdLineAttachPid = it->toULongLong(&ok);
         if (!ok) {
-            *errorMessage = msgInvalidNumericParameter(option, *it);
-            return false;
+            m_cmdLineAttachPid = 0;
+            m_cmdLineAttachCore = *it;
         }
         return true;
     }
@@ -530,7 +530,8 @@ bool DebuggerPlugin::parseArguments(const QStringList &args, QString *errorMessa
     if (Debugger::Constants::Internal::debug)
         qDebug().nospace() << args << "engines=0x"
             << QString::number(m_cmdLineEnabledEngines, 16)
-            << " pid" << m_cmdLineAttachPid << '\n';
+            << " pid" << m_cmdLineAttachPid
+            << " core" << m_cmdLineAttachCore << '\n';
     return true;
 }
 
@@ -909,6 +910,8 @@ void DebuggerPlugin::extensionsInitialized()
         m_manager->runTest(QString::fromLocal8Bit(env));
     if (m_cmdLineAttachPid)
         QTimer::singleShot(0, this, SLOT(attachCmdLinePid()));
+    if (!m_cmdLineAttachCore.isEmpty())
+        QTimer::singleShot(0, this, SLOT(attachCmdLineCore()));
 }
 
 void DebuggerPlugin::attachCmdLinePid()
@@ -1249,9 +1252,14 @@ void DebuggerPlugin::attachExternalApplication(qint64 pid, const QString &crashP
         runControl->start();
 }
 
+void DebuggerPlugin::attachCmdLineCore()
+{
+    m_manager->showStatusMessage(tr("Attaching to core %1.").arg(m_cmdLineAttachCore));
+    attachCore(m_cmdLineAttachCore, QString());
+}
+
 void DebuggerPlugin::attachCore()
 {
-    const DebuggerStartParametersPtr sp(new DebuggerStartParameters);
     AttachCoreDialog dlg(m_manager->mainWindow());
     dlg.setExecutableFile(
             configValue(_("LastExternalExecutableFile")).toString());
@@ -1263,8 +1271,14 @@ void DebuggerPlugin::attachCore()
                    dlg.executableFile());
     setConfigValue(_("LastExternalCoreFile"),
                    dlg.coreFile());
-    sp->executable = dlg.executableFile();
-    sp->coreFile = dlg.coreFile();
+    attachCore(dlg.coreFile(), dlg.executableFile());
+}
+
+void DebuggerPlugin::attachCore(const QString &core, const QString &exe)
+{
+    const DebuggerStartParametersPtr sp(new DebuggerStartParameters);
+    sp->executable = exe;
+    sp->coreFile = core;
     sp->startMode = AttachCore;
     RunConfigurationPtr rc = activeRunConfiguration();
     if (rc.isNull())
diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h
index dd5fea2efa7..4ef8b59353f 100644
--- a/src/plugins/debugger/debuggerplugin.h
+++ b/src/plugins/debugger/debuggerplugin.h
@@ -108,6 +108,7 @@ private slots:
     void attachCore();
     void attachRemoteTcf();
     void attachCmdLinePid();
+    void attachCmdLineCore();
 
 private:
     void readSettings();
@@ -117,6 +118,7 @@ private:
                               const QStringList::const_iterator& end,
                               QString *errorMessage);
     void attachExternalApplication(qint64 pid, const QString &crashParameter = QString());
+    void attachCore(const QString &core, const QString &exeFileName);
 
     friend class Debugger::DebuggerManager;
     friend class GdbOptionPage;
@@ -132,6 +134,7 @@ private:
     int m_gdbRunningContext;
     unsigned m_cmdLineEnabledEngines;
     quint64 m_cmdLineAttachPid;
+    QString m_cmdLineAttachCore;
     // Event handle for attaching to crashed Windows processes.
     quint64 m_cmdLineWinCrashEvent;
     QAction *m_toggleLockedAction;
diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp
index 106b1b097ae..9c4585791ca 100644
--- a/src/plugins/debugger/gdb/coregdbadapter.cpp
+++ b/src/plugins/debugger/gdb/coregdbadapter.cpp
@@ -112,36 +112,16 @@ void CoreGdbAdapter::prepareInferior()
 {
     QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
     setState(InferiorPreparing);
-    if (!startParameters().processArgs.isEmpty())
-        m_engine->postCommand(_("-exec-arguments ")
-            + startParameters().processArgs.join(_(" ")));
-    QFileInfo fi(m_engine->startParameters().executable);
-    m_engine->postCommand(_("-file-exec-and-symbols \"%1\"").arg(fi.absoluteFilePath()),
-        CB(handleFileExecAndSymbols));
-}
-
-void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
-{
-    QTC_ASSERT(state() == InferiorPreparing, qDebug() << state());
-    if (response.resultClass == GdbResultDone) {
-        //m_breakHandler->clearBreakMarkers();
-        setState(InferiorPrepared);
-        emit inferiorPrepared();
-    } else if (response.resultClass == GdbResultError) {
-        QString msg = tr("Starting executable failed:\n") +
-            __(response.data.findChild("msg").data());
-        setState(InferiorPreparationFailed);
-        emit inferiorPreparationFailed(msg);
-    }
+    setState(InferiorPrepared);
+    emit inferiorPrepared();
 }
 
 void CoreGdbAdapter::startInferior()
 {
     QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
-    QFileInfo fi(startParameters().executable);
-    QString fileName = _c('"') + fi.absoluteFilePath() + _c('"');
     QFileInfo fi2(startParameters().coreFile);
     // quoting core name below fails in gdb 6.8-debian
+    m_executable.clear();
     QString coreName = fi2.absoluteFilePath();
     m_engine->postCommand(_("target core ") + coreName, CB(handleTargetCore));
 }
@@ -150,9 +130,18 @@ void CoreGdbAdapter::handleTargetCore(const GdbResponse &response)
 {
     QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
     if (response.resultClass == GdbResultDone) {
-        setState(InferiorUnrunnable);
         showStatusMessage(tr("Attached to core."));
-        m_engine->updateAll();
+        m_executable = startParameters().executable;
+        if (m_executable.isEmpty()) {
+            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);
+        }
+        QFileInfo fi(m_executable);
+        m_engine->postCommand(_("-file-exec-and-symbols \"%1\"")
+            .arg(fi.absoluteFilePath()), CB(handleFileExecAndSymbols));
     } else {
         QTC_ASSERT(response.resultClass == GdbResultError, /**/);
         const QByteArray &msg = response.data.findChild("msg").data();
@@ -161,6 +150,23 @@ void CoreGdbAdapter::handleTargetCore(const GdbResponse &response)
     }
 }
 
+void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
+{
+    QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
+    if (response.resultClass == GdbResultDone) {
+        showStatusMessage(tr("Symbols found."));
+        setState(InferiorUnrunnable);
+        m_engine->updateAll();
+    } else if (response.resultClass == GdbResultError) {
+        QString msg = tr("Symbols not found in \"%1\" failed:\n%2")
+            .arg(__(response.data.findChild("msg").data()));
+        setState(InferiorUnrunnable);
+        m_engine->updateAll();
+        //setState(InferiorStartFailed);
+       // emit inferiorStartFailed(msg);
+    }
+}
+
 void CoreGdbAdapter::interruptInferior()
 {
     // A core should never 'run'
@@ -169,12 +175,21 @@ void CoreGdbAdapter::interruptInferior()
 
 void CoreGdbAdapter::shutdown()
 {
-    if (state() == InferiorUnrunnable || state() == InferiorShutDown) {
+    switch (state()) {
+
+    case DebuggerNotReady:
+        return;
+
+    case InferiorUnrunnable:
+    case InferiorShutDown:
+    case InferiorPreparationFailed:
         setState(AdapterShuttingDown);
         m_engine->postCommand(_("-gdb-exit"), CB(handleExit));
         return;
+
+    default:
+        QTC_ASSERT(false, qDebug() << state());
     }
-    QTC_ASSERT(state() == DebuggerNotReady, qDebug() << state());
 }
 
 void CoreGdbAdapter::handleExit(const GdbResponse &response)
diff --git a/src/plugins/debugger/gdb/coregdbadapter.h b/src/plugins/debugger/gdb/coregdbadapter.h
index c432b622751..8cb74db99df 100644
--- a/src/plugins/debugger/gdb/coregdbadapter.h
+++ b/src/plugins/debugger/gdb/coregdbadapter.h
@@ -76,6 +76,7 @@ private:
     Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
 
     QProcess m_gdbProc;
+    QString m_executable;
 };
 
 } // namespace Internal
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index fac5fe587a8..ba15808f918 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -881,16 +881,21 @@ void GdbEngine::executeDebuggerCommand(const QString &command)
 void GdbEngine::updateAll()
 {
     QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopped, /**/);
-    manager()->resetLocation();
     tryLoadDebuggingHelpers();
-    manager()->stackHandler()->setCurrentIndex(0);
     updateLocals(); 
-    reloadStack();
+    postCommand(_("-stack-list-frames"), WatchUpdate, CB(handleStackListFrames1), false);
+    manager()->stackHandler()->setCurrentIndex(0);
     if (supportsThreads())
         postCommand(_("-thread-list-ids"), WatchUpdate, CB(handleStackListThreads), 0);
     manager()->reloadRegisters();
 }
 
+void GdbEngine::handleStackListFrames1(const GdbResponse &response)
+{
+    handleStackListFrames(response);
+    manager()->gotoLocation(manager()->stackHandler()->currentFrame(), true);
+}
+
 void GdbEngine::handleQuerySources(const GdbResponse &response)
 {
     if (response.resultClass == GdbResultDone) {
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 4af8cc644cc..e6775a4d406 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -338,6 +338,7 @@ private:
     // Stack specific stuff
     //
     void handleStackListFrames(const GdbResponse &response);
+    void handleStackListFrames1(const GdbResponse &response);
     void handleStackSelectThread(const GdbResponse &response);
     void handleStackListThreads(const GdbResponse &response);
     Q_SLOT void reloadStack();
diff --git a/src/plugins/debugger/gdb/plaingdbadapter.cpp b/src/plugins/debugger/gdb/plaingdbadapter.cpp
index a7b92ae92a0..5d5e051c83b 100644
--- a/src/plugins/debugger/gdb/plaingdbadapter.cpp
+++ b/src/plugins/debugger/gdb/plaingdbadapter.cpp
@@ -144,7 +144,7 @@ void PlainGdbAdapter::prepareInferior()
     if (!startParameters().processArgs.isEmpty())
         m_engine->postCommand(_("-exec-arguments ")
             + startParameters().processArgs.join(_(" ")));
-    QFileInfo fi(m_engine->startParameters().executable);
+    QFileInfo fi(startParameters().executable);
     m_engine->postCommand(_("-file-exec-and-symbols \"%1\"").arg(fi.absoluteFilePath()),
         CB(handleFileExecAndSymbols));
 }
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp
index 3aa068362a9..604c4a205ee 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp
@@ -1411,7 +1411,7 @@ void TrkGdbAdapter::handleGdbStateChanged(QProcess::ProcessState newState)
 void TrkGdbAdapter::startAdapter()
 {
     // Retrieve parameters
-    const DebuggerStartParameters &parameters = m_engine->startParameters();
+    const DebuggerStartParameters &parameters = startParameters();
     setOverrideTrkDevice(parameters.remoteChannel);
     m_remoteExecutable = parameters.executable;
     m_symbolFile = parameters.symbolFileName;
-- 
GitLab