Add support for Boot2Qt

A plugin for communication with Boot2Qt devices.

Task-number: QTCREATORBUG-21808
Change-Id: I61f4a9451c2fe8ff4e1108e07db2e72e8c613c43
Reviewed-by: Kari Oikarinen <kari.oikarinen@qt.io>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
hjk
2019-06-04 14:22:35 +02:00
parent 0c74f6cc21
commit 5942b82490
56 changed files with 3980 additions and 0 deletions

View File

@@ -0,0 +1,223 @@
/****************************************************************************
**
** 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));
args.append(r.executable);
args.append(" ");
args.append(r.commandLineArguments);
r.commandLineArguments = args;
r.executable = Constants::AppcontrollerFilepath;
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