diff --git a/src/plugins/debugger/debugger.qbs b/src/plugins/debugger/debugger.qbs
index 08faeb3d1e60c6793578d4d51a3b22143ad926a7..9a69fb289af585baa642fe152e7116041edb162e 100644
--- a/src/plugins/debugger/debugger.qbs
+++ b/src/plugins/debugger/debugger.qbs
@@ -110,7 +110,6 @@ Project {
             files: [
                 "gdbengine.cpp", "gdbengine.h",
                 "gdboptionspage.cpp",
-                "startgdbserverdialog.cpp", "startgdbserverdialog.h",
             ]
         }
 
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index f3e1915b10602ec57a1f7a5bb62adfeb0e4231e5..078e1558e6b07066f36cc87279a1415a47857a14 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -61,7 +61,6 @@
 #include "snapshothandler.h"
 #include "threadshandler.h"
 #include "commonoptionspage.h"
-#include "gdb/startgdbserverdialog.h"
 
 #include "analyzer/analyzerconstants.h"
 #include "analyzer/analyzermanager.h"
@@ -735,7 +734,6 @@ public:
     void updateDebugWithoutDeployMenu();
 
     void startRemoteCdbSession();
-    void startRemoteServerAndAttachToProcess();
     void attachToRunningApplication();
     void attachToUnstartedApplicationDialog();
     void attachToQmlPort();
@@ -981,7 +979,6 @@ public:
     QAction *m_startAction = 0;
     QAction *m_debugWithoutDeployAction = 0;
     QAction *m_startAndDebugApplicationAction = 0;
-    QAction *m_startRemoteServerAction = 0;
     QAction *m_attachToRunningApplication = 0;
     QAction *m_attachToUnstartedApplication = 0;
     QAction *m_attachToQmlPortAction = 0;
@@ -1507,10 +1504,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
     act->setText(tr("Attach to Running Debug Server..."));
     connect(act, &QAction::triggered, this, &StartApplicationDialog::attachToRemoteServer);
 
-    act = m_startRemoteServerAction = new QAction(this);
-    act->setText(tr("Start Debug Server Attached to Process..."));
-    connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::startRemoteServerAndAttachToProcess);
-
     act = m_attachToRunningApplication = new QAction(this);
     act->setText(tr("Attach to Running Application..."));
     connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::attachToRunningApplication);
@@ -1584,11 +1577,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments,
     cmd->setAttribute(Command::CA_Hide);
     mstart->addAction(cmd, Constants::G_SPECIAL);
 
-    cmd = ActionManager::registerAction(m_startRemoteServerAction,
-         "Debugger.StartRemoteServer");
-    cmd->setDescription(tr("Start Gdbserver"));
-    mstart->addAction(cmd, Constants::G_SPECIAL);
-
     if (m_startRemoteCdbAction) {
         cmd = ActionManager::registerAction(m_startRemoteCdbAction,
              "Debugger.AttachRemoteCdb");
@@ -1992,30 +1980,48 @@ void DebuggerPluginPrivate::startRemoteCdbSession()
     debugger->startRunControl();
 }
 
-void DebuggerPluginPrivate::startRemoteServerAndAttachToProcess()
+class RemoteAttachRunner : public DebuggerRunTool
 {
-    auto kitChooser = new DebuggerKitChooser(DebuggerKitChooser::AnyDebugging);
-    auto dlg = new DeviceProcessesDialog(kitChooser, ICore::dialogParent());
-    dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
-    dlg->showAllDevices();
-    if (dlg->exec() == QDialog::Rejected) {
-        delete dlg;
-        return;
+public:
+    RemoteAttachRunner(RunControl *runControl, Kit *kit, int pid)
+        : DebuggerRunTool(runControl, kit)
+    {
+        IDevice::ConstPtr device = DeviceKitInformation::device(kit);
+        setDisplayName("AttachToRunningProcess");
+
+        portsGatherer = new GdbServerPortsGatherer(runControl);
+        portsGatherer->setUseGdbServer(true);
+        portsGatherer->setUseQmlServer(false);
+        portsGatherer->setDevice(device);
+
+        auto gdbServer = new GdbServerRunner(runControl, portsGatherer);
+        gdbServer->setUseMulti(false);
+        gdbServer->addStartDependency(portsGatherer);
+        gdbServer->setDevice(device);
+        gdbServer->setAttachPid(ProcessHandle(pid));
+
+        addStartDependency(gdbServer);
+
+        setStartMode(AttachToRemoteProcess);
+        setCloseMode(DetachAtClose);
+
+        //    setInferiorExecutable(localExecutable);
+        setUseContinueInsteadOfRun(true);
+        setContinueAfterAttach(false);
     }
 
-    dlg->setAttribute(Qt::WA_DeleteOnClose);
-    Kit *kit = kitChooser->currentKit();
-    QTC_ASSERT(kit, return);
-    IDevice::ConstPtr device = DeviceKitInformation::device(kit);
-    QTC_ASSERT(device, return);
+    void start() final
+    {
+        setRemoteChannel(portsGatherer->gdbServerChannel());
+        DebuggerRunTool::start();
+    }
 
-    GdbServerStarter *starter = new GdbServerStarter(dlg, true);
-    starter->run();
-}
+    GdbServerPortsGatherer *portsGatherer;
+};
 
 void DebuggerPluginPrivate::attachToRunningApplication()
 {
-    auto kitChooser = new DebuggerKitChooser(DebuggerKitChooser::LocalDebugging);
+    auto kitChooser = new DebuggerKitChooser(DebuggerKitChooser::AnyDebugging);
 
     auto dlg = new DeviceProcessesDialog(kitChooser, ICore::dialogParent());
     dlg->addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
@@ -2031,11 +2037,14 @@ void DebuggerPluginPrivate::attachToRunningApplication()
     IDevice::ConstPtr device = DeviceKitInformation::device(kit);
     QTC_ASSERT(device, return);
 
+    DeviceProcessItem process = dlg->currentProcess();
+
     if (device->type() == PE::DESKTOP_DEVICE_TYPE) {
-        attachToRunningProcess(kit, dlg->currentProcess(), false);
+        attachToRunningProcess(kit, process, false);
     } else {
-        GdbServerStarter *starter = new GdbServerStarter(dlg, true);
-        starter->run();
+        auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
+        auto debugger = new RemoteAttachRunner(runControl, kit, process.pid);
+        debugger->startRunControl();
     }
 }
 
diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
index f19c0086159699a211fe94c879486a255ca8eb89..6e129b4da8bbe0e6aa26df4f8f55cd4e5e9da6a5 100644
--- a/src/plugins/debugger/debuggerruncontrol.cpp
+++ b/src/plugins/debugger/debuggerruncontrol.cpp
@@ -936,6 +936,8 @@ GdbServerPortsGatherer::GdbServerPortsGatherer(RunControl *runControl)
             this, &RunWorker::reportFailure);
     connect(&m_portsGatherer, &DeviceUsedPortsGatherer::portListReady,
             this, &GdbServerPortsGatherer::handlePortListReady);
+
+    m_device = runControl->device();
 }
 
 GdbServerPortsGatherer::~GdbServerPortsGatherer()
@@ -944,26 +946,31 @@ GdbServerPortsGatherer::~GdbServerPortsGatherer()
 
 QString GdbServerPortsGatherer::gdbServerChannel() const
 {
-    const QString host = device()->sshParameters().host;
+    const QString host = m_device->sshParameters().host;
     return QString("%1:%2").arg(host).arg(m_gdbServerPort.number());
 }
 
 QUrl GdbServerPortsGatherer::qmlServer() const
 {
-    QUrl server = device()->toolControlChannel(IDevice::QmlControlChannel);
+    QUrl server = m_device->toolControlChannel(IDevice::QmlControlChannel);
     server.setPort(m_qmlServerPort.number());
     return server;
 }
 
+void GdbServerPortsGatherer::setDevice(IDevice::ConstPtr device)
+{
+    m_device = device;
+}
+
 void GdbServerPortsGatherer::start()
 {
     appendMessage(tr("Checking available ports..."), NormalMessageFormat);
-    m_portsGatherer.start(device());
+    m_portsGatherer.start(m_device);
 }
 
 void GdbServerPortsGatherer::handlePortListReady()
 {
-    Utils::PortList portList = device()->freePorts();
+    Utils::PortList portList = m_device->freePorts();
     appendMessage(tr("Found %n free ports.", nullptr, portList.count()), NormalMessageFormat);
     if (m_useGdbServer) {
         m_gdbServerPort = m_portsGatherer.getNextFreePort(&portList);
@@ -989,19 +996,38 @@ GdbServerRunner::GdbServerRunner(RunControl *runControl, GdbServerPortsGatherer
    : SimpleTargetRunner(runControl), m_portsGatherer(portsGatherer)
 {
     setDisplayName("GdbServerRunner");
+    if (runControl->runnable().is<StandardRunnable>())
+        m_runnable = runControl->runnable().as<StandardRunnable>();
 }
 
 GdbServerRunner::~GdbServerRunner()
 {
 }
 
+void GdbServerRunner::setRunnable(const StandardRunnable &runnable)
+{
+    m_runnable = runnable;
+}
+
+void GdbServerRunner::setUseMulti(bool on)
+{
+    m_useMulti = on;
+}
+
+void GdbServerRunner::setAttachPid(ProcessHandle pid)
+{
+    m_pid = pid;
+}
+
 void GdbServerRunner::start()
 {
     QTC_ASSERT(m_portsGatherer, reportFailure(); return);
 
-    StandardRunnable r = runnable().as<StandardRunnable>();
-    QStringList args = QtcProcess::splitArgs(r.commandLineArguments, OsTypeLinux);
-    QString command;
+    StandardRunnable gdbserver;
+    gdbserver.environment = m_runnable.environment;
+    gdbserver.workingDirectory = m_runnable.workingDirectory;
+
+    QStringList args = QtcProcess::splitArgs(m_runnable.commandLineArguments, OsTypeLinux);
 
     const bool isQmlDebugging = m_portsGatherer->useQmlServer();
     const bool isCppDebugging = m_portsGatherer->useGdbServer();
@@ -1010,21 +1036,24 @@ void GdbServerRunner::start()
         args.prepend(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
                                                     m_portsGatherer->qmlServerPort()));
     }
-
     if (isQmlDebugging && !isCppDebugging) {
-        command = r.executable;
+        gdbserver.executable = m_runnable.executable; // FIXME: Case should not happen?
     } else {
-        command = device()->debugServerPath();
-        if (command.isEmpty())
-            command = "gdbserver";
+        gdbserver.executable = device()->debugServerPath();
+        if (gdbserver.executable.isEmpty())
+            gdbserver.executable = "gdbserver";
         args.clear();
-        args.append(QString("--multi"));
+        if (m_useMulti)
+            args.append("--multi");
+        if (m_pid.isValid())
+            args.append("--attach");
         args.append(QString(":%1").arg(m_portsGatherer->gdbServerPort().number()));
+        if (m_pid.isValid())
+            args.append(QString::number(m_pid.pid()));
     }
-    r.executable = command;
-    r.commandLineArguments = QtcProcess::joinArgs(args, OsTypeLinux);
+    gdbserver.commandLineArguments = QtcProcess::joinArgs(args, OsTypeLinux);
 
-    setRunnable(r);
+    SimpleTargetRunner::setRunnable(gdbserver);
 
     appendMessage(tr("Starting gdbserver..."), NormalMessageFormat);
 
diff --git a/src/plugins/debugger/debuggerruncontrol.h b/src/plugins/debugger/debuggerruncontrol.h
index 4f17a23adad7c69b4473874a1a1a383c714663a4..50d2ed4b9864e5608a8248d6c1ba5f32eb41c141 100644
--- a/src/plugins/debugger/debuggerruncontrol.h
+++ b/src/plugins/debugger/debuggerruncontrol.h
@@ -161,6 +161,8 @@ public:
     Utils::Port qmlServerPort() const { return m_qmlServerPort; }
     QUrl qmlServer() const;
 
+    void setDevice(ProjectExplorer::IDevice::ConstPtr device);
+
 private:
     void start() override;
     void handlePortListReady();
@@ -170,6 +172,7 @@ private:
     bool m_useQmlServer = false;
     Utils::Port m_gdbServerPort;
     Utils::Port m_qmlServerPort;
+    ProjectExplorer::IDevice::ConstPtr m_device;
 };
 
 class DEBUGGER_EXPORT GdbServerRunner : public ProjectExplorer::SimpleTargetRunner
@@ -179,12 +182,20 @@ class DEBUGGER_EXPORT GdbServerRunner : public ProjectExplorer::SimpleTargetRunn
 public:
     explicit GdbServerRunner(ProjectExplorer::RunControl *runControl,
                              GdbServerPortsGatherer *portsGatherer);
+
     ~GdbServerRunner();
 
+    void setRunnable(const ProjectExplorer::StandardRunnable &runnable);
+    void setUseMulti(bool on);
+    void setAttachPid(Utils::ProcessHandle pid);
+
 private:
     void start() override;
 
     GdbServerPortsGatherer *m_portsGatherer;
+    ProjectExplorer::StandardRunnable m_runnable;
+    Utils::ProcessHandle m_pid;
+    bool m_useMulti = true;
 };
 
 extern DEBUGGER_EXPORT const char GdbServerRunnerWorkerId[];
diff --git a/src/plugins/debugger/gdb/gdb.pri b/src/plugins/debugger/gdb/gdb.pri
index 4e0883fa034f799832046b9d74a682e93468e201..c6678d127d090341f98acd60df3fd29dbacc18b4 100644
--- a/src/plugins/debugger/gdb/gdb.pri
+++ b/src/plugins/debugger/gdb/gdb.pri
@@ -1,8 +1,6 @@
 HEADERS += \
-    $$PWD/gdbengine.h \
-    $$PWD/startgdbserverdialog.h
+    $$PWD/gdbengine.h
 
 SOURCES += \
     $$PWD/gdbengine.cpp \
-    $$PWD/gdboptionspage.cpp \
-    $$PWD/startgdbserverdialog.cpp
+    $$PWD/gdboptionspage.cpp
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 157ff8fb879c0f7d7aa9c32e3ff40daa02e30d88..ca46e3e21702a6ad4e3f83bf8b4dedc786eeab59 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -1330,11 +1330,12 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
         notifyInferiorStopOk();
     } else if (state() == EngineRunRequested) {
         // This is gdb 7+'s initial *stopped in response to attach that
-        // appears before the ^done is seen.
+        // appears before the ^done is seen for local setups.
         notifyEngineRunAndInferiorStopOk();
-        if (terminal())
+        if (terminal()) {
             continueInferiorInternal();
-        return;
+            return;
+        }
     } else {
         QTC_CHECK(false);
     }
@@ -4267,7 +4268,11 @@ void GdbEngine::setupInferior()
 
     const DebuggerRunParameters &rp = runParameters();
 
-    if (isAttachEngine()) {
+    if (rp.startMode == AttachToRemoteProcess) {
+
+        notifyInferiorSetupOk();
+
+    } else if (isAttachEngine()) {
         // Task 254674 does not want to remove them
         //qq->breakHandler()->removeAllBreakpoints();
         handleInferiorPrepared();
@@ -4377,7 +4382,6 @@ void GdbEngine::setupInferior()
     } else if (isPlainEngine()) {
 
         setEnvironmentVariables();
-        const DebuggerRunParameters &rp = runParameters();
         if (!rp.inferior.workingDirectory.isEmpty())
             runCommand({"cd " + rp.inferior.workingDirectory});
         if (!rp.inferior.commandLineArguments.isEmpty()) {
@@ -4395,9 +4399,18 @@ void GdbEngine::runEngine()
 {
     CHECK_STATE(EngineRunRequested);
 
-    if (isAttachEngine()) {
+    const DebuggerRunParameters &rp = runParameters();
+
+    if (rp.startMode == AttachToRemoteProcess) {
+
+        notifyEngineRunAndInferiorStopOk();
 
-        const qint64 pid = runParameters().attachPID.pid();
+        QString channel = rp.remoteChannel;
+        runCommand({"target remote " + channel});
+
+    } else if (isAttachEngine()) {
+
+        const qint64 pid = rp.attachPID.pid();
         showStatusMessage(tr("Attaching to process %1.").arg(pid));
         runCommand({"attach " + QString::number(pid),
                     [this](const DebuggerResponse &r) { handleAttach(r); }});
@@ -4460,6 +4473,7 @@ void GdbEngine::handleAttach(const DebuggerResponse &response)
                 // InferiorStopOk, e.g. for "Attach to running application".
                 // The *stopped came in between sending the 'attach' and
                 // receiving its '^done'.
+                notifyEngineRunAndInferiorStopOk();
                 if (runParameters().continueAfterAttach)
                     continueInferiorInternal();
             }
@@ -4663,6 +4677,7 @@ void GdbEngine::handleSetTargetAsync(const DebuggerResponse &response)
 
 void GdbEngine::callTargetRemote()
 {
+    CHECK_STATE(InferiorSetupRequested);
     QString channel = runParameters().remoteChannel;
 
     // Don't touch channels with explicitly set protocols.
diff --git a/src/plugins/debugger/gdb/startgdbserverdialog.cpp b/src/plugins/debugger/gdb/startgdbserverdialog.cpp
deleted file mode 100644
index a9596269ca5c2f3eb69d58def06fcd0e19ea4b38..0000000000000000000000000000000000000000
--- a/src/plugins/debugger/gdb/startgdbserverdialog.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "startgdbserverdialog.h"
-
-#include <debugger/debuggerengine.h>
-#include <debugger/debuggermainwindow.h>
-#include <debugger/debuggerplugin.h>
-#include <debugger/debuggerkitinformation.h>
-#include <debugger/debuggerruncontrol.h>
-
-#include <coreplugin/icore.h>
-#include <coreplugin/messagebox.h>
-#include <projectexplorer/kitchooser.h>
-#include <projectexplorer/devicesupport/deviceprocesslist.h>
-#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
-#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
-#include <ssh/sshremoteprocessrunner.h>
-#include <utils/portlist.h>
-#include <utils/qtcassert.h>
-
-#include <QFileInfo>
-
-using namespace Core;
-using namespace ProjectExplorer;
-using namespace QSsh;
-using namespace Utils;
-
-
-namespace Debugger {
-namespace Internal {
-
-class StartGdbServerDialogPrivate
-{
-public:
-    StartGdbServerDialogPrivate() : dialog(0), kit(0) {}
-
-    DeviceProcessesDialog *dialog;
-    bool attachToServer;
-    DeviceProcessItem process;
-    Kit *kit;
-    IDevice::ConstPtr device;
-
-    DeviceUsedPortsGatherer gatherer;
-    SshRemoteProcessRunner runner;
-};
-
-GdbServerStarter::GdbServerStarter(DeviceProcessesDialog *dlg, bool attachAfterServerStart)
-  : QObject(dlg)
-{
-    d = new StartGdbServerDialogPrivate;
-    d->dialog = dlg;
-    d->kit = dlg->kitChooser()->currentKit();
-    d->process = dlg->currentProcess();
-    d->device = DeviceKitInformation::device(d->kit);
-    d->attachToServer = attachAfterServerStart;
-}
-
-GdbServerStarter::~GdbServerStarter()
-{
-    delete d;
-}
-
-void GdbServerStarter::handleRemoteError(const QString &errorMsg)
-{
-    AsynchronousMessageBox::critical(tr("Remote Error"), errorMsg);
-}
-
-void GdbServerStarter::portGathererError(const QString &text)
-{
-    logMessage(tr("Could not retrieve list of free ports:"));
-    logMessage(text);
-    logMessage(tr("Process aborted"));
-}
-
-void GdbServerStarter::run()
-{
-    QTC_ASSERT(d->device, return);
-    connect(&d->gatherer, &DeviceUsedPortsGatherer::error,
-            this, &GdbServerStarter::portGathererError);
-    connect(&d->gatherer, &DeviceUsedPortsGatherer::portListReady,
-            this, &GdbServerStarter::portListReady);
-    d->gatherer.start(d->device);
-}
-
-void GdbServerStarter::portListReady()
-{
-    PortList ports = d->device->freePorts();
-    const Port port = d->gatherer.getNextFreePort(&ports);
-    if (!port.isValid()) {
-        QTC_ASSERT(false, /**/);
-        emit logMessage(tr("Process aborted"));
-        return;
-    }
-
-    connect(&d->runner, &SshRemoteProcessRunner::connectionError,
-            this, &GdbServerStarter::handleConnectionError);
-    connect(&d->runner, &SshRemoteProcessRunner::processStarted,
-            this, &GdbServerStarter::handleProcessStarted);
-    connect(&d->runner, &SshRemoteProcessRunner::readyReadStandardOutput,
-            this, &GdbServerStarter::handleProcessOutputAvailable);
-    connect(&d->runner, &SshRemoteProcessRunner::readyReadStandardError,
-            this, &GdbServerStarter::handleProcessErrorOutput);
-    connect(&d->runner, &SshRemoteProcessRunner::processClosed,
-            this, &GdbServerStarter::handleProcessClosed);
-
-    QByteArray gdbServerPath = d->device->debugServerPath().toUtf8();
-    if (gdbServerPath.isEmpty())
-        gdbServerPath = "gdbserver";
-    QByteArray cmd = gdbServerPath + " --attach :"
-            + QByteArray::number(port.number()) + ' ' + QByteArray::number(d->process.pid);
-    logMessage(tr("Running command: %1").arg(QString::fromLatin1(cmd)));
-    d->runner.run(cmd, d->device->sshParameters());
-}
-
-void GdbServerStarter::handleConnectionError()
-{
-    logMessage(tr("Connection error: %1").arg(d->runner.lastConnectionErrorString()));
-}
-
-void GdbServerStarter::handleProcessStarted()
-{
-    logMessage(tr("Starting gdbserver..."));
-}
-
-void GdbServerStarter::handleProcessOutputAvailable()
-{
-    logMessage(QString::fromUtf8(d->runner.readAllStandardOutput().trimmed()));
-}
-
-void GdbServerStarter::handleProcessErrorOutput()
-{
-    const QByteArray ba = d->runner.readAllStandardError();
-    logMessage(QString::fromUtf8(ba.trimmed()));
-    // "Attached; pid = 16740"
-    // "Listening on port 10000"
-    foreach (const QByteArray &line, ba.split('\n')) {
-        if (line.startsWith("Listening on port")) {
-            const int port = line.mid(18).trimmed().toInt();
-            logMessage(tr("Port %1 is now accessible.").arg(port));
-            logMessage(tr("Server started on %1:%2")
-                .arg(d->device->sshParameters().host).arg(port));
-            if (d->attachToServer)
-                attach(port);
-        }
-    }
-}
-
-void GdbServerStarter::attach(int port)
-{
-    QString sysroot = SysRootKitInformation::sysRoot(d->kit).toString();
-    QString binary;
-    QString localExecutable;
-    QString candidate = sysroot + d->process.exe;
-    if (QFileInfo::exists(candidate))
-        localExecutable = candidate;
-    if (localExecutable.isEmpty()) {
-        binary = d->process.cmdLine.section(QLatin1Char(' '), 0, 0);
-        candidate = sysroot + QLatin1Char('/') + binary;
-        if (QFileInfo::exists(candidate))
-            localExecutable = candidate;
-    }
-    if (localExecutable.isEmpty()) {
-        candidate = sysroot + QLatin1String("/usr/bin/") + binary;
-        if (QFileInfo::exists(candidate))
-            localExecutable = candidate;
-    }
-    if (localExecutable.isEmpty()) {
-        candidate = sysroot + QLatin1String("/bin/") + binary;
-        if (QFileInfo::exists(candidate))
-            localExecutable = candidate;
-    }
-    if (localExecutable.isEmpty()) {
-        AsynchronousMessageBox::warning(tr("Warning"),
-            tr("Cannot find local executable for remote process \"%1\".")
-                .arg(d->process.exe));
-        return;
-    }
-
-    QList<Abi> abis = Abi::abisOfBinary(FileName::fromString(localExecutable));
-    if (abis.isEmpty()) {
-        AsynchronousMessageBox::warning(tr("Warning"),
-            tr("Cannot find ABI for remote process \"%1\".")
-                .arg(d->process.exe));
-        return;
-    }
-
-    QString remoteChannel = QString("%1:%2").arg(d->device->sshParameters().host).arg(port);
-
-    auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
-    auto debugger = new DebuggerRunTool(runControl, d->kit);
-    debugger->setRemoteChannel(remoteChannel);
-    debugger->setRunControlName(tr("Remote: \"%1\"").arg(remoteChannel));
-    debugger->setInferiorExecutable(localExecutable);
-    debugger->setStartMode(AttachToRemoteServer);
-    debugger->setCloseMode(KillAtClose);
-
-    debugger->startRunControl();
-}
-
-void GdbServerStarter::handleProcessClosed(int status)
-{
-    logMessage(tr("Process gdbserver finished. Status: %1").arg(status));
-}
-
-void GdbServerStarter::logMessage(const QString &line)
-{
-    d->dialog->logMessage(line);
-}
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/startgdbserverdialog.h b/src/plugins/debugger/gdb/startgdbserverdialog.h
deleted file mode 100644
index c90cefe7abca2cb283c12b6bb9e56d51c2e9f1bc..0000000000000000000000000000000000000000
--- a/src/plugins/debugger/gdb/startgdbserverdialog.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include <QObject>
-
-namespace ProjectExplorer { class DeviceProcessesDialog; }
-
-namespace Debugger {
-namespace Internal {
-
-class StartGdbServerDialogPrivate;
-
-class GdbServerStarter : public QObject
-{
-    Q_OBJECT
-
-public:
-    GdbServerStarter(ProjectExplorer::DeviceProcessesDialog *dlg,
-                     bool attachAfterServerStart);
-    ~GdbServerStarter();
-
-    void run();
-
-private:
-    void handleRemoteError(const QString &errorMessage);
-    void portGathererError(const QString &errorMessage);
-    void portListReady();
-
-    void handleProcessClosed(int);
-    void handleProcessErrorOutput();
-    void handleProcessOutputAvailable();
-    void handleProcessStarted();
-    void handleConnectionError();
-
-    void attach(int port);
-    void logMessage(const QString &line);
-    StartGdbServerDialogPrivate *d;
-};
-
-} // namespace Internal
-} // namespace Debugger
diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp
index 9e3d3339c7bd39b2b9b2b4f4fa5dcbf0dcca3e2c..b56f1d683eaae7b1cd5ff213ca0f513227477418 100644
--- a/src/plugins/projectexplorer/runconfiguration.cpp
+++ b/src/plugins/projectexplorer/runconfiguration.cpp
@@ -1384,24 +1384,14 @@ bool Runnable::canReUseOutputPane(const Runnable &other) const
 }
 
 
-// FIXME: Remove once ApplicationLauncher signalling does not depend on device.
-static bool isSynchronousLauncher(RunControl *runControl)
-{
-    RunConfiguration *runConfig = runControl->runConfiguration();
-    Target *target = runConfig ? runConfig->target() : nullptr;
-    Kit *kit = target ? target->kit() : nullptr;
-    Core::Id deviceId = DeviceTypeKitInformation::deviceTypeId(kit);
-    return !deviceId.isValid() || deviceId == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
-}
-
-
 // SimpleTargetRunner
 
 SimpleTargetRunner::SimpleTargetRunner(RunControl *runControl)
     : RunWorker(runControl)
 {
     setDisplayName("SimpleTargetRunner");
-    m_runnable = runControl->runnable();
+    m_runnable = runControl->runnable(); // Default value. Can be overridden using setRunnable.
+    m_device = runControl->device(); // Default value. Can be overridden using setDevice.
 }
 
 void SimpleTargetRunner::start()
@@ -1409,7 +1399,8 @@ void SimpleTargetRunner::start()
     m_stopReported = false;
     m_launcher.disconnect(this);
 
-    const bool isDesktop = isSynchronousLauncher(runControl());
+    const bool isDesktop = m_device.isNull()
+            || m_device->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE;
     const QString rawDisplayName = m_runnable.displayName();
     const QString displayName = isDesktop
             ? QDir::toNativeSeparators(rawDisplayName)
@@ -1528,11 +1519,21 @@ void SimpleTargetRunner::onProcessError(QProcess::ProcessError error)
     }
 }
 
+IDevice::ConstPtr SimpleTargetRunner::device() const
+{
+    return m_device;
+}
+
 void SimpleTargetRunner::setRunnable(const Runnable &runnable)
 {
     m_runnable = runnable;
 }
 
+void SimpleTargetRunner::setDevice(const IDevice::ConstPtr &device)
+{
+    m_device = device;
+}
+
 // RunWorkerPrivate
 
 RunWorkerPrivate::RunWorkerPrivate(RunWorker *runWorker, RunControl *runControl)
diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h
index f938f3a93d83eaeda3a7b60b652ec66c7cc90aa9..ebbf557d2a6a1a6c3ff711255a7135f9376ed0ac 100644
--- a/src/plugins/projectexplorer/runconfiguration.h
+++ b/src/plugins/projectexplorer/runconfiguration.h
@@ -522,6 +522,9 @@ public:
 
     void setRunnable(const Runnable &runnable);
 
+    void setDevice(const IDevice::ConstPtr &device);
+    IDevice::ConstPtr device() const;
+
 protected:
     void start() override;
     void stop() override;
@@ -533,6 +536,7 @@ private:
 
     ApplicationLauncher m_launcher;
     Runnable m_runnable;
+    IDevice::ConstPtr m_device;
     bool m_stopReported = false;
 };