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());
+}


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to