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 <[email protected]> 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]) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
