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