[llvm-branch-commits] [lldb] [lldb] Override UpdateBreakpointSites in ProcessGDBRemote to use MultiBreakpoint (PR #192988)
Felipe de Azevedo Piovezan via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Apr 29 07:00:54 PDT 2026
https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/192988
>From 2178444d2f8da6fc3498da1bd916d82616510859 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 9 Apr 2026 15:07:40 +0100
Subject: [PATCH 1/4] [lldb] Override UpdateBreakpointSites in ProcessGDBRemote
to use MultiBreakpoint
This concludes the implementation of MultiBreakpoint by actually using
the new packet to batch breakpoint requests.
https://github.com/llvm/llvm-project/pull/192910
---
lldb/include/lldb/Utility/GDBRemote.h | 3 +
.../Process/gdb-remote/ProcessGDBRemote.cpp | 192 ++++++++++++++++++
.../Process/gdb-remote/ProcessGDBRemote.h | 8 +
lldb/source/Utility/GDBRemote.cpp | 4 +
4 files changed, 207 insertions(+)
diff --git a/lldb/include/lldb/Utility/GDBRemote.h b/lldb/include/lldb/Utility/GDBRemote.h
index 3b839c5d79485..ab33f02ebb012 100644
--- a/lldb/include/lldb/Utility/GDBRemote.h
+++ b/lldb/include/lldb/Utility/GDBRemote.h
@@ -42,6 +42,9 @@ class StreamGDBRemote : public StreamString {
/// Number of bytes written.
// TODO: Convert this function to take ArrayRef<uint8_t>
int PutEscapedBytes(const void *s, size_t src_len);
+
+ /// Equivalent to PutEscapedBytes(str.data(), str.size());
+ int PutEscapedBytes(llvm::StringRef str);
};
/// GDB remote packet as used by the GDB remote communication history. Packets
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index adf108919b36e..3641deae8c463 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -6392,3 +6392,195 @@ void ProcessGDBRemote::DidExec() {
}
Process::DidExec();
}
+
+llvm::Error ProcessGDBRemote::UpdateBreakpointSitesNotBatched(
+ const std::map<lldb::BreakpointSiteSP, Process::BreakpointAction>
+ &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;
+ }
+ llvm_unreachable("unhandled BreakpointSite type");
+}
+
+namespace {
+struct BreakpointPacketInfo {
+ BreakpointSite &site;
+ size_t trap_opcode_size;
+ GDBStoppointType type;
+ bool is_enable;
+};
+
+std::string to_string(const BreakpointPacketInfo &info) {
+ char packet = info.is_enable ? 'Z' : 'z';
+ return llvm::formatv("{0}{1},{2:x-},{3:x-}", packet,
+ static_cast<int>(info.type), info.site.GetLoadAddress(),
+ info.trap_opcode_size)
+ .str();
+}
+} // namespace
+
+llvm::Error ProcessGDBRemote::UpdateBreakpointSites(
+ const std::map<lldb::BreakpointSiteSP, BreakpointAction> &site_to_action) {
+ if (site_to_action.empty())
+ return llvm::Error::success();
+ if (!m_gdb_comm.GetMultiBreakpointSupported())
+ return UpdateBreakpointSitesNotBatched(site_to_action);
+
+ Log *log = GetLog(GDBRLog::Breakpoints);
+
+ std::vector<BreakpointPacketInfo> breakpoint_infos;
+
+ for (auto [site, action] : site_to_action) {
+ addr_t addr = site->GetLoadAddress();
+ size_t trap_opcode_size = GetSoftwareBreakpointTrapOpcode(site.get());
+ std::optional<GDBStoppointType> type =
+ GetStoppointType(*site, action == BreakpointAction::Enable, m_gdb_comm);
+ if (!type) {
+ LLDB_LOG(log, "MultiBreakpoint: site {0} at {1:x} can't be batched",
+ site->GetID(), addr);
+ return UpdateBreakpointSitesNotBatched(site_to_action);
+ }
+ breakpoint_infos.push_back(
+ {*site, trap_opcode_size, *type, action == BreakpointAction::Enable});
+ }
+
+ StreamString stream;
+ stream << "jMultiBreakpoint:";
+
+ auto args_array = std::make_shared<StructuredData::Array>();
+ for (auto &bp_info : breakpoint_infos)
+ args_array->AddStringItem(to_string(bp_info));
+
+ StructuredData::Dictionary packet_dict;
+ packet_dict.AddItem("breakpoint_requests", args_array);
+ packet_dict.Dump(stream, false);
+
+ StreamGDBRemote escaped_stream;
+ escaped_stream.PutEscapedBytes(stream.GetString());
+ llvm::Expected<StringExtractorGDBRemote> response = SendMultiBreakpointPacket(
+ m_gdb_comm, escaped_stream.GetString(), GetInterruptTimeout());
+
+ if (!response) {
+ LLDB_LOG_ERROR(log, response.takeError(), "jMultiBreakpoint failed: {0}");
+ return UpdateBreakpointSitesNotBatched(site_to_action);
+ }
+
+ llvm::SmallVector<std::optional<uint8_t>> results =
+ ParseMultiBreakpointResponse(response->GetStringRef());
+
+ // This is a protocol violation, do nothing.
+ if (results.size() != site_to_action.size())
+ return llvm::createStringErrorV(
+ "MultiBreakpoint response count mismatch (expected {0}, got {1})",
+ site_to_action.size(), results.size());
+
+ // Process results: mark successful sites as enabled/disabled, retry failed
+ // sites individually.
+ llvm::Error joined = llvm::Error::success();
+ for (auto [error_code, bp_info] : llvm::zip(results, breakpoint_infos)) {
+ BreakpointSite &site = bp_info.site;
+ if (error_code == std::nullopt) {
+ SetBreakpointSiteEnabled(site, bp_info.is_enable);
+ if (bp_info.is_enable)
+ site.SetType(bp_info.type == eBreakpointHardware
+ ? BreakpointSite::eHardware
+ : BreakpointSite::eExternal);
+ continue;
+ }
+ LLDB_LOG(log,
+ "MultiBreakpoint: site {0} at {1:x} failed (E{2:X-2}), retrying",
+ site.GetID(), site.GetLoadAddress(), *error_code);
+ llvm::Error error = bp_info.is_enable ? DoEnableBreakpointSite(site)
+ : DoDisableBreakpointSite(site);
+ joined = llvm::joinErrors(std::move(joined), std::move(error));
+ }
+
+ return joined;
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 7c2877fa71d49..fa59655fe8a89 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -170,6 +170,10 @@ class ProcessGDBRemote : public Process,
// Process Breakpoints
Status EnableBreakpointSite(BreakpointSite *bp_site) override;
+ llvm::Error UpdateBreakpointSites(
+ const std::map<lldb::BreakpointSiteSP, BreakpointAction> &site_to_action)
+ override;
+
Status DisableBreakpointSite(BreakpointSite *bp_site) override;
// Process Watchpoints
@@ -462,6 +466,10 @@ class ProcessGDBRemote : public Process,
/// z packet or restoring the original instruction.
llvm::Error DoDisableBreakpointSite(BreakpointSite &bp_site);
+ llvm::Error UpdateBreakpointSitesNotBatched(
+ const std::map<lldb::BreakpointSiteSP, Process::BreakpointAction>
+ &site_to_action);
+
static bool NewThreadNotifyBreakpointHit(void *baton,
StoppointCallbackContext *context,
lldb::user_id_t break_id,
diff --git a/lldb/source/Utility/GDBRemote.cpp b/lldb/source/Utility/GDBRemote.cpp
index f987ebcd4f63e..bd322a5e9e540 100644
--- a/lldb/source/Utility/GDBRemote.cpp
+++ b/lldb/source/Utility/GDBRemote.cpp
@@ -24,6 +24,10 @@ StreamGDBRemote::StreamGDBRemote(uint32_t flags, ByteOrder byte_order)
StreamGDBRemote::~StreamGDBRemote() = default;
+int StreamGDBRemote::PutEscapedBytes(llvm::StringRef str) {
+ return PutEscapedBytes(str.data(), str.size());
+}
+
int StreamGDBRemote::PutEscapedBytes(const void *s, size_t src_len) {
int bytes_written = 0;
const uint8_t *src = static_cast<const uint8_t *>(s);
>From 525e554483803791f340a14dc4f1572a51f3151e Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Tue, 28 Apr 2026 08:41:09 +0100
Subject: [PATCH 2/4] fixup! use map typedef
---
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 5 ++---
lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h | 6 ++----
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 3641deae8c463..b02d37e602733 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -6394,8 +6394,7 @@ void ProcessGDBRemote::DidExec() {
}
llvm::Error ProcessGDBRemote::UpdateBreakpointSitesNotBatched(
- const std::map<lldb::BreakpointSiteSP, Process::BreakpointAction>
- &site_to_action) {
+ 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
@@ -6507,7 +6506,7 @@ std::string to_string(const BreakpointPacketInfo &info) {
} // namespace
llvm::Error ProcessGDBRemote::UpdateBreakpointSites(
- const std::map<lldb::BreakpointSiteSP, BreakpointAction> &site_to_action) {
+ const BreakpointSiteToActionMap &site_to_action) {
if (site_to_action.empty())
return llvm::Error::success();
if (!m_gdb_comm.GetMultiBreakpointSupported())
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index fa59655fe8a89..63215f3e612c8 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -171,8 +171,7 @@ class ProcessGDBRemote : public Process,
Status EnableBreakpointSite(BreakpointSite *bp_site) override;
llvm::Error UpdateBreakpointSites(
- const std::map<lldb::BreakpointSiteSP, BreakpointAction> &site_to_action)
- override;
+ const BreakpointSiteToActionMap &site_to_action) override;
Status DisableBreakpointSite(BreakpointSite *bp_site) override;
@@ -467,8 +466,7 @@ class ProcessGDBRemote : public Process,
llvm::Error DoDisableBreakpointSite(BreakpointSite &bp_site);
llvm::Error UpdateBreakpointSitesNotBatched(
- const std::map<lldb::BreakpointSiteSP, Process::BreakpointAction>
- &site_to_action);
+ const BreakpointSiteToActionMap &site_to_action);
static bool NewThreadNotifyBreakpointHit(void *baton,
StoppointCallbackContext *context,
>From da0706f624124aa1a71b3a0fde3ce6ee1407d7e9 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Wed, 29 Apr 2026 14:00:01 +0100
Subject: [PATCH 3/4] fixup! make helper method to send packet
---
.../gdb-remote/GDBRemoteClientBase.cpp | 17 +++++++++++++
.../Process/gdb-remote/GDBRemoteClientBase.h | 5 ++++
.../Process/gdb-remote/ProcessGDBRemote.cpp | 24 +++----------------
3 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
index 406fa06ea011a..46c5d62f551e2 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -9,6 +9,7 @@
#include "GDBRemoteClientBase.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorExtras.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -194,6 +195,22 @@ GDBRemoteClientBase::SendPacketAndWaitForResponse(
return SendPacketAndWaitForResponseNoLock(payload, response, sync_on_timeout);
}
+llvm::Expected<StringExtractorGDBRemote>
+GDBRemoteClientBase::SendPacketAndExpectResponse(
+ llvm::StringRef payload, std::chrono::seconds interrupt_timeout) {
+ StringExtractorGDBRemote response;
+ GDBRemoteCommunication::PacketResult packet_result =
+ SendPacketAndWaitForResponse(payload, response, interrupt_timeout);
+ if (packet_result != GDBRemoteCommunication::PacketResult::Success)
+ return llvm::createStringErrorV("Failed to send packet: '{0}'", payload);
+
+ if (response.IsUnsupportedResponse())
+ return llvm::createStringErrorV("Unsupported response: '{0}'",
+ response.GetStringRef());
+
+ return std::move(response);
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteClientBase::ReadPacketWithOutputSupport(
StringExtractorGDBRemote &response, Timeout<std::micro> timeout,
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
index 9c17a8c1de057..83d252bbc0649 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
@@ -74,6 +74,11 @@ class GDBRemoteClientBase : public GDBRemoteCommunication, public Broadcaster {
std::chrono::seconds interrupt_timeout,
llvm::function_ref<void(llvm::StringRef)> output_callback);
+ /// Wrapper around SendPacketAndWaitForResponse that returns and `Expected`.
+ llvm::Expected<StringExtractorGDBRemote> SendPacketAndExpectResponse(
+ llvm::StringRef payload,
+ std::chrono::seconds interrupt_timeout = std::chrono::seconds(0));
+
class Lock {
public:
// If interrupt_timeout == 0 seconds, only take the lock if the target is
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index b02d37e602733..c110e0ad21b20 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -6405,25 +6405,6 @@ llvm::Error ProcessGDBRemote::UpdateBreakpointSitesNotBatched(
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.
@@ -6543,8 +6524,9 @@ llvm::Error ProcessGDBRemote::UpdateBreakpointSites(
StreamGDBRemote escaped_stream;
escaped_stream.PutEscapedBytes(stream.GetString());
- llvm::Expected<StringExtractorGDBRemote> response = SendMultiBreakpointPacket(
- m_gdb_comm, escaped_stream.GetString(), GetInterruptTimeout());
+ llvm::Expected<StringExtractorGDBRemote> response =
+ m_gdb_comm.SendPacketAndExpectResponse(escaped_stream.GetString(),
+ GetInterruptTimeout());
if (!response) {
LLDB_LOG_ERROR(log, response.takeError(), "jMultiBreakpoint failed: {0}");
>From 450064a090b0363957242bc1e54e70194b0b8ac3 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Wed, 29 Apr 2026 15:00:25 +0100
Subject: [PATCH 4/4] fixup! don't fallback on all packets
---
.../Process/gdb-remote/ProcessGDBRemote.cpp | 32 ++++++++++++-------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index c110e0ad21b20..0670e56c8445b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -6493,22 +6493,19 @@ llvm::Error ProcessGDBRemote::UpdateBreakpointSites(
if (!m_gdb_comm.GetMultiBreakpointSupported())
return UpdateBreakpointSitesNotBatched(site_to_action);
- Log *log = GetLog(GDBRLog::Breakpoints);
-
std::vector<BreakpointPacketInfo> breakpoint_infos;
+ std::vector<std::pair<BreakpointSiteSP, BreakpointAction>>
+ non_batchable_sites;
for (auto [site, action] : site_to_action) {
- addr_t addr = site->GetLoadAddress();
size_t trap_opcode_size = GetSoftwareBreakpointTrapOpcode(site.get());
std::optional<GDBStoppointType> type =
GetStoppointType(*site, action == BreakpointAction::Enable, m_gdb_comm);
- if (!type) {
- LLDB_LOG(log, "MultiBreakpoint: site {0} at {1:x} can't be batched",
- site->GetID(), addr);
- return UpdateBreakpointSitesNotBatched(site_to_action);
- }
- breakpoint_infos.push_back(
- {*site, trap_opcode_size, *type, action == BreakpointAction::Enable});
+ if (type)
+ breakpoint_infos.push_back(
+ {*site, trap_opcode_size, *type, action == BreakpointAction::Enable});
+ else
+ non_batchable_sites.emplace_back(site, action);
}
StreamString stream;
@@ -6528,6 +6525,8 @@ llvm::Error ProcessGDBRemote::UpdateBreakpointSites(
m_gdb_comm.SendPacketAndExpectResponse(escaped_stream.GetString(),
GetInterruptTimeout());
+ Log *log = GetLog(GDBRLog::Breakpoints);
+
if (!response) {
LLDB_LOG_ERROR(log, response.takeError(), "jMultiBreakpoint failed: {0}");
return UpdateBreakpointSitesNotBatched(site_to_action);
@@ -6542,9 +6541,20 @@ llvm::Error ProcessGDBRemote::UpdateBreakpointSites(
"MultiBreakpoint response count mismatch (expected {0}, got {1})",
site_to_action.size(), results.size());
+ llvm::Error joined = llvm::Error::success();
+ for (auto [site, action] : non_batchable_sites) {
+ LLDB_LOG(log,
+ "MultiBreakpoint: site {0} at {1:x} can't be batched, trying on "
+ "its own",
+ site->GetID(), site->GetLoadAddress());
+ llvm::Error error = action == BreakpointAction::Enable
+ ? DoEnableBreakpointSite(*site)
+ : DoDisableBreakpointSite(*site);
+ joined = llvm::joinErrors(std::move(joined), std::move(error));
+ }
+
// Process results: mark successful sites as enabled/disabled, retry failed
// sites individually.
- llvm::Error joined = llvm::Error::success();
for (auto [error_code, bp_info] : llvm::zip(results, breakpoint_infos)) {
BreakpointSite &site = bp_info.site;
if (error_code == std::nullopt) {
More information about the llvm-branch-commits
mailing list