2019-06-04 14:22:35 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** Copyright (C) 2019 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 "qdbdevicedebugsupport.h"
|
|
|
|
|
|
|
|
|
|
#include "qdbconstants.h"
|
|
|
|
|
#include "qdbdevice.h"
|
|
|
|
|
#include "qdbrunconfiguration.h"
|
|
|
|
|
|
|
|
|
|
#include <debugger/debuggerruncontrol.h>
|
|
|
|
|
|
|
|
|
|
#include <ssh/sshconnection.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/algorithm.h>
|
|
|
|
|
#include <utils/url.h>
|
|
|
|
|
|
|
|
|
|
using namespace Debugger;
|
|
|
|
|
using namespace ProjectExplorer;
|
|
|
|
|
using namespace Utils;
|
|
|
|
|
using namespace Qdb::Internal;
|
|
|
|
|
|
|
|
|
|
namespace Qdb {
|
|
|
|
|
|
|
|
|
|
class QdbDeviceInferiorRunner : public RunWorker
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
QdbDeviceInferiorRunner(RunControl *runControl,
|
|
|
|
|
bool usePerf, bool useGdbServer, bool useQmlServer,
|
|
|
|
|
QmlDebug::QmlDebugServicesPreset qmlServices)
|
|
|
|
|
: RunWorker(runControl),
|
|
|
|
|
m_usePerf(usePerf), m_useGdbServer(useGdbServer), m_useQmlServer(useQmlServer),
|
|
|
|
|
m_qmlServices(qmlServices)
|
|
|
|
|
{
|
|
|
|
|
setId("QdbDebuggeeRunner");
|
|
|
|
|
|
|
|
|
|
connect(&m_launcher, &ApplicationLauncher::remoteProcessStarted,
|
|
|
|
|
this, &RunWorker::reportStarted);
|
|
|
|
|
connect(&m_launcher, &ApplicationLauncher::finished,
|
|
|
|
|
this, &RunWorker::reportStopped);
|
|
|
|
|
connect(&m_launcher, &ApplicationLauncher::appendMessage,
|
|
|
|
|
this, &RunWorker::appendMessage);
|
|
|
|
|
connect(&m_launcher, &ApplicationLauncher::remoteStdout,
|
|
|
|
|
this, [this](const QString &out) { appendMessage(out, StdOutFormat); });
|
|
|
|
|
connect(&m_launcher, &ApplicationLauncher::remoteStderr,
|
|
|
|
|
this, [this](const QString &out) { appendMessage(out, StdErrFormat); });
|
|
|
|
|
|
|
|
|
|
m_portsGatherer = new GdbServerPortsGatherer(runControl);
|
|
|
|
|
m_portsGatherer->setUseGdbServer(useGdbServer || usePerf);
|
|
|
|
|
m_portsGatherer->setUseQmlServer(useQmlServer);
|
|
|
|
|
addStartDependency(m_portsGatherer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Port perfPort() const { return m_portsGatherer->gdbServerPort(); }
|
|
|
|
|
QUrl gdbServer() const { return m_portsGatherer->gdbServer(); }
|
|
|
|
|
Port qmlServerPort() const { return m_portsGatherer->qmlServerPort(); }
|
|
|
|
|
QUrl qmlServer() const { return m_portsGatherer->qmlServer(); }
|
|
|
|
|
|
|
|
|
|
void start() override
|
|
|
|
|
{
|
|
|
|
|
const int perfPort = m_portsGatherer->gdbServerPort().number();
|
|
|
|
|
const int gdbServerPort = m_portsGatherer->gdbServerPort().number();
|
|
|
|
|
const int qmlServerPort = m_portsGatherer->qmlServerPort().number();
|
|
|
|
|
|
|
|
|
|
int lowerPort = 0;
|
|
|
|
|
int upperPort = 0;
|
|
|
|
|
|
|
|
|
|
Runnable r = runnable();
|
|
|
|
|
|
|
|
|
|
QString args;
|
|
|
|
|
if (m_useGdbServer) {
|
|
|
|
|
args.append(" --debug-gdb");
|
|
|
|
|
lowerPort = upperPort = gdbServerPort;
|
|
|
|
|
}
|
|
|
|
|
if (m_useQmlServer) {
|
|
|
|
|
args.append(" --debug-qml --qml-debug-services ");
|
|
|
|
|
args.append(QmlDebug::qmlDebugServices(m_qmlServices));
|
|
|
|
|
lowerPort = upperPort = qmlServerPort;
|
|
|
|
|
}
|
|
|
|
|
if (m_useGdbServer && m_useQmlServer) {
|
|
|
|
|
if (gdbServerPort + 1 != qmlServerPort) {
|
|
|
|
|
reportFailure("Need adjacent free ports for combined C++/QML debugging");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
lowerPort = gdbServerPort;
|
|
|
|
|
upperPort = qmlServerPort;
|
|
|
|
|
}
|
|
|
|
|
if (m_usePerf) {
|
|
|
|
|
if (auto perfSettings = runControl()->settings("Analyzer.Perf.Settings")) {
|
|
|
|
|
QStringList perfRecordArgs = perfSettings
|
|
|
|
|
->property("perfRecordArguments").toStringList();
|
|
|
|
|
args.append(QString::fromLatin1(" --profile-perf %1").arg(
|
|
|
|
|
Utils::transform(perfRecordArgs, [](QString arg) {
|
|
|
|
|
return arg.replace(',', ",,");
|
|
|
|
|
}).join(',')));
|
|
|
|
|
}
|
|
|
|
|
lowerPort = upperPort = perfPort;
|
|
|
|
|
}
|
|
|
|
|
args.append(QString(" --port-range %1-%2 ").arg(lowerPort).arg(upperPort));
|
2019-06-20 17:19:12 +02:00
|
|
|
args.append(r.executable.toString());
|
2019-06-04 14:22:35 +02:00
|
|
|
args.append(" ");
|
|
|
|
|
args.append(r.commandLineArguments);
|
|
|
|
|
|
|
|
|
|
r.commandLineArguments = args;
|
2019-06-20 17:19:12 +02:00
|
|
|
r.executable = FilePath::fromString(Constants::AppcontrollerFilepath);
|
2019-06-04 14:22:35 +02:00
|
|
|
|
|
|
|
|
m_launcher.start(r, device());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stop() override { m_launcher.stop(); }
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Debugger::GdbServerPortsGatherer *m_portsGatherer = nullptr;
|
|
|
|
|
bool m_usePerf;
|
|
|
|
|
bool m_useGdbServer;
|
|
|
|
|
bool m_useQmlServer;
|
|
|
|
|
QmlDebug::QmlDebugServicesPreset m_qmlServices;
|
|
|
|
|
ApplicationLauncher m_launcher;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// QdbDeviceDebugSupport
|
|
|
|
|
|
|
|
|
|
QdbDeviceDebugSupport::QdbDeviceDebugSupport(RunControl *runControl)
|
|
|
|
|
: Debugger::DebuggerRunTool(runControl)
|
|
|
|
|
{
|
|
|
|
|
setId("QdbDeviceDebugSupport");
|
|
|
|
|
|
|
|
|
|
m_debuggee = new QdbDeviceInferiorRunner(runControl, false, isCppDebugging(), isQmlDebugging(),
|
|
|
|
|
QmlDebug::QmlDebuggerServices);
|
|
|
|
|
addStartDependency(m_debuggee);
|
|
|
|
|
|
|
|
|
|
m_debuggee->addStopDependency(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QdbDeviceDebugSupport::start()
|
|
|
|
|
{
|
|
|
|
|
setStartMode(Debugger::AttachToRemoteServer);
|
|
|
|
|
setCloseMode(KillAndExitMonitorAtClose);
|
|
|
|
|
setRemoteChannel(m_debuggee->gdbServer());
|
|
|
|
|
setQmlServer(m_debuggee->qmlServer());
|
|
|
|
|
setUseContinueInsteadOfRun(true);
|
|
|
|
|
setContinueAfterAttach(true);
|
|
|
|
|
addSolibSearchDir("%{sysroot}/system/lib");
|
|
|
|
|
|
|
|
|
|
DebuggerRunTool::start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QdbDeviceDebugSupport::stop()
|
|
|
|
|
{
|
|
|
|
|
// Do nothing unusual. The launcher will die as result of (gdb) kill.
|
|
|
|
|
DebuggerRunTool::stop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// QdbDeviceQmlProfilerSupport
|
|
|
|
|
|
|
|
|
|
QdbDeviceQmlToolingSupport::QdbDeviceQmlToolingSupport(RunControl *runControl,
|
|
|
|
|
QmlDebug::QmlDebugServicesPreset services)
|
|
|
|
|
: RunWorker(runControl)
|
|
|
|
|
{
|
|
|
|
|
setId("QdbDeviceQmlToolingSupport");
|
|
|
|
|
|
|
|
|
|
m_runner = new QdbDeviceInferiorRunner(runControl, false, false, true, services);
|
|
|
|
|
addStartDependency(m_runner);
|
|
|
|
|
addStopDependency(m_runner);
|
|
|
|
|
|
|
|
|
|
m_worker = runControl->createWorker(runControl->runMode());
|
|
|
|
|
m_worker->addStartDependency(this);
|
|
|
|
|
addStopDependency(m_worker);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QdbDeviceQmlToolingSupport::start()
|
|
|
|
|
{
|
|
|
|
|
m_worker->recordData("QmlServerUrl", m_runner->qmlServer());
|
|
|
|
|
reportStarted();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// QdbDevicePerfProfilerSupport
|
|
|
|
|
|
|
|
|
|
QdbDevicePerfProfilerSupport::QdbDevicePerfProfilerSupport(RunControl *runControl)
|
|
|
|
|
: RunWorker(runControl)
|
|
|
|
|
{
|
|
|
|
|
setId("QdbDevicePerfProfilerSupport");
|
|
|
|
|
|
|
|
|
|
m_profilee = new QdbDeviceInferiorRunner(runControl, true, false, false,
|
|
|
|
|
QmlDebug::NoQmlDebugServices);
|
|
|
|
|
addStartDependency(m_profilee);
|
|
|
|
|
addStopDependency(m_profilee);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QdbDevicePerfProfilerSupport::start()
|
|
|
|
|
{
|
|
|
|
|
QUrl url;
|
|
|
|
|
url.setScheme(Utils::urlTcpScheme());
|
|
|
|
|
url.setHost(device()->sshParameters().host());
|
|
|
|
|
url.setPort(m_profilee->perfPort().number());
|
|
|
|
|
runControl()->setProperty("PerfConnection", url);
|
|
|
|
|
reportStarted();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Qdb
|