[lldbremote] Implement support for MultiBreakpoint packet#192919
Conversation
|
@llvm/pr-subscribers-lldb Author: Felipe de Azevedo Piovezan (felipepiovezan) ChangesThis is fairly straightfoward, thanks to the helper functions created in the previous commit. Full diff: https://github.com/llvm/llvm-project/pull/192919.diff 6 Files Affected:
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):
|
🐧 Linux x64 Test Results
✅ The build succeeded and all tests passed. |
6bf0eda to
8265e86
Compare
|
Linux bots aren't too happy with the tests, will investigate. |
8427d0c to
8c83175
Compare
8265e86 to
a490b93
Compare
8c83175 to
62420e3
Compare
a490b93 to
7fe5090
Compare
62420e3 to
c3b8061
Compare
7fe5090 to
9070524
Compare
c3b8061 to
7d292a5
Compare
9070524 to
a47c0ae
Compare
7d292a5 to
86cf048
Compare
3561fc7 to
ca11aac
Compare
|
This keeps timing out ever since I made the response also be a dictionary... |
ca11aac to
738715a
Compare
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
DavidSpickett
left a comment
There was a problem hiding this comment.
LGTM
And I do clearly see where we would easily be able to refactor this to support other packets of the same design pattern if that ever happens.
This describes the packet discussed in the RFC: https://discourse.llvm.org/t/rfc-a-new-packet-to-set-remove-multiple-breakpoints/90623 The following PRs are related: * [[lldb] Propose MultiBreakpoint extension to GDB Remote](#192910) * [[debugserver] Implement MultiBreakpoint](#192914) * [[lldb-server][NFC] Factor out code handling breakpoint packets](#192915) * [[lldb-server] Implement support for MultiBreakpoint packet](#192919) * [[lldb][GDBRemote] Parse MultiBreakpoint+ capability](#192962) * [[lldb][NFC] Move BreakpointSite::IsEnabled/SetEnabled into Process](#192964) * [[lldb] Implement delayed breakpoints](#192971) * [[lldb] Override UpdateBreakpointSites in ProcessGDBRemote to use MultiBreakpoint](#192988)
This implements the packet as described in llvm/llvm-project#192910 The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
…ets (#192915) This commit extracts the code handling breakpoint packets into a helper function that can be used by a future implementation of the MultiBreakpointPacket. It is meant to be purely NFC. There are two functions handling breakpoint packets (`handle_Z` and `handle_z`) with a lot of repeated code. This commit did not attempt to merge the two, as that would make the diff much larger due to subtle differences in the error message produced by the two. The only deduplication done is in the code processing a GDBStoppointType, where a helper struct (`BreakpointKind`) and function (`std::optional<BreakpointKind> getBreakpointKind(GDBStoppointType stoppoint_type)`) was created. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
…(#192919) This is fairly straightforward, thanks to the helper functions created in the previous commit. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
…(#192919) This is fairly straightforward, thanks to the helper functions created in the previous commit. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
The Process class is the one responsible for managing the state of a BreakpointSite inside the process. As such, it should be the one answering questions about the state of the site. Future patches will make this even more important by introducing a "logical" is enabled, by delaying the moment in which breakpoints are actually updated in the process. The following PRs are related to the MultiBreakpoint feature: * #192910 * #192914 * #192915 * #192919 * #192962 * #192964 * #192971 * #192988 #192910
…(#192919) This is fairly straightforward, thanks to the helper functions created in the previous commit. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
| @skipUnlessDarwin # Remove once lldbsever support is implemented. | ||
| @skipIfOutOfTreeDebugserver | ||
| # Runs on systems where we can always predict the software break size | ||
| @skipIf(archs=no_match(["x86_64", "arm64", "aarch64"])) |
There was a problem hiding this comment.
We need a skipIfWindows too because we debug in process on Windows. - https://lab.llvm.org/buildbot/#/builders/141/builds/17796
There was a problem hiding this comment.
The buildbot lldb-x86_64-win is broken too
https://lab.llvm.org/buildbot/#/builders/211/builds/7814
There was a problem hiding this comment.
Ah, let me fix that now. Thank you for flagging this
This describes the packet discussed in the RFC: https://discourse.llvm.org/t/rfc-a-new-packet-to-set-remove-multiple-breakpoints/90623 The following PRs are related: * [[lldb] Propose MultiBreakpoint extension to GDB Remote](llvm#192910) * [[debugserver] Implement MultiBreakpoint](llvm#192914) * [[lldb-server][NFC] Factor out code handling breakpoint packets](llvm#192915) * [[lldb-server] Implement support for MultiBreakpoint packet](llvm#192919) * [[lldb][GDBRemote] Parse MultiBreakpoint+ capability](llvm#192962) * [[lldb][NFC] Move BreakpointSite::IsEnabled/SetEnabled into Process](llvm#192964) * [[lldb] Implement delayed breakpoints](llvm#192971) * [[lldb] Override UpdateBreakpointSites in ProcessGDBRemote to use MultiBreakpoint](llvm#192988)
This implements the packet as described in llvm#192910 The following PRs are related to the MultiBreakpoint feature: * llvm#192910 * llvm#192914 * llvm#192915 * llvm#192919 * llvm#192962 * llvm#192964 * llvm#192971 * llvm#192988
…92915) This commit extracts the code handling breakpoint packets into a helper function that can be used by a future implementation of the MultiBreakpointPacket. It is meant to be purely NFC. There are two functions handling breakpoint packets (`handle_Z` and `handle_z`) with a lot of repeated code. This commit did not attempt to merge the two, as that would make the diff much larger due to subtle differences in the error message produced by the two. The only deduplication done is in the code processing a GDBStoppointType, where a helper struct (`BreakpointKind`) and function (`std::optional<BreakpointKind> getBreakpointKind(GDBStoppointType stoppoint_type)`) was created. The following PRs are related to the MultiBreakpoint feature: * llvm#192910 * llvm#192914 * llvm#192915 * llvm#192919 * llvm#192962 * llvm#192964 * llvm#192971 * llvm#192988
This is fairly straightforward, thanks to the helper functions created in the previous commit. The following PRs are related to the MultiBreakpoint feature: * llvm#192910 * llvm#192914 * llvm#192915 * llvm#192919 * llvm#192962 * llvm#192964 * llvm#192971 * llvm#192988
The Process class is the one responsible for managing the state of a BreakpointSite inside the process. As such, it should be the one answering questions about the state of the site. Future patches will make this even more important by introducing a "logical" is enabled, by delaying the moment in which breakpoints are actually updated in the process. The following PRs are related to the MultiBreakpoint feature: * #192910 * #192914 * #192915 * #192919 * #192962 * #192964 * #192971 * #192988 #192910
The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
…192964) The Process class is the one responsible for managing the state of a BreakpointSite inside the process. As such, it should be the one answering questions about the state of the site. Future patches will make this even more important by introducing a "logical" is enabled, by delaying the moment in which breakpoints are actually updated in the process. The following PRs are related to the MultiBreakpoint feature: * #192910 * #192914 * #192915 * #192919 * #192962 * #192964 * #192971 * #192988
… Process (#192964) The Process class is the one responsible for managing the state of a BreakpointSite inside the process. As such, it should be the one answering questions about the state of the site. Future patches will make this even more important by introducing a "logical" is enabled, by delaying the moment in which breakpoints are actually updated in the process. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
… Process (#192964) The Process class is the one responsible for managing the state of a BreakpointSite inside the process. As such, it should be the one answering questions about the state of the site. Future patches will make this even more important by introducing a "logical" is enabled, by delaying the moment in which breakpoints are actually updated in the process. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
The following PRs are related to the MultiBreakpoint feature: * llvm#192910 * llvm#192914 * llvm#192915 * llvm#192919 * llvm#192962 * llvm#192964 * llvm#192971 * llvm#192988
… Process (#192964) The Process class is the one responsible for managing the state of a BreakpointSite inside the process. As such, it should be the one answering questions about the state of the site. Future patches will make this even more important by introducing a "logical" is enabled, by delaying the moment in which breakpoints are actually updated in the process. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
This describes the packet discussed in the RFC: https://discourse.llvm.org/t/rfc-a-new-packet-to-set-remove-multiple-breakpoints/90623 The following PRs are related: * [[lldb] Propose MultiBreakpoint extension to GDB Remote](llvm#192910) * [[debugserver] Implement MultiBreakpoint](llvm#192914) * [[lldb-server][NFC] Factor out code handling breakpoint packets](llvm#192915) * [[lldb-server] Implement support for MultiBreakpoint packet](llvm#192919) * [[lldb][GDBRemote] Parse MultiBreakpoint+ capability](llvm#192962) * [[lldb][NFC] Move BreakpointSite::IsEnabled/SetEnabled into Process](llvm#192964) * [[lldb] Implement delayed breakpoints](llvm#192971) * [[lldb] Override UpdateBreakpointSites in ProcessGDBRemote to use MultiBreakpoint](llvm#192988)
This implements the packet as described in llvm#192910 The following PRs are related to the MultiBreakpoint feature: * llvm#192910 * llvm#192914 * llvm#192915 * llvm#192919 * llvm#192962 * llvm#192964 * llvm#192971 * llvm#192988
…92915) This commit extracts the code handling breakpoint packets into a helper function that can be used by a future implementation of the MultiBreakpointPacket. It is meant to be purely NFC. There are two functions handling breakpoint packets (`handle_Z` and `handle_z`) with a lot of repeated code. This commit did not attempt to merge the two, as that would make the diff much larger due to subtle differences in the error message produced by the two. The only deduplication done is in the code processing a GDBStoppointType, where a helper struct (`BreakpointKind`) and function (`std::optional<BreakpointKind> getBreakpointKind(GDBStoppointType stoppoint_type)`) was created. The following PRs are related to the MultiBreakpoint feature: * llvm#192910 * llvm#192914 * llvm#192915 * llvm#192919 * llvm#192962 * llvm#192964 * llvm#192971 * llvm#192988
This is fairly straightforward, thanks to the helper functions created in the previous commit. The following PRs are related to the MultiBreakpoint feature: * llvm#192910 * llvm#192914 * llvm#192915 * llvm#192919 * llvm#192962 * llvm#192964 * llvm#192971 * llvm#192988
This patch changes the Process class so that it delays *physically* enabling/disabling breakpoints until the process is about to resume/detach/be destroyed, potentially reducing the packets transmitted by batching all breakpoints together. Most classes only need to know whether a breakpoint is "logically" enabled, as opposed to "physically" enabled (i.e. the remote server has actually enabled the breakpoint). However, lower level classes like derived Process classes, or StopInfo may actually need to know whether the breakpoint was physically enabled. As such, this commit also adds a "IsPhysicallyEnabled" API. The following PRs are related to the MultiBreakpoint feature: * #192910 * #192914 * #192915 * #192919 * #192962 * #192964 * #192971 * #192988
This patch changes the Process class so that it delays *physically* enabling/disabling breakpoints until the process is about to resume/detach/be destroyed, potentially reducing the packets transmitted by batching all breakpoints together. Most classes only need to know whether a breakpoint is "logically" enabled, as opposed to "physically" enabled (i.e. the remote server has actually enabled the breakpoint). However, lower level classes like derived Process classes, or StopInfo may actually need to know whether the breakpoint was physically enabled. As such, this commit also adds a "IsPhysicallyEnabled" API. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
This patch changes the Process class so that it delays *physically* enabling/disabling breakpoints until the process is about to resume/detach/be destroyed, potentially reducing the packets transmitted by batching all breakpoints together. Most classes only need to know whether a breakpoint is "logically" enabled, as opposed to "physically" enabled (i.e. the remote server has actually enabled the breakpoint). However, lower level classes like derived Process classes, or StopInfo may actually need to know whether the breakpoint was physically enabled. As such, this commit also adds a "IsPhysicallyEnabled" API. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
This patch changes the Process class so that it delays *physically* enabling/disabling breakpoints until the process is about to resume/detach/be destroyed, potentially reducing the packets transmitted by batching all breakpoints together. Most classes only need to know whether a breakpoint is "logically" enabled, as opposed to "physically" enabled (i.e. the remote server has actually enabled the breakpoint). However, lower level classes like derived Process classes, or StopInfo may actually need to know whether the breakpoint was physically enabled. As such, this commit also adds a "IsPhysicallyEnabled" API. The following PRs are related to the MultiBreakpoint feature: * llvm/llvm-project#192910 * llvm/llvm-project#192914 * llvm/llvm-project#192915 * llvm/llvm-project#192919 * llvm/llvm-project#192962 * llvm/llvm-project#192964 * llvm/llvm-project#192971 * llvm/llvm-project#192988
This is fairly straightforward, thanks to the helper functions created in the previous commit.
The following PRs are related to the MultiBreakpoint feature: