[Lldb-commits] [lldb] 4f72abd - [LLDB] Add support for the structured data plugins in lldb-server (#159457)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Sep 18 07:40:59 PDT 2025
Author: Walter Erquinigo
Date: 2025-09-18T10:40:55-04:00
New Revision: 4f72abd8404efa3de32188429d5f079ad12264e3
URL: https://github.com/llvm/llvm-project/commit/4f72abd8404efa3de32188429d5f079ad12264e3
DIFF: https://github.com/llvm/llvm-project/commit/4f72abd8404efa3de32188429d5f079ad12264e3.diff
LOG: [LLDB] Add support for the structured data plugins in lldb-server (#159457)
The LLDB client has support for structured data plugins, but lldb-server
doesn't have corresponding support for it. This patch adds the missing
functionality in LLGS for servers to register their supported plugins
and send corresponding async messages.
Added:
Modified:
lldb/include/lldb/Host/common/NativeProcessProtocol.h
lldb/include/lldb/Utility/StringExtractorGDBRemote.h
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
lldb/source/Utility/StringExtractorGDBRemote.cpp
lldb/unittests/tools/lldb-server/tests/LLGSTest.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h
index 1d5fecfcd5c27..06b36c2cc9eb5 100644
--- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h
+++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h
@@ -409,6 +409,14 @@ class NativeProcessProtocol {
"Not implemented");
}
+ /// Get the list of structured data plugins supported by this process. They
+ /// must match the `type` field used by the corresponding
+ /// StructuredDataPlugins in the client.
+ ///
+ /// \return
+ /// A vector of structured data plugin names.
+ virtual std::vector<std::string> GetStructuredDataPlugins() { return {}; };
+
protected:
struct SoftwareBreakpoint {
uint32_t ref_count;
diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
index dd468ef5bddef..439245fdc3083 100644
--- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
+++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h
@@ -119,6 +119,7 @@ class StringExtractorGDBRemote : public StringExtractor {
eServerPacketType_qRegisterInfo,
eServerPacketType_qShlibInfoAddr,
eServerPacketType_qStepPacketSupported,
+ eServerPacketType_qStructuredDataPlugins,
eServerPacketType_qSupported,
eServerPacketType_qSyncThreadStateSupported,
eServerPacketType_qThreadExtraInfo,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index e3202d62ec7c8..2f62415446b7a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -146,6 +146,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
&GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qStructuredDataPlugins,
+ &GDBRemoteCommunicationServerLLGS::Handle_qStructuredDataPlugins);
RegisterMemberFunctionHandler(
StringExtractorGDBRemote::eServerPacketType_qsThreadInfo,
&GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);
@@ -1245,6 +1248,19 @@ Status GDBRemoteCommunicationServerLLGS::InitializeConnection(
return error;
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::SendStructuredDataPacket(
+ const llvm::json::Value &value) {
+ std::string json_string;
+ raw_string_ostream os(json_string);
+ os << value;
+
+ StreamGDBRemote escaped_response;
+ escaped_response.PutCString("JSON-async:");
+ escaped_response.PutEscapedBytes(json_string.c_str(), json_string.size());
+ return SendPacketNoLock(escaped_response.GetString());
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer,
uint32_t len) {
@@ -1436,6 +1452,21 @@ GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceGetBinaryData(
return SendErrorResponse(bytes.takeError());
}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_qStructuredDataPlugins(
+ StringExtractorGDBRemote &packet) {
+ // Fail if we don't have a current process.
+ if (!m_current_process ||
+ (m_current_process->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(68);
+
+ std::vector<std::string> structured_data_plugins =
+ m_current_process->GetStructuredDataPlugins();
+
+ return SendJSONResponse(
+ llvm::json::Value(llvm::json::Array(structured_data_plugins)));
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
StringExtractorGDBRemote &packet) {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index 646b6a102abf6..b400cc2fc21cd 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -86,6 +86,9 @@ class GDBRemoteCommunicationServerLLGS
Status InitializeConnection(std::unique_ptr<Connection> connection);
+ GDBRemoteCommunication::PacketResult
+ SendStructuredDataPacket(const llvm::json::Value &value);
+
struct DebuggedProcess {
enum class Flag {
vkilled = (1u << 0),
@@ -185,6 +188,8 @@ class GDBRemoteCommunicationServerLLGS
PacketResult Handle_qsThreadInfo(StringExtractorGDBRemote &packet);
+ PacketResult Handle_qStructuredDataPlugins(StringExtractorGDBRemote &packet);
+
PacketResult Handle_p(StringExtractorGDBRemote &packet);
PacketResult Handle_P(StringExtractorGDBRemote &packet);
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp
index c5755b2733605..010149ad4b381 100644
--- a/lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -280,6 +280,8 @@ StringExtractorGDBRemote::GetServerPacketType() const {
return eServerPacketType_qSupported;
if (PACKET_MATCHES("qSyncThreadStateSupported"))
return eServerPacketType_qSyncThreadStateSupported;
+ if (PACKET_MATCHES("qStructuredDataPlugins"))
+ return eServerPacketType_qStructuredDataPlugins;
break;
case 'T':
diff --git a/lldb/unittests/tools/lldb-server/tests/LLGSTest.cpp b/lldb/unittests/tools/lldb-server/tests/LLGSTest.cpp
index 34f8d23e94e4c..b438d7496d881 100644
--- a/lldb/unittests/tools/lldb-server/tests/LLGSTest.cpp
+++ b/lldb/unittests/tools/lldb-server/tests/LLGSTest.cpp
@@ -9,6 +9,7 @@
#include "TestBase.h"
#include "lldb/Host/Host.h"
#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
using namespace llgs_tests;
using namespace lldb_private;
@@ -74,3 +75,16 @@ TEST_F(TestBase, LLGS_TEST(vAttachRichError)) {
testing::StartsWith(
"cannot attach to process 1 when another process with pid"))));
}
+
+TEST_F(TestBase, LLGS_TEST(qStructuredDataPlugins)) {
+ auto ClientOr = TestClient::launchCustom(
+ getLogFileName(),
+ /* disable_stdio */ true, {}, {getInferiorPath("environment_check")});
+ ASSERT_THAT_EXPECTED(ClientOr, Succeeded());
+ auto &Client = **ClientOr;
+ std::string response_string;
+ ASSERT_THAT_ERROR(
+ Client.SendMessage("qStructuredDataPlugins", response_string),
+ Succeeded());
+ EXPECT_STREQ("[]", response_string.c_str());
+}
More information about the lldb-commits
mailing list