Commit afc39c4c authored by hjk's avatar hjk
Browse files

Qnx: Merge debug support related files



The attach part has not been active for a while, but there's code
now easier to reuse. So move participants of a potential solution
to a suitable place before attempting to fix functionality.

Change-Id: I9a7d4a6637e8ef214c22ee5683103e464109210d
Reviewed-by: Christian Stenger's avatarChristian Stenger <christian.stenger@qt.io>
parent 890c1906
......@@ -23,8 +23,6 @@ SOURCES += qnxplugin.cpp \
qnxdeviceprocesslist.cpp \
qnxtoolchain.cpp \
slog2inforunner.cpp \
qnxattachdebugsupport.cpp \
qnxattachdebugdialog.cpp \
qnxconfiguration.cpp \
qnxsettingswidget.cpp \
qnxconfigurationmanager.cpp \
......@@ -55,8 +53,6 @@ HEADERS += qnxplugin.h\
qnxdeviceprocesslist.h \
qnxtoolchain.h \
slog2inforunner.h \
qnxattachdebugsupport.h \
qnxattachdebugdialog.h \
qnxconfiguration.h \
qnxsettingswidget.h \
qnxconfigurationmanager.h \
......
......@@ -24,10 +24,6 @@ QtcPlugin {
"qnxtoolchain.cpp",
"qnxtoolchain.h",
"qnx.qrc",
"qnxattachdebugsupport.cpp",
"qnxattachdebugsupport.h",
"qnxattachdebugdialog.cpp",
"qnxattachdebugdialog.h",
"qnxbaseqtconfigwidget.cpp",
"qnxbaseqtconfigwidget.h",
"qnxconstants.h",
......
/****************************************************************************
**
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company
** Contact: info@kdab.com
**
** 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 "qnxattachdebugdialog.h"
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <QFormLayout>
#include <QLabel>
#include <QVBoxLayout>
using namespace Qnx;
using namespace Qnx::Internal;
QnxAttachDebugDialog::QnxAttachDebugDialog(ProjectExplorer::KitChooser *kitChooser, QWidget *parent)
: ProjectExplorer::DeviceProcessesDialog(kitChooser, parent)
{
auto sourceLabel = new QLabel(tr("Project source directory:"), this);
m_projectSource = new Utils::PathChooser(this);
m_projectSource->setExpectedKind(Utils::PathChooser::ExistingDirectory);
auto binaryLabel = new QLabel(tr("Local executable:"), this);
m_localExecutable = new Utils::PathChooser(this);
m_localExecutable->setExpectedKind(Utils::PathChooser::File);
auto formLayout = new QFormLayout;
formLayout->addRow(sourceLabel, m_projectSource);
formLayout->addRow(binaryLabel, m_localExecutable);
auto mainLayout = dynamic_cast<QVBoxLayout*>(layout());
QTC_ASSERT(mainLayout, return);
mainLayout->insertLayout(mainLayout->count() - 2, formLayout);
}
QString QnxAttachDebugDialog::projectSource() const
{
return m_projectSource->path();
}
QString QnxAttachDebugDialog::localExecutable() const
{
return m_localExecutable->path();
}
/****************************************************************************
**
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company
** Contact: info@kdab.com
**
** 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 <projectexplorer/devicesupport/deviceprocessesdialog.h>
namespace Utils { class PathChooser; }
namespace Qnx {
namespace Internal {
class QnxAttachDebugDialog : public ProjectExplorer::DeviceProcessesDialog
{
Q_OBJECT
public:
explicit QnxAttachDebugDialog(ProjectExplorer::KitChooser *kitChooser, QWidget *parent = 0);
QString projectSource() const;
QString localExecutable() const;
private:
Utils::PathChooser *m_projectSource;
Utils::PathChooser *m_localExecutable;
};
} // namespace Internal
} // namespace Qnx
/****************************************************************************
**
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company
** Contact: info@kdab.com
**
** 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 "qnxattachdebugsupport.h"
#include "qnxattachdebugdialog.h"
#include "qnxconstants.h"
#include "qnxqtversion.h"
#include "qnxutils.h"
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerruncontrol.h>
#include <debugger/debuggerstartparameters.h>
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitchooser.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/runnables.h>
#include <projectexplorer/toolchain.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/portlist.h>
#include <utils/qtcassert.h>
using namespace ProjectExplorer;
namespace Qnx {
namespace Internal {
QnxAttachDebugSupport::QnxAttachDebugSupport(QObject *parent)
: QObject(parent)
{
m_launcher = new ApplicationLauncher(this);
m_portsGatherer = new DeviceUsedPortsGatherer(this);
connect(m_portsGatherer, &DeviceUsedPortsGatherer::portListReady,
this, &QnxAttachDebugSupport::launchPDebug);
connect(m_portsGatherer, &DeviceUsedPortsGatherer::error,
this, &QnxAttachDebugSupport::handleError);
connect(m_launcher, &ApplicationLauncher::remoteProcessStarted,
this, &QnxAttachDebugSupport::attachToProcess);
connect(m_launcher, &ApplicationLauncher::reportError,
this, &QnxAttachDebugSupport::handleError);
connect(m_launcher, &ApplicationLauncher::reportProgress,
this, &QnxAttachDebugSupport::handleProgressReport);
connect(m_launcher, &ApplicationLauncher::remoteStdout,
this, &QnxAttachDebugSupport::handleRemoteOutput);
connect(m_launcher, &ApplicationLauncher::remoteStderr,
this, &QnxAttachDebugSupport::handleRemoteOutput);
}
void QnxAttachDebugSupport::showProcessesDialog()
{
auto kitChooser = new KitChooser;
kitChooser->setKitPredicate([](const Kit *k){
return k->isValid() && DeviceTypeKitInformation::deviceTypeId(k) == Core::Id(Constants::QNX_QNX_OS_TYPE);
});
QnxAttachDebugDialog dlg(kitChooser, 0);
dlg.addAcceptButton(DeviceProcessesDialog::tr("&Attach to Process"));
dlg.showAllDevices();
if (dlg.exec() == QDialog::Rejected)
return;
m_kit = kitChooser->currentKit();
if (!m_kit)
return;
m_device = DeviceKitInformation::device(m_kit);
QTC_ASSERT(m_device, return);
m_process = dlg.currentProcess();
m_projectSourceDirectory = dlg.projectSource();
m_localExecutablePath = dlg.localExecutable();
m_portsGatherer->start(m_device);
}
void QnxAttachDebugSupport::launchPDebug()
{
Utils::PortList portList = m_device->freePorts();
m_pdebugPort = m_portsGatherer->getNextFreePort(&portList);
if (!m_pdebugPort.isValid()) {
handleError(tr("No free ports for debugging."));
return;
}
StandardRunnable r;
r.executable = QLatin1String("pdebug");
r.commandLineArguments = QString::number(m_pdebugPort.number());
m_launcher->start(r, m_device);
}
void QnxAttachDebugSupport::attachToProcess()
{
Debugger::DebuggerStartParameters sp;
sp.attachPID = Utils::ProcessHandle(m_process.pid);
sp.startMode = Debugger::AttachToRemoteServer;
sp.closeMode = Debugger::DetachAtClose;
sp.remoteChannel = QString("%1:%2").arg(m_device->sshParameters().host).arg(m_pdebugPort.number());
sp.displayName = tr("Remote: \"%1\" - Process %2").arg(sp.remoteChannel).arg(m_process.pid);
sp.inferior.executable = m_localExecutablePath;
sp.useCtrlCStub = true;
QnxQtVersion *qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(m_kit));
if (qtVersion)
sp.solibSearchPath = QnxUtils::searchPaths(qtVersion);
auto runControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE);
auto debugger = new Debugger::DebuggerRunTool(runControl);
debugger->setRunParameters(sp);
// connect(qobject_cast<Debugger::DebuggerRunTool *>(runControl->toolRunner()),
// &Debugger::DebuggerRunTool::stateChanged,
// this, &QnxAttachDebugSupport::handleDebuggerStateChanged);
debugger->startRunControl();
}
void QnxAttachDebugSupport::handleDebuggerStateChanged(Debugger::DebuggerState state)
{
if (state == Debugger::DebuggerFinished)
stopPDebug();
}
void QnxAttachDebugSupport::handleError(const QString &message)
{
if (m_runTool)
m_runTool->showMessage(message, Debugger::AppError);
}
void QnxAttachDebugSupport::handleProgressReport(const QString &message)
{
if (m_runTool)
m_runTool->showMessage(message + QLatin1Char('\n'), Debugger::AppStuff);
}
void QnxAttachDebugSupport::handleRemoteOutput(const QString &output)
{
if (m_runTool)
m_runTool->showMessage(output, Debugger::AppOutput);
}
void QnxAttachDebugSupport::stopPDebug()
{
m_launcher->stop();
}
} // namespace Internal
} // namespace Qnx
/****************************************************************************
**
** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company
** Contact: info@kdab.com
**
** 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 <debugger/debuggerconstants.h>
#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <utils/port.h>
#include <QObject>
namespace Debugger { class DebuggerRunTool; }
namespace ProjectExplorer {
class ApplicationLauncher;
class DeviceUsedPortsGatherer;
class Kit;
}
namespace Qnx {
namespace Internal {
class QnxAttachDebugSupport : public QObject
{
Q_OBJECT
public:
explicit QnxAttachDebugSupport(QObject *parent = 0);
public slots:
void showProcessesDialog();
private slots:
void launchPDebug();
void attachToProcess();
void handleDebuggerStateChanged(Debugger::DebuggerState state);
void handleError(const QString &message);
void handleProgressReport(const QString &message);
void handleRemoteOutput(const QString &output);
private:
void stopPDebug();
ProjectExplorer::Kit *m_kit = 0;
ProjectExplorer::IDevice::ConstPtr m_device;
ProjectExplorer::DeviceProcessItem m_process;
ProjectExplorer::ApplicationLauncher *m_launcher;
ProjectExplorer::DeviceUsedPortsGatherer *m_portsGatherer;
Debugger::DebuggerRunTool *m_runTool = 0;
Utils::Port m_pdebugPort;
QString m_projectSourceDirectory;
QString m_localExecutablePath;
};
} // namespace Internal
} // namespace Qnx
......@@ -24,6 +24,7 @@
****************************************************************************/
#include "qnxdebugsupport.h"
#include "qnxconstants.h"
#include "qnxdevice.h"
#include "qnxrunconfiguration.h"
......@@ -31,26 +32,64 @@
#include "qnxqtversion.h"
#include "qnxutils.h"
#include <coreplugin/icore.h>
#include <debugger/debuggerkitinformation.h>
#include <debugger/debuggerruncontrol.h>
#include <projectexplorer/applicationlauncher.h>
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <projectexplorer/devicesupport/deviceusedportsgatherer.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitchooser.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/runnables.h>
#include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h>
#include <qmldebug/qmldebugcommandlinearguments.h>
#include <qtsupport/qtkitinformation.h>
#include <utils/pathchooser.h>
#include <utils/portlist.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <QFormLayout>
#include <QLabel>
#include <QVBoxLayout>
using namespace Debugger;
using namespace ProjectExplorer;
using namespace Utils;
namespace Qnx {
namespace Internal {
static QStringList searchPaths(Kit *kit)
{
auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(kit));
if (!qtVersion)
return {};
const QDir pluginDir(qtVersion->qmakeProperty("QT_INSTALL_PLUGINS"));
const QStringList pluginSubDirs = pluginDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
QStringList searchPaths;
for (const QString &dir : pluginSubDirs)
searchPaths << qtVersion->qmakeProperty("QT_INSTALL_PLUGINS") + '/' + dir;
searchPaths << qtVersion->qmakeProperty("QT_INSTALL_LIBS");
searchPaths << qtVersion->qnxTarget() + '/' + qtVersion->cpuDir() + "/lib";
searchPaths << qtVersion->qnxTarget() + '/' + qtVersion->cpuDir() + "/usr/lib";
return searchPaths;
}
// QnxDebuggeeRunner
class QnxDebuggeeRunner : public ProjectExplorer::SimpleTargetRunner
......@@ -68,7 +107,7 @@ private:
StandardRunnable r = runnable().as<StandardRunnable>();
QStringList arguments;
if (m_portsGatherer->useGdbServer()) {
Utils::Port pdebugPort = m_portsGatherer->gdbServerPort();
Port pdebugPort = m_portsGatherer->gdbServerPort();
r.executable = Constants::QNX_DEBUG_EXECUTABLE;
arguments.append(pdebugPort.toString());
}
......@@ -76,8 +115,8 @@ private:
arguments.append(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
m_portsGatherer->qmlServerPort()));
}
arguments.append(Utils::QtcProcess::splitArgs(r.commandLineArguments));
r.commandLineArguments = Utils::QtcProcess::joinArgs(arguments);
arguments.append(QtcProcess::splitArgs(r.commandLineArguments));
r.commandLineArguments = QtcProcess::joinArgs(arguments);
setRunnable(r);
......@@ -94,7 +133,7 @@ QnxDebugSupport::QnxDebugSupport(RunControl *runControl)
: DebuggerRunTool(runControl)
{
setDisplayName("QnxDebugSupport");
appendMessage(tr("Preparing remote side..."), Utils::LogMessageFormat);
appendMessage(tr("Preparing remote side..."), LogMessageFormat);
m_portsGatherer = new GdbServerPortsGatherer(runControl);
m_portsGatherer->setUseGdbServer(isCppDebugging());
......@@ -123,14 +162,193 @@ void QnxDebugSupport::start()
setStartMode(AttachToRemoteServer);
setCloseMode(KillAtClose);
setUseCtrlCStub(true);
setSymbolFile(runConfig->localExecutableFilePath());
setRemoteChannel(m_portsGatherer->gdbServerChannel());
setQmlServer(m_portsGatherer->qmlServer());
setInferior(inferior);
setSolibSearchPath(searchPaths(k));
DebuggerRunTool::start();
}
// QnxAttachDebugDialog
class QnxAttachDebugDialog : public DeviceProcessesDialog
{
public:
QnxAttachDebugDialog(KitChooser *kitChooser)
: DeviceProcessesDialog(kitChooser, Core::ICore::dialogParent())
{
auto sourceLabel = new QLabel(QnxDebugSupport::tr("Project source directory:"), this);
m_projectSource = new PathChooser(this);
m_projectSource->setExpectedKind(PathChooser::ExistingDirectory);
auto binaryLabel = new QLabel(QnxDebugSupport::tr("Local executable:"), this);
m_localExecutable = new PathChooser(this);
m_localExecutable->setExpectedKind(PathChooser::File);
auto formLayout = new QFormLayout;
formLayout->addRow(sourceLabel, m_projectSource);
formLayout->addRow(binaryLabel, m_localExecutable);
auto mainLayout = dynamic_cast<QVBoxLayout*>(layout());
QTC_ASSERT(mainLayout, return);
mainLayout->insertLayout(mainLayout->count() - 2, formLayout);
}
QString projectSource() const { return m_projectSource->path(); }
QString localExecutable() const { return m_localExecutable->path(); }
private:
PathChooser *m_projectSource;
PathChooser *m_localExecutable;
};
// QnxAttachDebugSupport
class PDebugRunner : public ProjectExplorer::SimpleTargetRunner
{
public:
PDebugRunner(RunControl *runControl, GdbServerPortsGatherer *portsGatherer)
: SimpleTargetRunner(runControl), m_portsGatherer(portsGatherer)
{
setDisplayName("PDebugRunner");
}
private:
void start() final
{
StandardRunnable r = runnable().as<StandardRunnable>();
QStringList arguments;
if (m_portsGatherer->useGdbServer()) {
Port pdebugPort = m_portsGatherer->gdbServerPort();
r.executable = Constants::QNX_DEBUG_EXECUTABLE;
arguments.append(pdebugPort.toString());
}
if (m_portsGatherer->useQmlServer()) {
arguments.append(QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlDebuggerServices,
m_portsGatherer->qmlServerPort()));
}
arguments.append(QtcProcess::splitArgs(r.commandLineArguments));
r.commandLineArguments = QtcProcess::joinArgs(arguments);
auto qtVersion = dynamic_cast<QnxQtVersion *>(QtSupport::QtKitInformation::qtVersion(k));
if (qtVersion)
setSolibSearchPath(QnxUtils::searchPaths(qtVersion));
setRunnable(r);
SimpleTargetRunner::start();
}
GdbServerPortsGatherer *m_portsGatherer;
};
QnxAttachDebugSupport::QnxAttachDebugSupport(RunControl *runControl)
: DebuggerRunTool(runControl)
{
setDisplayName("QnxAttachDebugSupport");
m_portsGatherer = new GdbServerPortsGatherer(runControl);
m_portsGatherer->setUseGdbServer(isCppDebugging());
m_portsGatherer->setUseQmlServer(isQmlDebugging());
m_pdebugRunner = new PDebugRunner(runControl, m_portsGatherer);
m_pdebugRunner->addStartDependency(m_portsGatherer);
addStartDependency(m_pdebugRunner);
// connect(m_launcher, &ApplicationLauncher::remoteProcessStarted,
// this, &QnxAttachDebugSupport::attachToProcess);
// connect(m_launcher, &ApplicationLauncher::reportError,
// this, &QnxAttachDebugSupport::handleError);
// connect(m_launcher, &ApplicationLauncher::reportProgress,
// this, &QnxAttachDebugSupport::handleProgressReport);