2023-08-08 15:37:39 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
|
|
|
|
|
|
|
|
|
#include "gdbdapengine.h"
|
|
|
|
|
|
2023-08-15 16:48:15 +02:00
|
|
|
#include "dapclient.h"
|
|
|
|
|
|
2023-08-18 15:17:11 +02:00
|
|
|
#include <coreplugin/messagemanager.h>
|
|
|
|
|
|
2023-08-08 15:37:39 +02:00
|
|
|
#include <debugger/debuggermainwindow.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/temporarydirectory.h>
|
|
|
|
|
|
|
|
|
|
#include <projectexplorer/buildconfiguration.h>
|
|
|
|
|
#include <projectexplorer/buildsystem.h>
|
|
|
|
|
#include <projectexplorer/projecttree.h>
|
|
|
|
|
|
|
|
|
|
#include <QDebug>
|
|
|
|
|
#include <QLocalSocket>
|
2023-08-18 15:17:11 +02:00
|
|
|
#include <QVersionNumber>
|
2023-08-08 15:37:39 +02:00
|
|
|
|
|
|
|
|
using namespace Core;
|
|
|
|
|
using namespace Utils;
|
|
|
|
|
|
|
|
|
|
namespace Debugger::Internal {
|
|
|
|
|
|
|
|
|
|
class ProcessDataProvider : public IDataProvider
|
|
|
|
|
{
|
|
|
|
|
public:
|
2023-08-17 13:32:55 +02:00
|
|
|
ProcessDataProvider(const DebuggerRunParameters &rp,
|
|
|
|
|
const CommandLine &cmd,
|
|
|
|
|
QObject *parent = nullptr)
|
|
|
|
|
: IDataProvider(parent)
|
|
|
|
|
, m_runParameters(rp)
|
2023-08-08 15:37:39 +02:00
|
|
|
, m_cmd(cmd)
|
|
|
|
|
{
|
|
|
|
|
connect(&m_proc, &Process::started, this, &IDataProvider::started);
|
|
|
|
|
connect(&m_proc, &Process::done, this, &IDataProvider::done);
|
|
|
|
|
connect(&m_proc,
|
|
|
|
|
&Process::readyReadStandardOutput,
|
|
|
|
|
this,
|
|
|
|
|
&IDataProvider::readyReadStandardOutput);
|
|
|
|
|
connect(&m_proc,
|
|
|
|
|
&Process::readyReadStandardError,
|
|
|
|
|
this,
|
|
|
|
|
&IDataProvider::readyReadStandardError);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~ProcessDataProvider()
|
|
|
|
|
{
|
|
|
|
|
m_proc.kill();
|
|
|
|
|
m_proc.waitForFinished();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void start() override
|
|
|
|
|
{
|
|
|
|
|
m_proc.setProcessMode(ProcessMode::Writer);
|
2023-09-29 15:46:20 +02:00
|
|
|
if (m_runParameters.debugger.workingDirectory.isDir())
|
|
|
|
|
m_proc.setWorkingDirectory(m_runParameters.debugger.workingDirectory);
|
2023-08-08 15:37:39 +02:00
|
|
|
m_proc.setEnvironment(m_runParameters.debugger.environment);
|
|
|
|
|
m_proc.setCommand(m_cmd);
|
|
|
|
|
m_proc.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isRunning() const override { return m_proc.isRunning(); }
|
2023-08-30 14:41:33 +02:00
|
|
|
void writeRaw(const QByteArray &data) override
|
|
|
|
|
{
|
|
|
|
|
if (m_proc.state() == QProcess::Running)
|
|
|
|
|
m_proc.writeRaw(data);
|
|
|
|
|
}
|
2023-08-08 15:37:39 +02:00
|
|
|
void kill() override { m_proc.kill(); }
|
|
|
|
|
QByteArray readAllStandardOutput() override { return m_proc.readAllStandardOutput().toUtf8(); }
|
|
|
|
|
QString readAllStandardError() override { return m_proc.readAllStandardError(); }
|
|
|
|
|
int exitCode() const override { return m_proc.exitCode(); }
|
|
|
|
|
QString executable() const override { return m_proc.commandLine().executable().toUserOutput(); }
|
|
|
|
|
|
|
|
|
|
QProcess::ExitStatus exitStatus() const override { return m_proc.exitStatus(); }
|
|
|
|
|
QProcess::ProcessError error() const override { return m_proc.error(); }
|
|
|
|
|
Utils::ProcessResult result() const override { return m_proc.result(); }
|
|
|
|
|
QString exitMessage() const override { return m_proc.exitMessage(); };
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Utils::Process m_proc;
|
|
|
|
|
const DebuggerRunParameters m_runParameters;
|
|
|
|
|
const CommandLine m_cmd;
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-12 10:44:57 +02:00
|
|
|
class GdbDapClient : public DapClient
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
GdbDapClient(IDataProvider *provider, QObject *parent = nullptr)
|
|
|
|
|
: DapClient(provider, parent)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const QLoggingCategory &logCategory() override
|
|
|
|
|
{
|
|
|
|
|
static const QLoggingCategory logCategory = QLoggingCategory("qtc.dbg.dapengine.gdb",
|
|
|
|
|
QtWarningMsg);
|
|
|
|
|
return logCategory;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-08-08 15:37:39 +02:00
|
|
|
GdbDapEngine::GdbDapEngine()
|
|
|
|
|
: DapEngine()
|
|
|
|
|
{
|
|
|
|
|
setObjectName("GdbDapEngine");
|
2023-08-18 15:17:11 +02:00
|
|
|
setDebuggerName("Gdb");
|
|
|
|
|
setDebuggerType("DAP");
|
2023-08-08 15:37:39 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-08 16:05:22 +02:00
|
|
|
void GdbDapEngine::handleDapInitialize()
|
|
|
|
|
{
|
|
|
|
|
if (!isLocalAttachEngine()) {
|
|
|
|
|
DapEngine::handleDapInitialize();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-12 10:44:57 +02:00
|
|
|
QTC_ASSERT(state() == EngineRunRequested, qCDebug(logCategory()) << state());
|
2023-09-08 16:05:22 +02:00
|
|
|
m_dapClient->postRequest("attach", QJsonObject{{"__restart", ""}});
|
2023-09-12 10:44:57 +02:00
|
|
|
qCDebug(logCategory()) << "handleDapAttach";
|
2023-09-08 16:05:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool GdbDapEngine::isLocalAttachEngine() const
|
|
|
|
|
{
|
|
|
|
|
return runParameters().startMode == AttachToLocalProcess;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GdbDapEngine::handleDapConfigurationDone()
|
|
|
|
|
{
|
|
|
|
|
if (!isLocalAttachEngine()) {
|
|
|
|
|
DapEngine::handleDapConfigurationDone();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
notifyEngineRunAndInferiorStopOk();
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-08 15:37:39 +02:00
|
|
|
void GdbDapEngine::setupEngine()
|
|
|
|
|
{
|
2023-09-12 10:44:57 +02:00
|
|
|
QTC_ASSERT(state() == EngineSetupRequested, qCDebug(logCategory()) << state());
|
2023-08-08 15:37:39 +02:00
|
|
|
|
|
|
|
|
const DebuggerRunParameters &rp = runParameters();
|
2023-09-08 16:05:22 +02:00
|
|
|
CommandLine cmd{rp.debugger.command.executable(), {"-i", "dap"}};
|
|
|
|
|
|
|
|
|
|
if (isLocalAttachEngine())
|
|
|
|
|
cmd.addArgs({"-p", QString::number(rp.attachPID.pid())});
|
2023-08-08 15:37:39 +02:00
|
|
|
|
2023-08-18 15:17:11 +02:00
|
|
|
QVersionNumber oldestVersion(14, 0, 50);
|
|
|
|
|
QVersionNumber version = QVersionNumber::fromString(rp.version);
|
|
|
|
|
if (version < oldestVersion) {
|
|
|
|
|
notifyEngineSetupFailed();
|
|
|
|
|
MessageManager::writeDisrupting("Debugger version " + rp.version
|
|
|
|
|
+ " is too old. Please upgrade to at least "
|
|
|
|
|
+ oldestVersion.toString());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-17 13:32:55 +02:00
|
|
|
IDataProvider *dataProvider = new ProcessDataProvider(rp, cmd, this);
|
2023-09-12 10:44:57 +02:00
|
|
|
m_dapClient = new GdbDapClient(dataProvider, this);
|
2023-08-15 16:48:15 +02:00
|
|
|
|
2023-08-08 15:37:39 +02:00
|
|
|
connectDataGeneratorSignals();
|
2023-08-15 16:48:15 +02:00
|
|
|
m_dapClient->dataProvider()->start();
|
2023-08-08 15:37:39 +02:00
|
|
|
}
|
|
|
|
|
|
2023-09-21 16:05:03 +02:00
|
|
|
const QLoggingCategory &GdbDapEngine::logCategory()
|
|
|
|
|
{
|
|
|
|
|
static const QLoggingCategory logCategory = QLoggingCategory("qtc.dbg.dapengine.gdb",
|
|
|
|
|
QtWarningMsg);
|
|
|
|
|
return logCategory;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-08 15:37:39 +02:00
|
|
|
} // namespace Debugger::Internal
|