Skip to content

Conversation

walter-erquinigo
Copy link
Member

@walter-erquinigo walter-erquinigo commented Sep 17, 2025

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.

@llvmbot
Copy link
Member

llvmbot commented Sep 17, 2025

@llvm/pr-subscribers-lldb

Author: Walter Erquinigo (walter-erquinigo)

Changes

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.

I couldn't find a reasonable way to add a test for this, but the changes are trivial. I tested them with my custom server manually.


Full diff: https://github.com/llvm/llvm-project/pull/159457.diff

5 Files Affected:

  • (modified) lldb/include/lldb/Host/common/NativeProcessProtocol.h (+8)
  • (modified) lldb/include/lldb/Utility/StringExtractorGDBRemote.h (+1)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (+31)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h (+5)
  • (modified) lldb/source/Utility/StringExtractorGDBRemote.cpp (+2)
diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h
index 1d5fecfcd5c27..a09a54bcc5ec3 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
+  /// plugin. They must match the `type` fieldused 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':

@walter-erquinigo walter-erquinigo force-pushed the llvm-fork/werquinigo/structured-data branch from 587b5db to c86981d Compare September 17, 2025 21:19
Copy link
Contributor

@dmpots dmpots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change looks fine to me. Can we add a test for the qStructuredDataPlugins packet here?

https://github.com/llvm/llvm-project/blob/main/lldb/unittests/tools/lldb-server/tests/LLGSTest.cpp

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the 68 mean something special here? Can we use a named constant instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't know what it means, but the entire file does that :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, well makes sense to follow the pattern here then.

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.

I couldn't find a reasonable way to add a test for this, but the changes
are trivial. I tested them with my custom server manually.
@walter-erquinigo walter-erquinigo force-pushed the llvm-fork/werquinigo/structured-data branch from c86981d to 30b75dd Compare September 18, 2025 01:58
@walter-erquinigo
Copy link
Member Author

@dmpots , I've added the test

Copy link
Contributor

@dmpots dmpots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, well makes sense to follow the pattern here then.

@walter-erquinigo walter-erquinigo merged commit 4f72abd into llvm:main Sep 18, 2025
9 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 18, 2025

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building lldb at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/24402

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-unit :: ValueObject/./LLDBValueObjectTests/9/12 (2313 of 2322)
PASS: lldb-unit :: tools/lldb-server/tests/./LLDBServerTests/0/3 (2314 of 2322)
PASS: lldb-unit :: tools/lldb-server/tests/./LLDBServerTests/1/3 (2315 of 2322)
PASS: lldb-unit :: tools/lldb-server/tests/./LLDBServerTests/2/3 (2316 of 2322)
PASS: lldb-unit :: Target/./TargetTests/11/14 (2317 of 2322)
PASS: lldb-unit :: Host/./HostTests/4/9 (2318 of 2322)
PASS: lldb-unit :: Host/./HostTests/5/9 (2319 of 2322)
PASS: lldb-unit :: Host/./HostTests/8/9 (2320 of 2322)
PASS: lldb-unit :: Process/gdb-remote/./ProcessGdbRemoteTests/8/9 (2321 of 2322)
UNRESOLVED: lldb-api :: tools/lldb-server/TestLldbGdbServer.py (2322 of 2322)
******************** TEST 'lldb-api :: tools/lldb-server/TestLldbGdbServer.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --arch aarch64 --build-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --cmake-build-type Release /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/tools/lldb-server -p TestLldbGdbServer.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 22.0.0git (https://github.com/llvm/llvm-project.git revision 4f72abd8404efa3de32188429d5f079ad12264e3)
  clang revision 4f72abd8404efa3de32188429d5f079ad12264e3
  llvm revision 4f72abd8404efa3de32188429d5f079ad12264e3
Skipping the following test categories: ['libc++', 'msvcstl', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_Hc_then_Csignal_signals_correct_thread_launch_debugserver (TestLldbGdbServer.LldbGdbServerTestCase) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_Hc_then_Csignal_signals_correct_thread_launch_llgs (TestLldbGdbServer.LldbGdbServerTestCase)
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_Hg_fails_on_another_pid_llgs (TestLldbGdbServer.LldbGdbServerTestCase)
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_Hg_fails_on_minus_one_pid_llgs (TestLldbGdbServer.LldbGdbServerTestCase)
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_Hg_fails_on_zero_pid_llgs (TestLldbGdbServer.LldbGdbServerTestCase)
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_Hg_switches_to_3_threads_launch_debugserver (TestLldbGdbServer.LldbGdbServerTestCase) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_Hg_switches_to_3_threads_launch_llgs (TestLldbGdbServer.LldbGdbServerTestCase)
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_P_and_p_thread_suffix_work_debugserver (TestLldbGdbServer.LldbGdbServerTestCase) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_P_and_p_thread_suffix_work_llgs (TestLldbGdbServer.LldbGdbServerTestCase)
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_P_writes_all_gpr_registers_debugserver (TestLldbGdbServer.LldbGdbServerTestCase) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_P_writes_all_gpr_registers_llgs (TestLldbGdbServer.LldbGdbServerTestCase)
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_attach_commandline_continue_app_exits_debugserver (TestLldbGdbServer.LldbGdbServerTestCase) (test case does not fall in any category of interest for this run) 
Program aborted due to an unhandled Error:
Operation not permitted
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.	Program arguments: /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/lldb-server gdbserver --attach=351820 --reverse-connect [::1]:38587
 #0 0x0000c95355dace50 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/lldb-server+0x4fce50)
 #1 0x0000c95355daa978 llvm::sys::RunSignalHandlers() (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/lldb-server+0x4fa978)
 #2 0x0000c95355dadc68 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
 #3 0x0000f2ac00da28f8 (linux-vdso.so.1+0x8f8)
 #4 0x0000f2ac005af1f0 __pthread_kill_implementation ./nptl/pthread_kill.c:44:76

walter-erquinigo added a commit to clayborg/llvm-project that referenced this pull request Sep 30, 2025
…vm#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.
walter-erquinigo added a commit to clayborg/llvm-project that referenced this pull request Oct 9, 2025
…vm#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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants