diff options
author | BogDan Vatra <bogdan@kde.org> | 2024-03-26 14:42:17 +0200 |
---|---|---|
committer | BogDan Vatra <bogdan@kdab.com> | 2024-04-11 12:11:24 +0000 |
commit | 3e4f50aeb9feba4565fe689eb33bb0ea4a5fc2dd (patch) | |
tree | ab47f6487d090c4a6d7e5954d97790cb207836a9 | |
parent | 4b29ad78e3f8f8917767818d97e29c7b9f8c4686 (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>
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"; |