[llvm-branch-commits] [lldb] [lldb] Override UpdateBreakpointSites in ProcessGDBRemote to use MultiBreakpoint (PR #192988)
Jonas Devlieghere via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Apr 28 10:50:28 PDT 2026
================
@@ -6392,3 +6392,194 @@ void ProcessGDBRemote::DidExec() {
}
Process::DidExec();
}
+
+llvm::Error ProcessGDBRemote::UpdateBreakpointSitesNotBatched(
+ const BreakpointSiteToActionMap &site_to_action) {
+ llvm::Error joined = llvm::Error::success();
+ for (auto &[site, action] : site_to_action) {
+ llvm::Error error = action == Process::BreakpointAction::Enable
+ ? DoEnableBreakpointSite(*site)
+ : DoDisableBreakpointSite(*site);
+ joined = llvm::joinErrors(std::move(joined), std::move(error));
+ }
+ return joined;
+}
+
+static llvm::Expected<StringExtractorGDBRemote>
+SendMultiBreakpointPacket(GDBRemoteCommunicationClient &gdb_comm,
+ llvm::StringRef packet_str,
+ std::chrono::seconds interrupt_timeout) {
+ StringExtractorGDBRemote response;
+ GDBRemoteCommunication::PacketResult packet_result =
+ gdb_comm.SendPacketAndWaitForResponse(packet_str, response,
+ interrupt_timeout);
+ if (packet_result != GDBRemoteCommunication::PacketResult::Success)
+ return llvm::createStringErrorV(
+ "MultiBreakpoint failed to send packet: '{0}'", packet_str);
+
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringErrorV(
+ "MultiBreakpoint unsupported response: '{0}'", response.GetStringRef());
+
+ return response;
+}
+
+/// Parse a MultiBreakpoint response into per-request results.
+/// Returns a vector of results: std::nullopt means OK, a uint8_t value is the
+/// error code from an Exx response.
+static llvm::SmallVector<std::optional<uint8_t>>
+ParseMultiBreakpointResponse(llvm::StringRef response_str) {
+ llvm::SmallVector<std::optional<uint8_t>> results;
+
+ StructuredData::ObjectSP parsed = StructuredData::ParseJSON(response_str);
+ StructuredData::Dictionary *dict =
+ parsed ? parsed->GetAsDictionary() : nullptr;
+ StructuredData::Array *array = nullptr;
+ if (dict)
+ dict->GetValueForKeyAsArray("results", array);
+ if (!array)
+ return results;
+
+ array->ForEach([&results](StructuredData::Object *object) -> bool {
+ llvm::StringRef token;
+ if (auto *string = object->GetAsString())
+ token = string->GetValue();
+ if (token == "OK") {
+ results.push_back(std::nullopt);
+ return true;
+ }
+ if (token.size() != 3 || !token.starts_with("E")) {
+ results.push_back(uint8_t(0xff));
+ return true;
+ }
+ uint8_t error_code = 0;
+ if (token.drop_front(1).getAsInteger(16, error_code))
+ results.push_back(0xff);
+ else
+ results.push_back(error_code);
+ return true;
+ });
+ return results;
+}
+
+/// Determine the GDB stoppoint type for a breakpoint site by checking which
+/// packet types the remote supports (for insertions), or by checking the site
+/// type (for deletions).
+static std::optional<GDBStoppointType>
+GetStoppointType(BreakpointSite &site, bool insert,
+ GDBRemoteCommunicationClient &gdb_comm) {
+ if (insert) {
+ if (!site.HardwareRequired() &&
+ gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
+ return eBreakpointSoftware;
+ if (gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
+ return eBreakpointHardware;
+ return std::nullopt;
+ }
+
+ switch (site.GetType()) {
+ case BreakpointSite::eExternal:
+ return eBreakpointSoftware;
+ case BreakpointSite::eHardware:
+ return eBreakpointHardware;
+ case BreakpointSite::eSoftware:
+ return std::nullopt;
----------------
JDevlieghere wrote:
This means that if you have one `eSoftware` site in the batch causes ALL sites to fall back to individual packets. I assume that's uncommon enough that it doesn't undermine the optimization? How hard would it be to filter out the software ones and still batch up the Z packets?
https://github.com/llvm/llvm-project/pull/192988
More information about the llvm-branch-commits
mailing list