2014-12-20 19:10:02 +00:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com>
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2014-12-20 19:10:02 +00:00
|
|
|
**
|
|
|
|
|
** 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
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2014-12-20 19:10:02 +00:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2014-12-20 19:10:02 +00:00
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "baremetaldebugsupport.h"
|
|
|
|
|
#include "baremetalrunconfiguration.h"
|
|
|
|
|
#include "baremetaldevice.h"
|
|
|
|
|
|
|
|
|
|
#include "gdbserverprovider.h"
|
|
|
|
|
#include "gdbserverprovidermanager.h"
|
|
|
|
|
|
|
|
|
|
#include <debugger/debuggerruncontrol.h>
|
|
|
|
|
#include <debugger/debuggerstartparameters.h>
|
|
|
|
|
|
|
|
|
|
#include <projectexplorer/devicesupport/deviceapplicationrunner.h>
|
|
|
|
|
|
|
|
|
|
namespace BareMetal {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
|
|
|
|
BareMetalDebugSupport::BareMetalDebugSupport(
|
|
|
|
|
const ProjectExplorer::IDevice::ConstPtr device,
|
|
|
|
|
Debugger::DebuggerRunControl *runControl)
|
|
|
|
|
: QObject(runControl)
|
|
|
|
|
, m_appRunner(new ProjectExplorer::DeviceApplicationRunner(this))
|
|
|
|
|
, m_runControl(runControl)
|
|
|
|
|
, m_device(device)
|
|
|
|
|
, m_state(BareMetalDebugSupport::Inactive)
|
|
|
|
|
{
|
|
|
|
|
Q_ASSERT(runControl);
|
2015-01-06 16:18:36 +01:00
|
|
|
connect(m_runControl.data(), &Debugger::DebuggerRunControl::requestRemoteSetup,
|
2014-12-20 19:10:02 +00:00
|
|
|
this, &BareMetalDebugSupport::remoteSetupRequested);
|
|
|
|
|
connect(runControl, &Debugger::DebuggerRunControl::finished,
|
|
|
|
|
this, &BareMetalDebugSupport::debuggingFinished);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BareMetalDebugSupport::~BareMetalDebugSupport()
|
|
|
|
|
{
|
|
|
|
|
setFinished();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::remoteSetupRequested()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_state == Inactive, return);
|
|
|
|
|
startExecution();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::debuggingFinished()
|
|
|
|
|
{
|
|
|
|
|
setFinished();
|
|
|
|
|
reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::remoteOutputMessage(const QByteArray &output)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_state == Inactive || m_state == Running, return);
|
|
|
|
|
showMessage(QString::fromUtf8(output), Debugger::AppOutput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::remoteErrorOutputMessage(const QByteArray &output)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_state == Inactive, return);
|
|
|
|
|
showMessage(QString::fromUtf8(output), Debugger::AppError);
|
|
|
|
|
|
|
|
|
|
// FIXME: Should we here parse an outputn?
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::remoteProcessStarted()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_state == StartingRunner, return);
|
|
|
|
|
adapterSetupDone();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::appRunnerFinished(bool success)
|
|
|
|
|
{
|
|
|
|
|
if (m_state == Inactive)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (m_state == Running) {
|
|
|
|
|
if (!success)
|
|
|
|
|
m_runControl->notifyInferiorIll();
|
|
|
|
|
} else if (m_state == StartingRunner) {
|
|
|
|
|
Debugger::RemoteSetupResult result;
|
|
|
|
|
result.success = false;
|
|
|
|
|
result.reason = tr("Debugging failed.");
|
|
|
|
|
m_runControl->notifyEngineRemoteSetupFinished(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::progressReport(const QString &progressOutput)
|
|
|
|
|
{
|
|
|
|
|
showMessage(progressOutput + QLatin1Char('\n'), Debugger::LogStatus);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::appRunnerError(const QString &error)
|
|
|
|
|
{
|
|
|
|
|
if (m_state == Running) {
|
|
|
|
|
showMessage(error, Debugger::AppError);
|
|
|
|
|
m_runControl->notifyInferiorIll();
|
|
|
|
|
} else if (m_state != Inactive) {
|
|
|
|
|
adapterSetupFailed(error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::adapterSetupDone()
|
|
|
|
|
{
|
|
|
|
|
m_state = Running;
|
|
|
|
|
Debugger::RemoteSetupResult result;
|
|
|
|
|
result.success = true;
|
|
|
|
|
m_runControl->notifyEngineRemoteSetupFinished(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::adapterSetupFailed(const QString &error)
|
|
|
|
|
{
|
|
|
|
|
debuggingFinished();
|
|
|
|
|
|
|
|
|
|
Debugger::RemoteSetupResult result;
|
|
|
|
|
result.success = false;
|
|
|
|
|
result.reason = tr("Initial setup failed: %1").arg(error);
|
|
|
|
|
m_runControl->notifyEngineRemoteSetupFinished(result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::startExecution()
|
|
|
|
|
{
|
|
|
|
|
auto dev = qSharedPointerCast<const BareMetalDevice>(m_device);
|
|
|
|
|
QTC_ASSERT(dev, return);
|
|
|
|
|
|
|
|
|
|
const GdbServerProvider *p = GdbServerProviderManager::instance()->findProvider(
|
|
|
|
|
dev->gdbServerProviderId());
|
|
|
|
|
QTC_ASSERT(p, return);
|
|
|
|
|
|
|
|
|
|
m_state = StartingRunner;
|
|
|
|
|
showMessage(tr("Starting GDB server...") + QLatin1Char('\n'), Debugger::LogStatus);
|
|
|
|
|
|
2015-11-29 18:38:21 +03:00
|
|
|
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::remoteStderr,
|
2014-12-20 19:10:02 +00:00
|
|
|
this, &BareMetalDebugSupport::remoteErrorOutputMessage);
|
2015-11-29 18:38:21 +03:00
|
|
|
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::remoteStdout,
|
2014-12-20 19:10:02 +00:00
|
|
|
this, &BareMetalDebugSupport::remoteOutputMessage);
|
2015-11-29 18:38:21 +03:00
|
|
|
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::remoteProcessStarted,
|
2014-12-20 19:10:02 +00:00
|
|
|
this, &BareMetalDebugSupport::remoteProcessStarted);
|
2015-11-29 18:38:21 +03:00
|
|
|
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::finished,
|
2014-12-20 19:10:02 +00:00
|
|
|
this, &BareMetalDebugSupport::appRunnerFinished);
|
2015-11-29 18:38:21 +03:00
|
|
|
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::reportProgress,
|
2014-12-20 19:10:02 +00:00
|
|
|
this, &BareMetalDebugSupport::progressReport);
|
2015-11-29 18:38:21 +03:00
|
|
|
connect(m_appRunner, &ProjectExplorer::DeviceApplicationRunner::reportError,
|
2014-12-20 19:10:02 +00:00
|
|
|
this, &BareMetalDebugSupport::appRunnerError);
|
|
|
|
|
|
|
|
|
|
const QString cmd = p->executable();
|
|
|
|
|
const QStringList args = p->arguments();
|
|
|
|
|
m_appRunner->start(m_device, cmd, args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::setFinished()
|
|
|
|
|
{
|
|
|
|
|
if (m_state == Inactive)
|
|
|
|
|
return;
|
|
|
|
|
if (m_state == Running)
|
|
|
|
|
m_appRunner->stop();
|
|
|
|
|
m_state = Inactive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::reset()
|
|
|
|
|
{
|
|
|
|
|
m_appRunner->disconnect(this);
|
|
|
|
|
m_state = Inactive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BareMetalDebugSupport::showMessage(const QString &msg, int channel)
|
|
|
|
|
{
|
|
|
|
|
if (m_state != Inactive)
|
|
|
|
|
m_runControl->showMessage(msg, channel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace BareMetal
|