https://github.com/felipepiovezan created https://github.com/llvm/llvm-project/pull/192919
This is fairly straightfoward, thanks to the helper functions created in the previous commit. https://github.com/llvm/llvm-project/pull/192910 >From 6bf0eda13ffc1da1987fdc01ee8e9221fa8eb417 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan <[email protected]> Date: Mon, 23 Mar 2026 09:26:32 +0000 Subject: [PATCH] [lldbserver] Implement support for MultiBreakpoint packet This is fairly straightfoward, thanks to the helper functions created in the previous commit. https://github.com/llvm/llvm-project/pull/192910 --- .../lldb/Utility/StringExtractorGDBRemote.h | 1 + .../tools/lldb-server/gdbremote_testcase.py | 1 + .../GDBRemoteCommunicationServerLLGS.cpp | 59 +++++++++++++++++++ .../GDBRemoteCommunicationServerLLGS.h | 2 + .../Utility/StringExtractorGDBRemote.cpp | 2 + .../multi-breakpoint/TestMultiBreakpoint.py | 1 - 6 files changed, 65 insertions(+), 1 deletion(-) diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h index 439245fdc3083..1fdf913ccf3ae 100644 --- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h +++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h @@ -162,6 +162,7 @@ class StringExtractorGDBRemote : public StringExtractor { eServerPacketType_X, eServerPacketType_Z, eServerPacketType_z, + eServerPacketType_MultiBreakpoint, eServerPacketType__M, eServerPacketType__m, 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 5ba642bbedf74..020649bd0023c 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 @@ -932,6 +932,7 @@ def add_qSupported_packets(self, client_features=[]): "SupportedWatchpointTypes", "SupportedCompressions", "MultiMemRead", + "MultiBreakpoint", ] def parse_qSupported_response(self, context): diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 4c77de9f34adc..8dc0656fc9de8 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -198,6 +198,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { &GDBRemoteCommunicationServerLLGS::Handle_Z); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, &GDBRemoteCommunicationServerLLGS::Handle_z); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_MultiBreakpoint, + &GDBRemoteCommunicationServerLLGS::Handle_MultiBreakpoint); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QPassSignals, &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); @@ -3123,6 +3126,61 @@ GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { ExecuteRemoveBreakpoint(packet.GetStringRef())); } +/// Split a MultiBreakpoint packet body into individual breakpoint requests. A +/// ';' starts a new request only if it is followed by [Zz]. +static std::vector<llvm::StringRef> +SplitBreakpointRequests(llvm::StringRef packet) { + std::vector<llvm::StringRef> requests; + size_t request_start = 0; + for (size_t i = 0; i + 1 < packet.size(); ++i) { + if (packet[i] != ';') + continue; + char next_char = packet[i + 1]; + if (next_char == 'Z' || next_char == 'z') { + requests.push_back(packet.substr(request_start, i - request_start)); + request_start = i + 1; + } + } + requests.push_back(packet.substr(request_start)); + return requests; +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_MultiBreakpoint( + StringExtractorGDBRemote &packet) { + llvm::StringRef packet_str = packet.GetStringRef(); + if (!packet_str.consume_front("MultiBreakpoint:")) + return SendIllFormedResponse(packet, + "Invalid MultiBreakpoint packet prefix"); + + if (packet_str.empty()) + return SendIllFormedResponse(packet, "MultiBreakpoint has no requests"); + + StreamString response; + bool first = true; + for (llvm::StringRef request : SplitBreakpointRequests(packet_str)) { + BreakpointResult result = request.starts_with("Z") + ? ExecuteSetBreakpoint(request) + : ExecuteRemoveBreakpoint(request); + if (!first) + response.PutChar(';'); + switch (result.kind) { + case BreakpointResult::Kind::OK: + response.PutCString("OK"); + break; + case BreakpointResult::Kind::Error: + response.Format("E{0:X-2}", result.error_code); + break; + case BreakpointResult::Kind::IllFormed: + response.PutCString("E03"); + break; + } + first = false; + } + + return SendPacketNoLock(response.GetString()); +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); @@ -4338,6 +4396,7 @@ std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures( "QListThreadsInStopReply+", "qXfer:features:read+", "QNonStop+", + "MultiBreakpoint+", }); // report server-only features diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index a663c0b949744..f375f2f7ca24f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -216,6 +216,8 @@ class GDBRemoteCommunicationServerLLGS PacketResult Handle_z(StringExtractorGDBRemote &packet); + PacketResult Handle_MultiBreakpoint(StringExtractorGDBRemote &packet); + PacketResult Handle_s(StringExtractorGDBRemote &packet); PacketResult Handle_qXfer(StringExtractorGDBRemote &packet); diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index 40b5d037d0463..1c89545bf1616 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -431,6 +431,8 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_m; case 'M': + if (PACKET_STARTS_WITH("MultiBreakpoint:")) + return eServerPacketType_MultiBreakpoint; return eServerPacketType_M; case 'p': diff --git a/lldb/test/API/functionalities/multi-breakpoint/TestMultiBreakpoint.py b/lldb/test/API/functionalities/multi-breakpoint/TestMultiBreakpoint.py index 0978a499c7112..e7f87efd0419e 100644 --- a/lldb/test/API/functionalities/multi-breakpoint/TestMultiBreakpoint.py +++ b/lldb/test/API/functionalities/multi-breakpoint/TestMultiBreakpoint.py @@ -9,7 +9,6 @@ from lldbsuite.test import lldbutil -@skipUnlessDarwin # Remove once lldbsever support is implemented. @skipIfOutOfTreeDebugserver class TestMultiBreakpoint(TestBase): def send_packet(self, packet_str): _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
