OSDN Git Service

debugger: let debugger attach to currently running process
authorhjk <qtc-committer@nokia.com>
Tue, 31 May 2011 07:48:00 +0000 (09:48 +0200)
committerhjk <qthjk@ovi.com>
Tue, 31 May 2011 11:34:40 +0000 (13:34 +0200)
Change-Id: I4aab1aa84a3dc9211d84d59be76005a8e841239e
(cherry picked from commit 55e399b524721e3561b6c7faae8aef84bf064565)
Reviewed-on: http://codereview.qt.nokia.com/251
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: hjk <qthjk@ovi.com>
src/plugins/debugger/debuggerengine.cpp
src/plugins/debugger/debuggerplugin.cpp
src/plugins/projectexplorer/appoutputpane.cpp
src/plugins/projectexplorer/appoutputpane.h
src/plugins/projectexplorer/localapplicationruncontrol.cpp
src/plugins/projectexplorer/localapplicationruncontrol.h
src/plugins/projectexplorer/runconfiguration.cpp
src/plugins/projectexplorer/runconfiguration.h
src/plugins/qmlprojectmanager/qmlprojectruncontrol.cpp
src/plugins/qt4projectmanager/qt-s60/s60emulatorrunconfiguration.cpp

index 754c990..05a659b 100644 (file)
@@ -520,6 +520,8 @@ void DebuggerEngine::startDebugger(DebuggerRunControl *runControl)
 
     d->m_inferiorPid = d->m_startParameters.attachPID > 0
         ? d->m_startParameters.attachPID : 0;
+    if (d->m_inferiorPid)
+        d->m_runControl->setApplicationProcessHandle(ProcessHandle(d->m_inferiorPid));
 
     if (!d->m_startParameters.environment.size())
         d->m_startParameters.environment = Utils::Environment();
@@ -1174,6 +1176,7 @@ void DebuggerEngine::notifyInferiorPid(qint64 pid)
         return;
     d->m_inferiorPid = pid;
     if (pid) {
+        d->m_runControl->setApplicationProcessHandle(ProcessHandle(pid));
         showMessage(tr("Taking notice of pid %1").arg(pid));
         if (d->m_startParameters.startMode == StartInternal
             || d->m_startParameters.startMode == StartExternal
index d0c3153..aecdd66 100644 (file)
@@ -688,9 +688,10 @@ public slots:
     void startRemoteApplication();
     void startRemoteEngine();
     void attachExternalApplication();
+    Q_SLOT void attachExternalApplication(ProjectExplorer::RunControl *rc);
     void attachExternalApplication(qint64 pid, const QString &binary,
-                                   const ProjectExplorer::Abi &abi = ProjectExplorer::Abi(),
-                                   const QString &debuggerCommand = QString());
+                                   const ProjectExplorer::Abi &abi,
+                                   const QString &debuggerCommand);
     void runScheduled();
     void attachCore();
     void attachCore(const QString &core, const QString &exeFileName,
@@ -1065,6 +1066,7 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(DebuggerPlugin *plugin) :
     m_dummyEngine(0),
     m_globalDebuggerOptions(new GlobalDebuggerOptions)
 {
+    setObjectName("DebuggerCore");
     qRegisterMetaType<WatchData>("WatchData");
     qRegisterMetaType<ContextData>("ContextData");
     qRegisterMetaType<DebuggerStartParameters>("DebuggerStartParameters");
@@ -1434,6 +1436,18 @@ void DebuggerPluginPrivate::attachExternalApplication(qint64 pid, const QString
         startDebugger(rc);
 }
 
+void DebuggerPluginPrivate::attachExternalApplication(ProjectExplorer::RunControl *rc)
+{
+    DebuggerStartParameters sp;
+    sp.attachPID = rc->applicationProcessHandle().pid();
+    sp.displayName = tr("Debugger attached to %1").arg(rc->displayName());
+    sp.startMode = AttachExternal;
+    //sp.toolChainAbi = abiOfBinary(sp.executable);
+    sp.toolChainAbi = ProjectExplorer::Abi::hostAbi(); // FIXME: Extract from RunControl?
+    if (DebuggerRunControl *rc = createDebugger(sp))
+        startDebugger(rc);
+}
+
 void DebuggerPluginPrivate::attachCore()
 {
     AttachCoreDialog dlg(mainWindow());
@@ -2538,6 +2552,8 @@ void DebuggerPluginPrivate::extensionsInitialized()
     Core::ActionManager *am = core->actionManager();
     QTC_ASSERT(am, return);
 
+    m_plugin->addObject(this);
+
     const Context globalcontext(CC::C_GLOBAL);
     const Context cppDebuggercontext(C_CPPDEBUGGER);
     const Context qmlDebuggerContext(C_QMLDEBUGGER);
@@ -3128,6 +3144,7 @@ void DebuggerPluginPrivate::showModuleSymbols(const QString &moduleName,
 
 void DebuggerPluginPrivate::aboutToShutdown()
 {
+    m_plugin->removeObject(this);
     disconnect(sessionManager(),
         SIGNAL(startupProjectChanged(ProjectExplorer::Project*)),
         this, 0);
index 67171f2..61b500b 100644 (file)
@@ -46,6 +46,8 @@
 #include <aggregation/aggregate.h>
 #include <texteditor/fontsettings.h>
 #include <texteditor/texteditorsettings.h>
+#include <extensionsystem/pluginmanager.h>
+#include <extensionsystem/invoker.h>
 
 #include <utils/qtcassert.h>
 #include <utils/outputformatter.h>
@@ -62,6 +64,11 @@ enum { debug = 0 };
 using namespace ProjectExplorer;
 using namespace ProjectExplorer::Internal;
 
+static QObject *debuggerCore()
+{
+    return ExtensionSystem::PluginManager::instance()->getObjectByName("DebuggerCore");
+}
+
 AppOutputPane::RunControlTab::RunControlTab(RunControl *rc, Core::OutputWindow *w) :
     runControl(rc), window(w), asyncClosing(false)
 {
@@ -72,7 +79,8 @@ AppOutputPane::AppOutputPane() :
     m_tabWidget(new QTabWidget),
     m_stopAction(new QAction(QIcon(QLatin1String(Constants::ICON_STOP)), tr("Stop"), this)),
     m_reRunButton(new QToolButton),
-    m_stopButton(new QToolButton)
+    m_stopButton(new QToolButton),
+    m_attachButton(new QToolButton)
 {
     // Rerun
     m_reRunButton->setIcon(QIcon(ProjectExplorer::Constants::ICON_RUN_SMALL));
@@ -97,6 +105,15 @@ AppOutputPane::AppOutputPane() :
     connect(m_stopAction, SIGNAL(triggered()),
             this, SLOT(stopRunControl()));
 
+    // Attach
+    m_attachButton->setToolTip(tr("Attach debugger to this process"));
+    m_attachButton->setEnabled(false);
+    m_attachButton->setIcon(QIcon(ProjectExplorer::Constants::ICON_DEBUG_SMALL));
+    m_attachButton->setAutoRaise(true);
+
+    connect(m_attachButton, SIGNAL(clicked()),
+            this, SLOT(attachToRunControl()));
+
     // Spacer (?)
 
     QVBoxLayout *layout = new QVBoxLayout;
@@ -185,7 +202,7 @@ QWidget *AppOutputPane::outputWidget(QWidget *)
 
 QList<QWidget*> AppOutputPane::toolBarWidgets() const
 {
-    return QList<QWidget*>() << m_reRunButton << m_stopButton;
+    return QList<QWidget*>() << m_reRunButton << m_stopButton << m_attachButton;
 }
 
 QString AppOutputPane::displayName() const
@@ -313,6 +330,15 @@ void AppOutputPane::reRunRunControl()
     tab.runControl->start();
 }
 
+void AppOutputPane::attachToRunControl()
+{
+    const int index = currentIndex();
+    QTC_ASSERT(index != -1, return);
+    ProjectExplorer::RunControl *rc = m_runControlTabs.at(index).runControl;
+    QTC_ASSERT(rc->isRunning(), return);
+    ExtensionSystem::Invoker<void>(debuggerCore(), "attachExternalApplication", rc);
+}
+
 void AppOutputPane::stopRunControl()
 {
     const int index = currentIndex();
@@ -399,6 +425,7 @@ void AppOutputPane::tabChanged(int i)
     if (i == -1) {
         m_stopAction->setEnabled(false);
         m_reRunButton->setEnabled(false);
+        m_attachButton->setEnabled(false);
     } else {
         const int index = indexOf(m_tabWidget->widget(i));
         QTC_ASSERT(index != -1, return; )
@@ -407,6 +434,7 @@ void AppOutputPane::tabChanged(int i)
         m_stopAction->setEnabled(rc->isRunning());
         m_reRunButton->setEnabled(!rc->isRunning());
         m_reRunButton->setIcon(rc->icon());
+        m_attachButton->setEnabled(debuggerCore());
     }
 }
 
@@ -416,6 +444,7 @@ void AppOutputPane::runControlStarted()
     if (current && current == sender()) {
         m_reRunButton->setEnabled(false);
         m_stopAction->setEnabled(true);
+        m_attachButton->setEnabled(debuggerCore());
         m_reRunButton->setIcon(current->icon());
     }
 }
@@ -437,6 +466,7 @@ void AppOutputPane::runControlFinished()
     if (current && current == sender()) {
         m_reRunButton->setEnabled(true);
         m_stopAction->setEnabled(false);
+        m_attachButton->setEnabled(false);
         m_reRunButton->setIcon(current->icon());
     }
     // Check for asynchronous close. Close the tab.
index bf36b41..f16c866 100644 (file)
@@ -97,6 +97,7 @@ public slots:
 private slots:
     void reRunRunControl();
     void stopRunControl();
+    void attachToRunControl();
     bool closeTab(int index);
     void tabChanged(int);
     void runControlStarted();
@@ -132,6 +133,7 @@ private:
     QAction *m_stopAction;
     QToolButton *m_reRunButton;
     QToolButton *m_stopButton;
+    QToolButton *m_attachButton;
 };
 
 } // namespace Internal
index 153bb16..dffb39f 100644 (file)
@@ -109,6 +109,7 @@ void LocalApplicationRunControl::start()
         emit finished();
     }  else {
         m_applicationLauncher.start(m_runMode, m_executable, m_commandLineArguments);
+        setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID()));
         QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable));
         appendMessage(msg, Utils::NormalMessageFormat);
     }
index 8397f0f..e8a9f05 100644 (file)
@@ -71,6 +71,7 @@ private:
     QString m_executable;
     QString m_commandLineArguments;
     ProjectExplorer::ApplicationLauncher::Mode m_runMode;
+    ProcessHandle m_applicationProcessHandle;
 };
 
 } // namespace Internal
index c4f1f2c..42bb2bc 100644 (file)
@@ -151,6 +151,12 @@ IRunConfigurationFactory *findRunConfigurationFactory(RunConfigurationFactoryMat
 } // namespace
 
 /*!
+    \class ProjectExplorer::ProcessHandle
+    \brief  Helper class to describe a process.
+
+*/
+
+/*!
     \class ProjectExplorer::RunConfiguration
     \brief  Base class for a run configuration. A run configuration specifies how a
     target should be run, while the runner (see below) does the actual running.
@@ -351,6 +357,7 @@ Utils::OutputFormatter *RunConfiguration::createOutputFormatter() const
     return new Utils::OutputFormatter();
 }
 
+
 /*!
     \class ProjectExplorer::IRunConfigurationFactory
 
@@ -492,6 +499,16 @@ QString RunControl::displayName() const
     return m_displayName;
 }
 
+ProcessHandle RunControl::applicationProcessHandle() const
+{
+    return m_applicationProcessHandle;
+}
+
+void RunControl::setApplicationProcessHandle(const ProcessHandle &handle)
+{
+    m_applicationProcessHandle = handle;
+}
+
 bool RunControl::promptToStop(bool *optionalPrompt) const
 {
     QTC_ASSERT(isRunning(), return true;)
index 862edd2..0ae9a88 100644 (file)
@@ -51,6 +51,20 @@ class IRunConfigurationAspect;
 class RunControl;
 class Target;
 
+// FIXME: This should also contain a handle to an remote device if used.
+class PROJECTEXPLORER_EXPORT ProcessHandle
+{
+public:
+    explicit ProcessHandle(quint64 pid = 0) : m_pid(pid) {}
+
+    bool isValid() const { return m_pid != 0; }
+    void setPid(quint64 pid) { m_pid = pid; }
+    quint64 pid() const { return m_pid; }
+
+private:
+    quint64 m_pid;
+};
+
 // Documentation inside.
 class PROJECTEXPLORER_EXPORT RunConfiguration : public ProjectConfiguration
 {
@@ -210,6 +224,9 @@ public:
     virtual QString displayName() const;
     virtual QIcon icon() const = 0;
 
+    ProcessHandle applicationProcessHandle() const;
+    void setApplicationProcessHandle(const ProcessHandle &handle);
+
     bool sameRunConfiguration(const RunControl *other) const;
 
     Utils::OutputFormatter *outputFormatter();
@@ -240,6 +257,9 @@ private:
     const QWeakPointer<RunConfiguration> m_runConfiguration;
     Utils::OutputFormatter *m_outputFormatter;
 
+    // A handle to the actual application process.
+    ProcessHandle m_applicationProcessHandle;
+
 #ifdef Q_OS_MAC
     //these two are used to bring apps in the foreground on Mac
     qint64 m_internalPid;
@@ -251,5 +271,6 @@ private:
 
 // Allow a RunConfiguration to be stored in a QVariant
 Q_DECLARE_METATYPE(ProjectExplorer::RunConfiguration*)
+Q_DECLARE_METATYPE(ProjectExplorer::RunControl*)
 
 #endif // RUNCONFIGURATION_H
index 1a00a9f..0685af9 100644 (file)
@@ -96,7 +96,7 @@ void QmlProjectRunControl::start()
 {
     m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable,
                                 m_commandLineArguments);
-
+    setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID()));
     emit started();
     QString msg = tr("Starting %1 %2\n")
         .arg(QDir::toNativeSeparators(m_executable), m_commandLineArguments);
index 11c38db..6d86d88 100644 (file)
@@ -348,13 +348,14 @@ S60EmulatorRunControl::S60EmulatorRunControl(S60EmulatorRunConfiguration *runCon
             this, SLOT(slotAppendMessage(QString, Utils::OutputFormat)));
     connect(&m_applicationLauncher, SIGNAL(processExited(int)),
             this, SLOT(processExited(int)));
-    connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(qint64)),
-            this, SLOT(bringApplicationToForeground(qint64)));
+    connect(&m_applicationLauncher, SIGNAL(bringToForegroundRequested(quint64)),
+            this, SLOT(bringApplicationToForeground(quint64)));
 }
 
 void S60EmulatorRunControl::start()
 {
     m_applicationLauncher.start(ApplicationLauncher::Gui, m_executable, QString());
+    setApplicationProcessHandle(ProcessHandle(m_applicationLauncher.applicationPID()));
     emit started();
 
     QString msg = tr("Starting %1...\n").arg(QDir::toNativeSeparators(m_executable));