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/dapclient.cpp dap/dapclient.h
|
||||||
dap/dapengine.cpp dap/dapengine.h
|
dap/dapengine.cpp dap/dapengine.h
|
||||||
dap/gdbdapengine.cpp dap/gdbdapengine.h
|
dap/gdbdapengine.cpp dap/gdbdapengine.h
|
||||||
|
dap/lldbdapengine.cpp dap/lldbdapengine.h
|
||||||
dap/pydapengine.cpp dap/pydapengine.h
|
dap/pydapengine.cpp dap/pydapengine.h
|
||||||
debugger.qrc
|
debugger.qrc
|
||||||
debugger_global.h
|
debugger_global.h
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
#include "cmakedapengine.h"
|
#include "cmakedapengine.h"
|
||||||
#include "dapclient.h"
|
#include "dapclient.h"
|
||||||
#include "gdbdapengine.h"
|
#include "gdbdapengine.h"
|
||||||
|
#include "lldbdapengine.h"
|
||||||
#include "pydapengine.h"
|
#include "pydapengine.h"
|
||||||
|
|
||||||
#include <debugger/breakhandler.h>
|
#include <debugger/breakhandler.h>
|
||||||
@@ -1058,6 +1059,8 @@ DebuggerEngine *createDapEngine(Utils::Id runMode)
|
|||||||
return new CMakeDapEngine;
|
return new CMakeDapEngine;
|
||||||
if (runMode == ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE)
|
if (runMode == ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE)
|
||||||
return new GdbDapEngine;
|
return new GdbDapEngine;
|
||||||
|
if (runMode == ProjectExplorer::Constants::DAP_LLDB_DEBUG_RUN_MODE)
|
||||||
|
return new LldbDapEngine;
|
||||||
if (runMode == ProjectExplorer::Constants::DAP_PY_DEBUG_RUN_MODE)
|
if (runMode == ProjectExplorer::Constants::DAP_PY_DEBUG_RUN_MODE)
|
||||||
return new PyDapEngine;
|
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",
|
"dapclient.cpp", "dapclient.h",
|
||||||
"dapengine.cpp", "dapengine.h",
|
"dapengine.cpp", "dapengine.h",
|
||||||
"gdbdapengine.cpp", "gdbdapengine.h",
|
"gdbdapengine.cpp", "gdbdapengine.h",
|
||||||
|
"lldbdapengine.cpp", "lldbdapengine.h",
|
||||||
"pydapengine.cpp", "pydapengine.h",
|
"pydapengine.cpp", "pydapengine.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -1224,6 +1224,7 @@ void DebuggerPluginPrivate::createDapDebuggerPerspective(QWidget *globalLogWindo
|
|||||||
ProjectExplorer::Constants::DAP_CMAKE_DEBUG_RUN_MODE,
|
ProjectExplorer::Constants::DAP_CMAKE_DEBUG_RUN_MODE,
|
||||||
/*forceSkipDeploy=*/true},
|
/*forceSkipDeploy=*/true},
|
||||||
DapPerspective{Tr::tr("GDB Preset"), ProjectExplorer::Constants::DAP_GDB_DEBUG_RUN_MODE},
|
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},
|
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::DEBUG_RUN_MODE);
|
||||||
addSupportedRunMode(ProjectExplorer::Constants::DAP_CMAKE_DEBUG_RUN_MODE);
|
addSupportedRunMode(ProjectExplorer::Constants::DAP_CMAKE_DEBUG_RUN_MODE);
|
||||||
addSupportedRunMode(ProjectExplorer::Constants::DAP_GDB_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(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
|
||||||
addSupportedDeviceType("DockerDeviceType");
|
addSupportedDeviceType("DockerDeviceType");
|
||||||
|
|
||||||
|
@@ -171,6 +171,7 @@ const char NORMAL_RUN_MODE[]="RunConfiguration.NormalRunMode";
|
|||||||
const char DEBUG_RUN_MODE[]="RunConfiguration.DebugRunMode";
|
const char DEBUG_RUN_MODE[]="RunConfiguration.DebugRunMode";
|
||||||
const char DAP_CMAKE_DEBUG_RUN_MODE[]="RunConfiguration.CmakeDebugRunMode";
|
const char DAP_CMAKE_DEBUG_RUN_MODE[]="RunConfiguration.CmakeDebugRunMode";
|
||||||
const char DAP_GDB_DEBUG_RUN_MODE[]="RunConfiguration.DapGdbDebugRunMode";
|
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 DAP_PY_DEBUG_RUN_MODE[]="RunConfiguration.DapPyDebugRunMode";
|
||||||
const char QML_PROFILER_RUN_MODE[]="RunConfiguration.QmlProfilerRunMode";
|
const char QML_PROFILER_RUN_MODE[]="RunConfiguration.QmlProfilerRunMode";
|
||||||
const char QML_PROFILER_RUNNER[]="RunConfiguration.QmlProfilerRunner";
|
const char QML_PROFILER_RUNNER[]="RunConfiguration.QmlProfilerRunner";
|
||||||
|
Reference in New Issue
Block a user