aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBogDan Vatra <bogdan@kde.org>2024-03-26 14:42:17 +0200
committerBogDan Vatra <bogdan@kdab.com>2024-04-11 12:11:24 +0000
commit3e4f50aeb9feba4565fe689eb33bb0ea4a5fc2dd (patch)
treeab47f6487d090c4a6d7e5954d97790cb207836a9
parent4b29ad78e3f8f8917767818d97e29c7b9f8c4686 (diff)
Use SSH port forwarding for debugging
This feature is needed to enable debugging on remote targes which can not expose gdbserver ports on the wild, and we must use ssh tunneling for that job. Change-Id: I6df712fd3b40790e89c79a7617a24430fde6805a Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--src/plugins/debugger/debuggerruncontrol.cpp12
-rw-r--r--src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp7
-rw-r--r--src/plugins/projectexplorer/runcontrol.cpp5
-rw-r--r--src/plugins/projectexplorer/runcontrol.h1
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp19
-rw-r--r--src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h2
-rw-r--r--src/plugins/remotelinux/linuxdevice.cpp15
-rw-r--r--src/plugins/remotelinux/remotelinux_constants.h3
8 files changed, 60 insertions, 4 deletions
diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp
index a46d34ccda..503bad4bc2 100644
--- a/src/plugins/debugger/debuggerruncontrol.cpp
+++ b/src/plugins/debugger/debuggerruncontrol.cpp
@@ -30,6 +30,8 @@
#include <projectexplorer/taskhub.h>
#include <projectexplorer/toolchain.h>
+#include <remotelinux/remotelinux_constants.h>
+
#include <utils/algorithm.h>
#include <utils/checkablemessagebox.h>
#include <utils/environment.h>
@@ -1060,7 +1062,15 @@ DebugServerRunner::DebugServerRunner(RunControl *runControl, DebugServerPortsGat
cmd.addArg("--multi");
if (m_pid.isValid())
cmd.addArg("--attach");
- cmd.addArg(QString(":%1").arg(portsGatherer->gdbServer().port()));
+
+ const auto port = portsGatherer->gdbServer().port();
+ cmd.addArg(QString(":%1").arg(port));
+
+ if (runControl->device()->extraData(RemoteLinux::Constants::SshForwardDebugServerPort).toBool()) {
+ addExtraData(RemoteLinux::Constants::SshForwardPort, port);
+ addExtraData(RemoteLinux::Constants::DisableSharing, true);
+ }
+
if (m_pid.isValid())
cmd.addArg(QString::number(m_pid.pid()));
}
diff --git a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
index 920d7f69c5..714d311a1e 100644
--- a/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
+++ b/src/plugins/projectexplorer/devicesupport/deviceusedportsgatherer.cpp
@@ -7,6 +7,8 @@
#include "sshparameters.h"
#include "../projectexplorertr.h"
+#include <remotelinux/remotelinux_constants.h>
+
#include <utils/port.h>
#include <utils/portlist.h>
#include <utils/qtcprocess.h>
@@ -179,7 +181,10 @@ public:
void start() final
{
m_channel.setScheme(urlTcpScheme());
- m_channel.setHost(device()->toolControlChannel(IDevice::ControlChannelHint()).host());
+ if (device()->extraData(RemoteLinux::Constants::SshForwardDebugServerPort).toBool())
+ m_channel.setHost("localhost");
+ else
+ m_channel.setHost(device()->toolControlChannel(IDevice::ControlChannelHint()).host());
if (m_portGatherer)
m_channel.setPort(m_portGatherer->findEndPoint().port());
reportStarted();
diff --git a/src/plugins/projectexplorer/runcontrol.cpp b/src/plugins/projectexplorer/runcontrol.cpp
index f5f24b05c7..3b601d45cb 100644
--- a/src/plugins/projectexplorer/runcontrol.cpp
+++ b/src/plugins/projectexplorer/runcontrol.cpp
@@ -1580,6 +1580,11 @@ void SimpleTargetRunner::forceRunOnHost()
}
}
+void SimpleTargetRunner::addExtraData(const QString &key, const QVariant &value)
+{
+ d->m_extraData[key] = value;
+}
+
// RunWorkerPrivate
RunWorkerPrivate::RunWorkerPrivate(RunWorker *runWorker, RunControl *runControl)
diff --git a/src/plugins/projectexplorer/runcontrol.h b/src/plugins/projectexplorer/runcontrol.h
index 629fff8346..0c47ff18b6 100644
--- a/src/plugins/projectexplorer/runcontrol.h
+++ b/src/plugins/projectexplorer/runcontrol.h
@@ -273,6 +273,7 @@ protected:
void setProcessMode(Utils::ProcessMode processMode);
void forceRunOnHost();
+ void addExtraData(const QString &key, const QVariant &value);
private:
void start() final;
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
index 8afafabded..f89767de0a 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.cpp
@@ -105,6 +105,13 @@ GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget(
auto sshPortLabel = new QLabel(Tr::tr("&SSH port:"));
sshPortLabel->setBuddy(m_sshPortSpinBox);
+ m_useSshPortForwardingForDebugging = new QCheckBox;
+ m_useSshPortForwardingForDebugging->setText(Tr::tr("Use SSH port forwarding for debugging"));
+ m_useSshPortForwardingForDebugging
+ ->setToolTip(Tr::tr("Enable debugging on remote targes which cannot expose gdbserver ports.\n"
+ "The ssh tunneling is used to map the remote gdbserver port to localhost.\n"
+ "The local and remote ports are determined automatically."));
+
using namespace Layouting;
Form {
@@ -117,7 +124,8 @@ GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget(
Tr::tr("GDB server executable:"), m_gdbServerLineEdit, br,
Tr::tr("QML runtime executable:"), m_qmlRuntimeLineEdit, br,
QString(), m_sourceProfileCheckBox, br,
- Tr::tr("Access via:"), m_linkDeviceComboBox
+ QString(), m_useSshPortForwardingForDebugging, br,
+ Tr::tr("Access via:"), m_linkDeviceComboBox, br,
}.attachTo(this);
connect(m_hostLineEdit, &QLineEdit::editingFinished,
@@ -152,6 +160,8 @@ GenericLinuxDeviceConfigurationWidget::GenericLinuxDeviceConfigurationWidget(
this, &GenericLinuxDeviceConfigurationWidget::sourceProfileCheckingChanged);
connect(m_linkDeviceComboBox, &QComboBox::currentIndexChanged,
this, &GenericLinuxDeviceConfigurationWidget::linkDeviceChanged);
+ connect(m_useSshPortForwardingForDebugging, &QCheckBox::toggled,
+ this, &GenericLinuxDeviceConfigurationWidget::sshPortForwardingForDebugging);
initGui();
}
@@ -253,6 +263,11 @@ void GenericLinuxDeviceConfigurationWidget::linkDeviceChanged(int index)
device()->setExtraData(Constants::LinkDevice, deviceId);
}
+void GenericLinuxDeviceConfigurationWidget::sshPortForwardingForDebugging(bool on)
+{
+ device()->setExtraData(Constants::SshForwardDebugServerPort, on);
+}
+
void GenericLinuxDeviceConfigurationWidget::updateDeviceFromUi()
{
hostNameEditingFinished();
@@ -266,6 +281,7 @@ void GenericLinuxDeviceConfigurationWidget::updateDeviceFromUi()
timeoutEditingFinished();
sourceProfileCheckingChanged(m_sourceProfileCheckBox->isChecked());
linkDeviceChanged(m_linkDeviceComboBox->currentIndex());
+ sshPortForwardingForDebugging(m_useSshPortForwardingForDebugging->isChecked());
qmlRuntimeEditingFinished();
}
@@ -331,6 +347,7 @@ void GenericLinuxDeviceConfigurationWidget::initGui()
sshParams.authenticationType == SshParameters::AuthenticationTypeSpecificKey);
m_gdbServerLineEdit->setFilePath(device()->debugServerPath());
m_qmlRuntimeLineEdit->setFilePath(device()->qmlRunCommand());
+ m_useSshPortForwardingForDebugging->setChecked(device()->extraData(Constants::SshForwardDebugServerPort).toBool());
updatePortsWarningLabel();
}
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h
index aba251b969..cc007ec6ef 100644
--- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h
+++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationwidget.h
@@ -45,6 +45,7 @@ private:
void hostKeyCheckingChanged(bool doCheck);
void sourceProfileCheckingChanged(bool doCheck);
void linkDeviceChanged(int index);
+ void sshPortForwardingForDebugging(bool on);
void updateDeviceFromUi() override;
void updatePortsWarningLabel();
@@ -66,6 +67,7 @@ private:
Utils::PathChooser *m_qmlRuntimeLineEdit;
QCheckBox *m_sourceProfileCheckBox;
QComboBox *m_linkDeviceComboBox;
+ QCheckBox *m_useSshPortForwardingForDebugging;
};
} // RemoteLinux::Internal
diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp
index 31195e8cfa..5fcb808a7c 100644
--- a/src/plugins/remotelinux/linuxdevice.cpp
+++ b/src/plugins/remotelinux/linuxdevice.cpp
@@ -666,6 +666,12 @@ void SshProcessInterfacePrivate::start()
cmd.addCommandLineAsSingleArg(inner);
}
+ const auto forwardPort = q->m_setup.m_extraData.value(Constants::SshForwardPort).toString();
+ if (!forwardPort.isEmpty()) {
+ cmd.addArg("-L");
+ cmd.addArg(QString("%1:localhost:%1").arg(forwardPort));
+ }
+
m_process.setProcessImpl(q->m_setup.m_processImpl);
m_process.setProcessMode(q->m_setup.m_processMode);
m_process.setTerminalMode(q->m_setup.m_terminalMode);
@@ -680,11 +686,12 @@ void SshProcessInterfacePrivate::start()
return;
}
- m_useConnectionSharing = SshSettings::connectionSharingEnabled();
+ m_useConnectionSharing = SshSettings::connectionSharingEnabled() && !q->m_setup.m_extraData.value(Constants::DisableSharing).toBool();
// TODO: Do we really need it for master process?
m_sshParameters.x11DisplayName
= q->m_setup.m_extraData.value("Ssh.X11ForwardToDisplay").toString();
+
if (m_useConnectionSharing) {
m_connecting = true;
m_connectionHandle.reset(new SshConnectionHandle(m_device));
@@ -769,6 +776,12 @@ CommandLine SshProcessInterfacePrivate::fullLocalCommandLine() const
cmd.addArg("-q");
+ const auto forwardPort = q->m_setup.m_extraData.value(Constants::SshForwardPort).toString();
+ if (!forwardPort.isEmpty()) {
+ cmd.addArg("-L");
+ cmd.addArg(QString("%1:localhost:%1").arg(forwardPort));
+ }
+
cmd.addArgs(m_sshParameters.connectionOptions(sshBinary));
if (!m_socketFilePath.isEmpty())
cmd.addArgs({"-o", "ControlPath=" + m_socketFilePath});
diff --git a/src/plugins/remotelinux/remotelinux_constants.h b/src/plugins/remotelinux/remotelinux_constants.h
index 90e3482646..a562164dfd 100644
--- a/src/plugins/remotelinux/remotelinux_constants.h
+++ b/src/plugins/remotelinux/remotelinux_constants.h
@@ -21,6 +21,9 @@ const char KillAppStepId[] = "RemoteLinux.KillAppStep";
const char SourceProfile[] = "RemoteLinux.SourceProfile";
const char LinkDevice[] = "RemoteLinux.LinkDevice";
+const char SshForwardDebugServerPort[] = "RemoteLinux.SshForwardDebugServerPort";
+const char SshForwardPort[] = "RemoteLinux.SshForwardPort";
+const char DisableSharing[] = "RemoteLinux.DisableSharing";
const char RunConfigId[] = "RemoteLinuxRunConfiguration:";
const char CustomRunConfigId[] = "RemoteLinux.CustomRunConfig";