[Lldb-commits] [lldb] [lldb-server] Add accelerator plugin infrastructure for debugging hardware accelerators like gpus (PR #198907)
satyanarayana reddy janga via lldb-commits
lldb-commits at lists.llvm.org
Wed May 27 07:31:51 PDT 2026
https://github.com/satyajanga updated https://github.com/llvm/llvm-project/pull/198907
>From 1eed527606b1d24de71ad1d3be0c534f0a0974d5 Mon Sep 17 00:00:00 2001
From: satya janga <satyajanga at fb.com>
Date: Thu, 21 May 2026 07:18:21 -0700
Subject: [PATCH] [lldb-server] Add accelerator plugin infrastructure with
protocol support
Add an extensible plugin system to lldb-server for debugging hardware
accelerators (GPUs, FPGAs, etc.) alongside the native host process.
This is the first step toward upstreaming the server-side plugin
support from the clayborg/llvm-server-plugins branch.
This patch adds:
- LLDBServerAcceleratorPlugin base class with GetPluginName() and
GetInitializeActions() virtual methods
- AcceleratorActions struct with JSON encode/decode
- accelerator-plugins+ feature in qSupported, only advertised when
at least one plugin is installed
- jAcceleratorPluginInitialize packet handler that returns a JSON
array of AcceleratorActions from all installed plugins
- PutAsJSON/PutAsJSONArray template methods on StreamGDBRemote
- InstallPlugin() on GDBRemoteCommunicationServerLLGS for registering
plugins directly (no PluginManager integration)
- Mock accelerator plugin gated by LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN
CMake option (default OFF)
- Tests verifying qSupported feature and jAcceleratorPluginInitialize
JSON response round-trip against a real lldb-server
---
lldb/docs/resources/lldbgdbremote.md | 54 +++++++++++++-
.../lldb/Host/common/NativeProcessProtocol.h | 3 +-
.../Utility/AcceleratorGDBRemotePackets.h | 38 ++++++++++
lldb/include/lldb/Utility/GDBRemote.h | 20 +++++
.../lldb/Utility/StringExtractorGDBRemote.h | 1 +
.../tools/lldb-server/gdbremote_testcase.py | 1 +
.../Plugins/Process/gdb-remote/CMakeLists.txt | 1 +
.../GDBRemoteCommunicationServerLLGS.cpp | 23 ++++++
.../GDBRemoteCommunicationServerLLGS.h | 9 +++
.../LLDBServerAcceleratorPlugin.cpp | 17 +++++
.../gdb-remote/LLDBServerAcceleratorPlugin.h | 43 +++++++++++
.../Utility/AcceleratorGDBRemotePackets.cpp | 27 +++++++
lldb/source/Utility/CMakeLists.txt | 1 +
.../Utility/StringExtractorGDBRemote.cpp | 2 +
lldb/test/API/accelerator/mock/Makefile | 3 +
.../mock/TestMockAcceleratorPlugin.py | 74 +++++++++++++++++++
lldb/test/API/accelerator/mock/main.c | 1 +
lldb/test/API/lit.site.cfg.py.in | 3 +
lldb/test/CMakeLists.txt | 1 +
lldb/tools/lldb-server/CMakeLists.txt | 17 +++++
.../Plugins/Accelerator/CMakeLists.txt | 1 +
.../Plugins/Accelerator/Mock/CMakeLists.txt | 12 +++
.../Mock/LLDBServerMockAcceleratorPlugin.cpp | 24 ++++++
.../Mock/LLDBServerMockAcceleratorPlugin.h | 28 +++++++
lldb/tools/lldb-server/Plugins/CMakeLists.txt | 1 +
lldb/tools/lldb-server/lldb-gdbserver.cpp | 10 +++
lldb/utils/lldb-dotest/CMakeLists.txt | 1 +
lldb/utils/lldb-dotest/lldb-dotest.in | 3 +
28 files changed, 414 insertions(+), 5 deletions(-)
create mode 100644 lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h
create mode 100644 lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.cpp
create mode 100644 lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h
create mode 100644 lldb/source/Utility/AcceleratorGDBRemotePackets.cpp
create mode 100644 lldb/test/API/accelerator/mock/Makefile
create mode 100644 lldb/test/API/accelerator/mock/TestMockAcceleratorPlugin.py
create mode 100644 lldb/test/API/accelerator/mock/main.c
create mode 100644 lldb/tools/lldb-server/Plugins/Accelerator/CMakeLists.txt
create mode 100644 lldb/tools/lldb-server/Plugins/Accelerator/Mock/CMakeLists.txt
create mode 100644 lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.cpp
create mode 100644 lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h
create mode 100644 lldb/tools/lldb-server/Plugins/CMakeLists.txt
diff --git a/lldb/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md
index e93a5ea120d17..74a347b93824d 100644
--- a/lldb/docs/resources/lldbgdbremote.md
+++ b/lldb/docs/resources/lldbgdbremote.md
@@ -120,6 +120,52 @@ In any case, if we want the normal detach behavior we will just send:
D
```
+## jAcceleratorPluginInitialize
+
+This packet requests initialization data from all accelerator plugins
+installed in lldb-server. Accelerator plugins allow lldb-server to support
+debugging of hardware accelerators (e.g. GPUs, FPGAs) alongside the native
+host process.
+
+This packet requires the `accelerator-plugins+` feature from `qSupported`.
+It should be sent early in the session, after `qSupported` but before
+launching or attaching to an inferior process. If the hardware accelerator
+is not present, launching or attaching to the accelerator debug session
+will fail.
+
+```
+LLDB SENDS: jAcceleratorPluginInitialize
+STUB REPLIES: [<accelerator_action>,...]
+```
+
+Each `accelerator_action` is a JSON object with the following required fields:
+
+| Key | Type | Description |
+|----------------|---------|-------------|
+| `plugin_name` | string | Unique name identifying the accelerator plugin (e.g. `"mock"`, `"amdgpu"`). Each installed plugin has a globally unique name. |
+| `session_name` | string | Human-readable label for the accelerator target, stored on the Target object to distinguish it from the CPU target (e.g. `"AMD GPU Session"`). May be empty. |
+| `identifier` | integer | Identifier for this action, unique within the scope of its `plugin_name`. To refer to a specific action, use the combination of `plugin_name` and `identifier`. |
+
+There can be multiple accelerator plugins installed, each with a globally
+unique `plugin_name`. The response is a JSON array with one entry per
+installed plugin.
+
+Example:
+```
+LLDB SENDS: jAcceleratorPluginInitialize
+STUB REPLIES: [{"plugin_name":"amdgpu","session_name":"AMD GPU Session","identifier":0}]
+```
+
+If no accelerator plugins are installed, the server does not advertise the
+`accelerator-plugins+` feature and this packet should not be sent.
+
+In future patches, each `accelerator_action` will include additional fields
+such as breakpoints to set in the native process, connection info for
+secondary debug sessions, and synchronization options.
+
+**Priority To Implement:** Low. Only needed for hardware accelerator
+debugging support.
+
## jGetDyldProcessState
This packet fetches the process launch state, as reported by libdyld on
@@ -168,7 +214,7 @@ fetch detailed information in batches, to keep the size of the
packets from becoming too large.
-And the second form of jGetLoadedDynamicLibrariesInfos
+And the second form of jGetLoadedDynamicLibrariesInfos
requests information about a list of binaries, given their load addresses:
```
jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
@@ -1188,7 +1234,7 @@ In the example above, three lldb extensions are shown:
* A list of compression types that the stub can use to compress packets
when the QEnableCompression packet is used to request one of them.
* `SupportedWatchpointTypes=<item,item,...>`
- * A list of watchpoint types that this stub can manage. Currently defined
+ * A list of watchpoint types that this stub can manage. Currently defined
names are:
* `x86_64` - 64-bit x86-64 watchpoints (1, 2, 4, 8 byte watchpoints
aligned to those amounts)
@@ -1518,7 +1564,7 @@ tuples to return are:
region that are "dirty" -- they have been modified.
Page addresses are in base 16. The size of a page can
be found from the `qHostInfo`'s `page-size` key-value.
-
+
If the stub supports identifying dirty pages within a
memory region, this key should always be present for all
`qMemoryRegionInfo` replies. This key with no pages
@@ -1598,7 +1644,7 @@ The request packet has the fields:
1. mode bits in base 16
2. file path in ascii-hex encoding
-Reply:
+Reply:
* `F<mkdir-return-code>`
(mkdir called successfully and returned with the given return code)
* `Exx` (An error occurred)
diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h
index 3b133bd218316..f3c0f16502fab 100644
--- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h
+++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h
@@ -287,8 +287,9 @@ class NativeProcessProtocol {
savecore = (1u << 7),
siginfo_read = (1u << 8),
libraries = (1u << 9),
+ accelerator_plugins = (1u << 10),
- LLVM_MARK_AS_BITMASK_ENUM(libraries)
+ LLVM_MARK_AS_BITMASK_ENUM(accelerator_plugins)
};
class Manager {
diff --git a/lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h b/lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h
new file mode 100644
index 0000000000000..479503bf47a3c
--- /dev/null
+++ b/lldb/include/lldb/Utility/AcceleratorGDBRemotePackets.h
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_ACCELERATORGDBREMOTEPACKETS_H
+#define LLDB_UTILITY_ACCELERATORGDBREMOTEPACKETS_H
+
+#include "llvm/Support/JSON.h"
+#include <cstdint>
+#include <string>
+
+namespace lldb_private {
+
+struct AcceleratorActions {
+ AcceleratorActions() = default;
+ AcceleratorActions(llvm::StringRef plugin_name, int64_t action_id)
+ : plugin_name(plugin_name), identifier(action_id) {}
+
+ /// Unique name identifying the accelerator plugin.
+ std::string plugin_name;
+ /// Human-readable label for the accelerator target.
+ std::string session_name;
+ /// Unique identifier for this action within the plugin.
+ int64_t identifier = 0;
+};
+
+bool fromJSON(const llvm::json::Value &value, AcceleratorActions &data,
+ llvm::json::Path path);
+
+llvm::json::Value toJSON(const AcceleratorActions &data);
+
+} // namespace lldb_private
+
+#endif // LLDB_UTILITY_ACCELERATORGDBREMOTEPACKETS_H
diff --git a/lldb/include/lldb/Utility/GDBRemote.h b/lldb/include/lldb/Utility/GDBRemote.h
index ab33f02ebb012..888a4dd54124d 100644
--- a/lldb/include/lldb/Utility/GDBRemote.h
+++ b/lldb/include/lldb/Utility/GDBRemote.h
@@ -13,6 +13,7 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
+#include "llvm/Support/JSON.h"
#include "llvm/Support/raw_ostream.h"
#include <cstddef>
@@ -45,6 +46,25 @@ class StreamGDBRemote : public StreamString {
/// Equivalent to PutEscapedBytes(str.data(), str.size());
int PutEscapedBytes(llvm::StringRef str);
+
+ template <class T> int PutAsJSON(const T &obj, bool hex_ascii) {
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << llvm::json::Value(toJSON(obj));
+ if (hex_ascii)
+ return PutStringAsRawHex8(json_string);
+ return PutEscapedBytes(json_string.c_str(), json_string.size());
+ }
+
+ template <class T> int PutAsJSONArray(const std::vector<T> &array) {
+ llvm::json::Array json_array;
+ for (const auto &obj : array)
+ json_array.push_back(toJSON(obj));
+ std::string json_string;
+ llvm::raw_string_ostream os(json_string);
+ os << llvm::json::Value(std::move(json_array));
+ return PutEscapedBytes(json_string.data(), json_string.size());
+ }
};
/// GDB remote packet as used by the GDB remote communication history. Packets
diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
index 9aeac03a54bee..85ec27cac9ac0 100644
--- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
+++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
@@ -173,6 +173,7 @@ class StringExtractorGDBRemote : public StringExtractor {
eServerPacketType_jLLDBTraceGetState,
eServerPacketType_jLLDBTraceGetBinaryData,
eServerPacketType_jMultiBreakpoint,
+ eServerPacketType_jAcceleratorPluginInitialize,
eServerPacketType_qMemTags, // read memory tags
eServerPacketType_QMemTags, // write memory tags
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
index 9eb390f51ac7b..3e89555f24ff3 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
@@ -940,6 +940,7 @@ def add_qSupported_packets(self, client_features=[]):
"SupportedCompressions",
"MultiMemRead",
"jMultiBreakpoint",
+ "accelerator-plugins",
]
def parse_qSupported_response(self, context):
diff --git a/lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt b/lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt
index d805d3930cda3..00a59f8ef2ad4 100644
--- a/lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt
@@ -31,6 +31,7 @@ add_lldb_library(lldbPluginProcessGDBRemote PLUGIN
GDBRemoteCommunicationServerCommon.cpp
GDBRemoteCommunicationServerLLGS.cpp
GDBRemoteCommunicationServerPlatform.cpp
+ LLDBServerAcceleratorPlugin.cpp
GDBRemoteRegisterContext.cpp
GDBRemoteRegisterFallback.cpp
ProcessGDBRemote.cpp
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index c3c70ad93e9e5..dab08d96adc4a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -31,6 +31,7 @@
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/AcceleratorGDBRemotePackets.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/Endian.h"
@@ -54,6 +55,7 @@
using namespace lldb;
using namespace lldb_private;
+using namespace lldb_private::lldb_server;
using namespace lldb_private::process_gdb_remote;
using namespace llvm;
@@ -221,6 +223,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_jMultiBreakpoint,
&GDBRemoteCommunicationServerLLGS::Handle_jMultiBreakpoint);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jAcceleratorPluginInitialize,
+ &GDBRemoteCommunicationServerLLGS::Handle_jAcceleratorPluginInitialize);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g,
&GDBRemoteCommunicationServerLLGS::Handle_g);
@@ -4432,6 +4437,8 @@ std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures(
ret.push_back("memory-tagging+");
if (bool(plugin_features & Extension::savecore))
ret.push_back("qSaveCore+");
+ if (!m_accelerator_plugins.empty())
+ ret.push_back("accelerator-plugins+");
// check for client features
m_extensions_supported = {};
@@ -4523,3 +4530,19 @@ lldb_private::process_gdb_remote::LLGSArgToURL(llvm::StringRef url_arg,
return (reverse_connect ? "unix-connect://" : "unix-accept://") +
url_arg.str();
}
+
+void GDBRemoteCommunicationServerLLGS::InstallPlugin(
+ std::unique_ptr<LLDBServerAcceleratorPlugin> plugin_up) {
+ m_accelerator_plugins.emplace_back(std::move(plugin_up));
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jAcceleratorPluginInitialize(
+ StringExtractorGDBRemote &) {
+ std::vector<AcceleratorActions> accelerator_actions;
+ for (auto &plugin_up : m_accelerator_plugins)
+ accelerator_actions.push_back(plugin_up->GetInitializeActions());
+ StreamGDBRemote response;
+ response.PutAsJSONArray(accelerator_actions);
+ return SendPacketNoLock(response.GetString());
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index ee4372adc0b40..5a088f8de2380 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -20,6 +20,7 @@
#include "lldb/lldb-private-forward.h"
#include "GDBRemoteCommunicationServerCommon.h"
+#include "LLDBServerAcceleratorPlugin.h"
class StringExtractorGDBRemote;
@@ -72,6 +73,9 @@ class GDBRemoteCommunicationServerLLGS
/// attach operation.
Status AttachWaitProcess(llvm::StringRef process_name, bool include_existing);
+ void InstallPlugin(
+ std::unique_ptr<lldb_server::LLDBServerAcceleratorPlugin> plugin_up);
+
// NativeProcessProtocol::NativeDelegate overrides
void InitializeDelegate(NativeProcessProtocol *process) override;
@@ -104,6 +108,8 @@ class GDBRemoteCommunicationServerLLGS
MainLoop &m_mainloop;
MainLoop::ReadHandleUP m_network_handle_up;
NativeProcessProtocol::Manager &m_process_manager;
+ std::vector<std::unique_ptr<lldb_server::LLDBServerAcceleratorPlugin>>
+ m_accelerator_plugins;
lldb::tid_t m_current_tid = LLDB_INVALID_THREAD_ID;
lldb::tid_t m_continue_tid = LLDB_INVALID_THREAD_ID;
NativeProcessProtocol *m_current_process;
@@ -278,6 +284,9 @@ class GDBRemoteCommunicationServerLLGS
PacketResult Handle_jMultiBreakpoint(StringExtractorGDBRemote &packet);
+ PacketResult
+ Handle_jAcceleratorPluginInitialize(StringExtractorGDBRemote &packet);
+
void SetCurrentThreadID(lldb::tid_t tid);
lldb::tid_t GetCurrentThreadID() const;
diff --git a/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.cpp b/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.cpp
new file mode 100644
index 0000000000000..ce3b767832095
--- /dev/null
+++ b/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.cpp
@@ -0,0 +1,17 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLDBServerAcceleratorPlugin.h"
+
+using namespace lldb_private::lldb_server;
+
+LLDBServerAcceleratorPlugin::LLDBServerAcceleratorPlugin(GDBServer &gdb_server,
+ MainLoop &main_loop)
+ : m_gdb_server(gdb_server), m_main_loop(main_loop) {}
+
+LLDBServerAcceleratorPlugin::~LLDBServerAcceleratorPlugin() = default;
diff --git a/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h b/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h
new file mode 100644
index 0000000000000..baffd30ebb40b
--- /dev/null
+++ b/lldb/source/Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_LLDBSERVERACCELERATORPLUGIN_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_LLDBSERVERACCELERATORPLUGIN_H
+
+#include "lldb/Host/MainLoop.h"
+#include "lldb/Utility/AcceleratorGDBRemotePackets.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace lldb_private {
+
+namespace process_gdb_remote {
+class GDBRemoteCommunicationServerLLGS;
+} // namespace process_gdb_remote
+
+namespace lldb_server {
+
+class LLDBServerAcceleratorPlugin {
+public:
+ using GDBServer = process_gdb_remote::GDBRemoteCommunicationServerLLGS;
+
+ LLDBServerAcceleratorPlugin(GDBServer &gdb_server, MainLoop &main_loop);
+ virtual ~LLDBServerAcceleratorPlugin();
+
+ virtual llvm::StringRef GetPluginName() = 0;
+
+ virtual AcceleratorActions GetInitializeActions() = 0;
+
+protected:
+ GDBServer &m_gdb_server;
+ MainLoop &m_main_loop;
+};
+
+} // namespace lldb_server
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_LLDBSERVERACCELERATORPLUGIN_H
diff --git a/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp b/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp
new file mode 100644
index 0000000000000..8019db4328c78
--- /dev/null
+++ b/lldb/source/Utility/AcceleratorGDBRemotePackets.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/AcceleratorGDBRemotePackets.h"
+
+using namespace lldb_private;
+
+llvm::json::Value lldb_private::toJSON(const AcceleratorActions &data) {
+ return llvm::json::Object{
+ {"plugin_name", data.plugin_name},
+ {"session_name", data.session_name},
+ {"identifier", data.identifier},
+ };
+}
+
+bool lldb_private::fromJSON(const llvm::json::Value &value,
+ AcceleratorActions &data, llvm::json::Path path) {
+ llvm::json::ObjectMapper o(value, path);
+ return o && o.map("plugin_name", data.plugin_name) &&
+ o.map("session_name", data.session_name) &&
+ o.map("identifier", data.identifier);
+}
diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt
index 3836ab0ec6c29..080e0d1a0fd96 100644
--- a/lldb/source/Utility/CMakeLists.txt
+++ b/lldb/source/Utility/CMakeLists.txt
@@ -44,6 +44,7 @@ add_lldb_library(lldbUtility NO_INTERNAL_DEPENDENCIES
FileSpec.cpp
FileSpecList.cpp
GDBRemote.cpp
+ AcceleratorGDBRemotePackets.cpp
IOObject.cpp
LLDBAssert.cpp
LLDBLog.cpp
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp
index 17e36398fc218..7b46bef933ac2 100644
--- a/lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -332,6 +332,8 @@ StringExtractorGDBRemote::GetServerPacketType() const {
return eServerPacketType_jLLDBTraceGetBinaryData;
if (PACKET_STARTS_WITH("jMultiBreakpoint:"))
return eServerPacketType_jMultiBreakpoint;
+ if (PACKET_MATCHES("jAcceleratorPluginInitialize"))
+ return eServerPacketType_jAcceleratorPluginInitialize;
break;
case 'v':
diff --git a/lldb/test/API/accelerator/mock/Makefile b/lldb/test/API/accelerator/mock/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/accelerator/mock/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/accelerator/mock/TestMockAcceleratorPlugin.py b/lldb/test/API/accelerator/mock/TestMockAcceleratorPlugin.py
new file mode 100644
index 0000000000000..3e9ca174cd533
--- /dev/null
+++ b/lldb/test/API/accelerator/mock/TestMockAcceleratorPlugin.py
@@ -0,0 +1,74 @@
+"""
+Tests for the lldb-server mock accelerator plugin.
+
+Verifies the accelerator-plugins+ feature in qSupported and
+the jAcceleratorPluginInitialize packet response.
+"""
+
+import json
+
+import gdbremote_testcase
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import configuration
+
+
+def get_accelerator_action(actions, plugin_name):
+ for action in actions:
+ if action["plugin_name"] == plugin_name:
+ return action
+ return None
+
+
+class MockAcceleratorPluginTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
+ def setUp(self):
+ super().setUp()
+ if "mock-accelerator" not in configuration.enabled_plugins:
+ self.skipTest("mock-accelerator plugin is not enabled")
+
+ @add_test_categories(["llgs"])
+ def test_qSupported_reports_accelerator_plugins(self):
+ self.build()
+ self.set_inferior_startup_launch()
+ self.prep_debug_monitor_and_inferior()
+
+ self.add_qSupported_packets()
+ context = self.expect_gdbremote_sequence()
+ features = self.parse_qSupported_response(context)
+
+ self.assertIn("accelerator-plugins", features)
+ self.assertEqual(features["accelerator-plugins"], "+")
+
+ @add_test_categories(["llgs"])
+ def test_jAcceleratorPluginInitialize_returns_mock_actions(self):
+ self.build()
+ self.set_inferior_startup_launch()
+ self.prep_debug_monitor_and_inferior()
+
+ self.add_qSupported_packets()
+ self.expect_gdbremote_sequence()
+
+ self.test_sequence.add_log_lines(
+ [
+ "read packet: $jAcceleratorPluginInitialize#00",
+ {
+ "direction": "send",
+ "regex": r"^\$(.+)#[0-9a-fA-F]{2}",
+ "capture": {1: "accel_init_response"},
+ },
+ ],
+ True,
+ )
+ context = self.expect_gdbremote_sequence()
+
+ raw_response = context.get("accel_init_response")
+ self.assertIsNotNone(raw_response)
+
+ decoded = self.decode_gdbremote_binary(raw_response)
+ actions = json.loads(decoded)
+ self.assertIsInstance(actions, list)
+
+ mock_action = get_accelerator_action(actions, "mock")
+ self.assertIsNotNone(mock_action)
+ self.assertIn("session_name", mock_action)
+ self.assertIn("identifier", mock_action)
diff --git a/lldb/test/API/accelerator/mock/main.c b/lldb/test/API/accelerator/mock/main.c
new file mode 100644
index 0000000000000..78f2de106c92b
--- /dev/null
+++ b/lldb/test/API/accelerator/mock/main.c
@@ -0,0 +1 @@
+int main(void) { return 0; }
diff --git a/lldb/test/API/lit.site.cfg.py.in b/lldb/test/API/lit.site.cfg.py.in
index 35d108f53e119..b5b070bb8d60d 100644
--- a/lldb/test/API/lit.site.cfg.py.in
+++ b/lldb/test/API/lit.site.cfg.py.in
@@ -54,6 +54,9 @@ config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb
lldb_build_intel_pt = '@LLDB_BUILD_INTEL_PT@'
if lldb_build_intel_pt == '1':
config.enabled_plugins.append('intel-pt')
+lldb_build_mock_accelerator = '@LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN@'
+if lldb_build_mock_accelerator == '1':
+ config.enabled_plugins.append('mock-accelerator')
# Additional dotest arguments can be passed to lit by providing a
# semicolon-separates list: --param dotest-args="arg;arg".
diff --git a/lldb/test/CMakeLists.txt b/lldb/test/CMakeLists.txt
index ed9dcd11cc6cd..d5e4377648da8 100644
--- a/lldb/test/CMakeLists.txt
+++ b/lldb/test/CMakeLists.txt
@@ -260,6 +260,7 @@ set(LLDB_TEST_USE_LLDB_SERVER OFF CACHE BOOL "If ON, run the test suites against
# These values are not canonicalized within LLVM.
llvm_canonicalize_cmake_booleans(
LLDB_BUILD_INTEL_PT
+ LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN
LLDB_ENABLE_MTE
LLDB_ENABLE_PYTHON
LLDB_ENABLE_LUA
diff --git a/lldb/tools/lldb-server/CMakeLists.txt b/lldb/tools/lldb-server/CMakeLists.txt
index fb55c64936121..aedd7ab9f885e 100644
--- a/lldb/tools/lldb-server/CMakeLists.txt
+++ b/lldb/tools/lldb-server/CMakeLists.txt
@@ -34,6 +34,17 @@ else()
list(APPEND LLDB_PLUGINS lldbPluginObjectFileELF)
endif()
+option(LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN
+ "Enable the mock accelerator plugin for testing" OFF)
+
+add_subdirectory(Plugins)
+
+set(LLDB_SERVER_PLUGINS)
+
+if(LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN)
+ list(APPEND LLDB_SERVER_PLUGINS lldbServerPluginMockAccelerator)
+endif()
+
if(APPLE_EMBEDDED)
if(LLDB_CODESIGN_IDENTITY)
# Use explicit LLDB identity
@@ -61,6 +72,7 @@ add_lldb_tool(lldb-server
lldbInitialization
lldbVersion
${LLDB_PLUGINS}
+ ${LLDB_SERVER_PLUGINS}
lldbPluginInstructionARM
lldbPluginInstructionLoongArch
lldbPluginInstructionMIPS
@@ -76,3 +88,8 @@ add_dependencies(lldb-server
)
target_include_directories(lldb-server PRIVATE "${LLDB_SOURCE_DIR}/source")
target_link_libraries(lldb-server PRIVATE ${LLDB_SYSTEM_LIBS})
+
+if(LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN)
+ target_compile_definitions(lldb-server
+ PRIVATE LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN)
+endif()
diff --git a/lldb/tools/lldb-server/Plugins/Accelerator/CMakeLists.txt b/lldb/tools/lldb-server/Plugins/Accelerator/CMakeLists.txt
new file mode 100644
index 0000000000000..853788384e141
--- /dev/null
+++ b/lldb/tools/lldb-server/Plugins/Accelerator/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(Mock)
diff --git a/lldb/tools/lldb-server/Plugins/Accelerator/Mock/CMakeLists.txt b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/CMakeLists.txt
new file mode 100644
index 0000000000000..9b5a82a087e3d
--- /dev/null
+++ b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_lldb_library(lldbServerPluginMockAccelerator
+ LLDBServerMockAcceleratorPlugin.cpp
+
+ LINK_LIBS
+ lldbHost
+ lldbUtility
+)
+
+target_include_directories(lldbServerPluginMockAccelerator
+ PRIVATE
+ "${LLDB_SOURCE_DIR}/source"
+)
diff --git a/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.cpp b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.cpp
new file mode 100644
index 0000000000000..cade2dfa1231b
--- /dev/null
+++ b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLDBServerMockAcceleratorPlugin.h"
+
+using namespace lldb_private;
+using namespace lldb_private::lldb_server;
+
+LLDBServerMockAcceleratorPlugin::LLDBServerMockAcceleratorPlugin(
+ GDBServer &gdb_server, MainLoop &main_loop)
+ : LLDBServerAcceleratorPlugin(gdb_server, main_loop) {}
+
+llvm::StringRef LLDBServerMockAcceleratorPlugin::GetPluginName() {
+ return "mock";
+}
+
+AcceleratorActions LLDBServerMockAcceleratorPlugin::GetInitializeActions() {
+ return AcceleratorActions(GetPluginName(), 0);
+}
diff --git a/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h
new file mode 100644
index 0000000000000..d145a97cffb8c
--- /dev/null
+++ b/lldb/tools/lldb-server/Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_TOOLS_LLDB_SERVER_PLUGINS_ACCELERATOR_MOCK_LLDBSERVERMOCKACCELERATORPLUGIN_H
+#define LLDB_TOOLS_LLDB_SERVER_PLUGINS_ACCELERATOR_MOCK_LLDBSERVERMOCKACCELERATORPLUGIN_H
+
+#include "Plugins/Process/gdb-remote/LLDBServerAcceleratorPlugin.h"
+
+namespace lldb_private {
+namespace lldb_server {
+
+class LLDBServerMockAcceleratorPlugin : public LLDBServerAcceleratorPlugin {
+public:
+ LLDBServerMockAcceleratorPlugin(GDBServer &gdb_server, MainLoop &main_loop);
+
+ llvm::StringRef GetPluginName() override;
+ AcceleratorActions GetInitializeActions() override;
+};
+
+} // namespace lldb_server
+} // namespace lldb_private
+
+#endif // LLDB_TOOLS_LLDB_SERVER_PLUGINS_ACCELERATOR_MOCK_LLDBSERVERMOCKACCELERATORPLUGIN_H
diff --git a/lldb/tools/lldb-server/Plugins/CMakeLists.txt b/lldb/tools/lldb-server/Plugins/CMakeLists.txt
new file mode 100644
index 0000000000000..c9f43933b3b55
--- /dev/null
+++ b/lldb/tools/lldb-server/Plugins/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(Accelerator)
diff --git a/lldb/tools/lldb-server/lldb-gdbserver.cpp b/lldb/tools/lldb-server/lldb-gdbserver.cpp
index bb758bffad076..2e00c66eaa4dd 100644
--- a/lldb/tools/lldb-server/lldb-gdbserver.cpp
+++ b/lldb/tools/lldb-server/lldb-gdbserver.cpp
@@ -38,6 +38,10 @@
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/WithColor.h"
+#if defined(LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN)
+#include "Plugins/Accelerator/Mock/LLDBServerMockAcceleratorPlugin.h"
+#endif
+
#if defined(__linux__)
#include "Plugins/Process/Linux/NativeProcessLinux.h"
#elif defined(__FreeBSD__)
@@ -450,6 +454,12 @@ int main_gdbserver(int argc, char *argv[]) {
NativeProcessManager manager(mainloop);
GDBRemoteCommunicationServerLLGS gdb_server(mainloop, manager);
+#if defined(LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN)
+ gdb_server.InstallPlugin(
+ std::make_unique<lldb_server::LLDBServerMockAcceleratorPlugin>(gdb_server,
+ mainloop));
+#endif
+
llvm::StringRef host_and_port;
if (!Inputs.empty() && connection_fd == SharedSocket::kInvalidFD) {
host_and_port = Inputs.front();
diff --git a/lldb/utils/lldb-dotest/CMakeLists.txt b/lldb/utils/lldb-dotest/CMakeLists.txt
index 23f1fc23c783d..83c2093230cd0 100644
--- a/lldb/utils/lldb-dotest/CMakeLists.txt
+++ b/lldb/utils/lldb-dotest/CMakeLists.txt
@@ -17,6 +17,7 @@ endif()
llvm_canonicalize_cmake_booleans(
LLDB_BUILD_INTEL_PT
+ LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN
LLDB_HAS_LIBCXX
LLDB_USE_ARM64E_DEBUGSERVER
)
diff --git a/lldb/utils/lldb-dotest/lldb-dotest.in b/lldb/utils/lldb-dotest/lldb-dotest.in
index 9e0c740efe9f5..dd865bc5246b4 100755
--- a/lldb/utils/lldb-dotest/lldb-dotest.in
+++ b/lldb/utils/lldb-dotest/lldb-dotest.in
@@ -13,6 +13,7 @@ dsymutil = '@LLDB_TEST_DSYMUTIL_CONFIGURED@'
make = '@LLDB_TEST_MAKE_CONFIGURED@'
lldb_build_dir = '@LLDB_TEST_BUILD_DIRECTORY_CONFIGURED@'
lldb_build_intel_pt = "@LLDB_BUILD_INTEL_PT@"
+lldb_build_mock_accelerator = "@LLDB_ENABLE_MOCK_ACCELERATOR_PLUGIN@"
lldb_framework_dir = "@LLDB_FRAMEWORK_DIR_CONFIGURED@"
lldb_libs_dir = "@LLDB_LIBS_DIR_CONFIGURED@"
llvm_tools_dir = "@LLVM_TOOLS_DIR_CONFIGURED@"
@@ -54,6 +55,8 @@ if __name__ == '__main__':
cmd.extend(['--framework', lldb_framework_dir])
if lldb_build_intel_pt == "1":
cmd.extend(['--enable-plugin', 'intel-pt'])
+ if lldb_build_mock_accelerator == "1":
+ cmd.extend(['--enable-plugin', 'mock-accelerator'])
if lldb_enable_arm64e_debugserver:
cmd.extend(['--arm64e-debugserver'])
cmd.extend(['--lldb-obj-root', lldb_obj_root])
More information about the lldb-commits
mailing list