forked from qt-creator/qt-creator
Debugger: Add "LLDB Dap" preset
lldb has a dap interface since a while now. The "GDB Dap" preset is not compatible, since gdb uses the same executable and lldb has a "lldb-dap" (previously "lldb-vscode") executable. Change-Id: I4105223659de093f0ee44129527c4830d21a3090 Reviewed-by: Artem Sokolovskii <artem.sokolovskii@qt.io>
This commit is contained in:
@@ -33,6 +33,7 @@ add_qtc_plugin(Debugger
|
||||
dap/dapclient.cpp dap/dapclient.h
|
||||
dap/dapengine.cpp dap/dapengine.h
|
||||
dap/gdbdapengine.cpp dap/gdbdapengine.h
|
||||
dap/lldbdapengine.cpp dap/lldbdapengine.h
|
||||
dap/pydapengine.cpp dap/pydapengine.h
|
||||
debugger.qrc
|
||||
debugger_global.h
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "cmakedapengine.h"
|
||||
#include "dapclient.h"
|
||||
#include "gdbdapengine.h"
|
||||
#include "lldbdapengine.h"
|
||||
#include "pydapengine.h"
|
||||
|
||||
#include <debugger/breakhandler.h>
|
||||
@@ -1058,6 +1059,8 @@ DebuggerEngine *createDapEngine(Utils::Id runMode)
|
||||
return new CMakeDapEngine;
|
||||
if (runMode == ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE)
|
||||
return new GdbDapEngine;
|
||||
if (runMode == ProjectExplorer::Constants::DAP_LLDB_DEBUG_RUN_MODE)
|
||||
return new LldbDapEngine;
|
||||
if (runMode == ProjectExplorer::Constants::DAP_PY_DEBUG_RUN_MODE)
|
||||
return new PyDapEngine;
|
||||
|
||||
|
176
src/plugins/debugger/dap/lldbdapengine.cpp
Normal file
176
src/plugins/debugger/dap/lldbdapengine.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright (C) 2024 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 "lldbdapengine.h"
|
||||
|
||||
#include "dapclient.h"
|
||||
|
||||
#include <coreplugin/messagemanager.h>
|
||||
|
||||
#include <debugger/debuggermainwindow.h>
|
||||
|
||||
#include <utils/mimeconstants.h>
|
||||
#include <utils/mimeutils.h>
|
||||
#include <utils/temporarydirectory.h>
|
||||
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/buildsystem.h>
|
||||
#include <projectexplorer/projecttree.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLocalSocket>
|
||||
#include <QVersionNumber>
|
||||
|
||||
using namespace Core;
|
||||
using namespace Utils;
|
||||
|
||||
namespace Debugger::Internal {
|
||||
|
||||
// TODO: Same class as in gdbdapengine.cpp. Refactor into one place.
|
||||
class ProcessDataProvider : public IDataProvider
|
||||
{
|
||||
public:
|
||||
ProcessDataProvider(const DebuggerRunParameters &rp,
|
||||
const CommandLine &cmd,
|
||||
QObject *parent = nullptr)
|
||||
: IDataProvider(parent)
|
||||
, m_runParameters(rp)
|
||||
, 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);
|
||||
if (m_runParameters.debugger.workingDirectory.isDir())
|
||||
m_proc.setWorkingDirectory(m_runParameters.debugger.workingDirectory);
|
||||
m_proc.setEnvironment(m_runParameters.debugger.environment);
|
||||
m_proc.setCommand(m_cmd);
|
||||
m_proc.start();
|
||||
}
|
||||
|
||||
bool isRunning() const override { return m_proc.isRunning(); }
|
||||
void writeRaw(const QByteArray &data) override
|
||||
{
|
||||
if (m_proc.state() == QProcess::Running)
|
||||
m_proc.writeRaw(data);
|
||||
}
|
||||
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;
|
||||
};
|
||||
|
||||
class LldbDapClient : public DapClient
|
||||
{
|
||||
public:
|
||||
LldbDapClient(IDataProvider *provider, QObject *parent = nullptr)
|
||||
: DapClient(provider, parent)
|
||||
{}
|
||||
|
||||
private:
|
||||
const QLoggingCategory &logCategory() override
|
||||
{
|
||||
static const QLoggingCategory logCategory = QLoggingCategory("qtc.dbg.dapengine.lldb",
|
||||
QtWarningMsg);
|
||||
return logCategory;
|
||||
}
|
||||
};
|
||||
|
||||
LldbDapEngine::LldbDapEngine()
|
||||
: DapEngine()
|
||||
{
|
||||
setObjectName("LldbDapEngine");
|
||||
setDebuggerName("LLDB");
|
||||
setDebuggerType("DAP");
|
||||
}
|
||||
|
||||
void LldbDapEngine::handleDapInitialize()
|
||||
{
|
||||
if (!isLocalAttachEngine()) {
|
||||
DapEngine::handleDapInitialize();
|
||||
return;
|
||||
}
|
||||
|
||||
QTC_ASSERT(state() == EngineRunRequested, qCDebug(logCategory()) << state());
|
||||
m_dapClient->postRequest("attach", QJsonObject{{"__restart", ""}});
|
||||
qCDebug(logCategory()) << "handleDapAttach";
|
||||
}
|
||||
|
||||
bool LldbDapEngine::isLocalAttachEngine() const
|
||||
{
|
||||
return runParameters().startMode == AttachToLocalProcess;
|
||||
}
|
||||
|
||||
void LldbDapEngine::handleDapConfigurationDone()
|
||||
{
|
||||
if (!isLocalAttachEngine()) {
|
||||
DapEngine::handleDapConfigurationDone();
|
||||
return;
|
||||
}
|
||||
|
||||
notifyEngineRunAndInferiorStopOk();
|
||||
}
|
||||
|
||||
void LldbDapEngine::setupEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qCDebug(logCategory()) << state());
|
||||
|
||||
const DebuggerRunParameters &rp = runParameters();
|
||||
CommandLine cmd{rp.debugger.command.executable()};
|
||||
|
||||
if (isLocalAttachEngine())
|
||||
cmd.addArgs({"--debugger-pid", QString::number(rp.attachPID.pid())});
|
||||
|
||||
IDataProvider *dataProvider = new ProcessDataProvider(rp, cmd, this);
|
||||
m_dapClient = new LldbDapClient(dataProvider, this);
|
||||
|
||||
connectDataGeneratorSignals();
|
||||
m_dapClient->dataProvider()->start();
|
||||
}
|
||||
|
||||
bool LldbDapEngine::acceptsBreakpoint(const BreakpointParameters &bp) const
|
||||
{
|
||||
const auto mimeType = Utils::mimeTypeForFile(bp.fileName);
|
||||
return mimeType.matchesName(Utils::Constants::C_HEADER_MIMETYPE)
|
||||
|| mimeType.matchesName(Utils::Constants::C_SOURCE_MIMETYPE)
|
||||
|| mimeType.matchesName(Utils::Constants::CPP_HEADER_MIMETYPE)
|
||||
|| mimeType.matchesName(Utils::Constants::CPP_SOURCE_MIMETYPE)
|
||||
|| bp.type == BreakpointByFunction;
|
||||
}
|
||||
|
||||
const QLoggingCategory &LldbDapEngine::logCategory()
|
||||
{
|
||||
static const QLoggingCategory logCategory = QLoggingCategory("qtc.dbg.dapengine.lldb",
|
||||
QtWarningMsg);
|
||||
return logCategory;
|
||||
}
|
||||
|
||||
} // namespace Debugger::Internal
|
26
src/plugins/debugger/dap/lldbdapengine.h
Normal file
26
src/plugins/debugger/dap/lldbdapengine.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "dapengine.h"
|
||||
|
||||
namespace Debugger::Internal {
|
||||
|
||||
class LldbDapEngine : public DapEngine
|
||||
{
|
||||
public:
|
||||
LldbDapEngine();
|
||||
|
||||
private:
|
||||
void setupEngine() override;
|
||||
|
||||
void handleDapInitialize() override;
|
||||
void handleDapConfigurationDone() override;
|
||||
|
||||
bool isLocalAttachEngine() const;
|
||||
bool acceptsBreakpoint(const BreakpointParameters &bp) const override;
|
||||
const QLoggingCategory &logCategory() override;
|
||||
};
|
||||
|
||||
} // Debugger::Internal
|
@@ -123,6 +123,7 @@ QtcPlugin {
|
||||
"dapclient.cpp", "dapclient.h",
|
||||
"dapengine.cpp", "dapengine.h",
|
||||
"gdbdapengine.cpp", "gdbdapengine.h",
|
||||
"lldbdapengine.cpp", "lldbdapengine.h",
|
||||
"pydapengine.cpp", "pydapengine.h",
|
||||
]
|
||||
}
|
||||
|
@@ -1224,6 +1224,7 @@ void DebuggerPluginPrivate::createDapDebuggerPerspective(QWidget *globalLogWindo
|
||||
ProjectExplorer::Constants::DAP_CMAKE_DEBUG_RUN_MODE,
|
||||
/*forceSkipDeploy=*/true},
|
||||
DapPerspective{Tr::tr("GDB Preset"), ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE},
|
||||
DapPerspective{Tr::tr("LLDB Preset"), ProjectExplorer::Constants::DAP_LLDB_DEBUG_RUN_MODE},
|
||||
DapPerspective{Tr::tr("Python Preset"), ProjectExplorer::Constants::DAP_PY_DEBUG_RUN_MODE},
|
||||
};
|
||||
|
||||
|
@@ -1096,6 +1096,7 @@ DebuggerRunWorkerFactory::DebuggerRunWorkerFactory()
|
||||
addSupportedRunMode(ProjectExplorer::Constants::DEBUG_RUN_MODE);
|
||||
addSupportedRunMode(ProjectExplorer::Constants::DAP_CMAKE_DEBUG_RUN_MODE);
|
||||
addSupportedRunMode(ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE);
|
||||
addSupportedRunMode(ProjectExplorer::Constants::DAP_LLDB_DEBUG_RUN_MODE);
|
||||
addSupportedDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
|
||||
addSupportedDeviceType("DockerDeviceType");
|
||||
|
||||
|
@@ -171,6 +171,7 @@ const char NORMAL_RUN_MODE[]="RunConfiguration.NormalRunMode";
|
||||
const char DEBUG_RUN_MODE[]="RunConfiguration.DebugRunMode";
|
||||
const char DAP_CMAKE_DEBUG_RUN_MODE[]="RunConfiguration.CmakeDebugRunMode";
|
||||
const char DAP_GDB_DEBUG_RUN_MODE[]="RunConfiguration.DapGdbDebugRunMode";
|
||||
const char DAP_LLDB_DEBUG_RUN_MODE[]="RunConfiguration.DapLldbDebugRunMode";
|
||||
const char DAP_PY_DEBUG_RUN_MODE[]="RunConfiguration.DapPyDebugRunMode";
|
||||
const char QML_PROFILER_RUN_MODE[]="RunConfiguration.QmlProfilerRunMode";
|
||||
const char QML_PROFILER_RUNNER[]="RunConfiguration.QmlProfilerRunner";
|
||||
|
Reference in New Issue
Block a user