1 //===-- BreakpointList.cpp ------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Breakpoint/BreakpointList.h"
11 #include "lldb/Target/Target.h"
13 #include "llvm/Support/Errc.h"
16 using namespace lldb_private
;
18 static void NotifyChange(const BreakpointSP
&bp
, BreakpointEventType event
) {
19 Target
&target
= bp
->GetTarget();
20 if (target
.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged
)) {
22 std::make_shared
<Breakpoint::BreakpointEventData
>(event
, bp
);
23 target
.BroadcastEvent(Target::eBroadcastBitBreakpointChanged
,
28 BreakpointList::BreakpointList(bool is_internal
)
29 : m_next_break_id(0), m_is_internal(is_internal
) {}
31 BreakpointList::~BreakpointList() = default;
33 break_id_t
BreakpointList::Add(BreakpointSP
&bp_sp
, bool notify
) {
34 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
36 // Internal breakpoint IDs are negative, normal ones are positive
37 bp_sp
->SetID(m_is_internal
? --m_next_break_id
: ++m_next_break_id
);
39 m_breakpoints
.push_back(bp_sp
);
42 NotifyChange(bp_sp
, eBreakpointEventTypeAdded
);
44 return bp_sp
->GetID();
47 bool BreakpointList::Remove(break_id_t break_id
, bool notify
) {
48 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
50 auto it
= std::find_if(
51 m_breakpoints
.begin(), m_breakpoints
.end(),
52 [&](const BreakpointSP
&bp
) { return bp
->GetID() == break_id
; });
54 if (it
== m_breakpoints
.end())
58 NotifyChange(*it
, eBreakpointEventTypeRemoved
);
60 m_breakpoints
.erase(it
);
65 void BreakpointList::RemoveInvalidLocations(const ArchSpec
&arch
) {
66 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
67 for (const auto &bp_sp
: m_breakpoints
)
68 bp_sp
->RemoveInvalidLocations(arch
);
71 void BreakpointList::SetEnabledAll(bool enabled
) {
72 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
73 for (const auto &bp_sp
: m_breakpoints
)
74 bp_sp
->SetEnabled(enabled
);
77 void BreakpointList::SetEnabledAllowed(bool enabled
) {
78 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
79 for (const auto &bp_sp
: m_breakpoints
)
80 if (bp_sp
->AllowDisable())
81 bp_sp
->SetEnabled(enabled
);
84 void BreakpointList::RemoveAll(bool notify
) {
85 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
86 ClearAllBreakpointSites();
89 for (const auto &bp_sp
: m_breakpoints
)
90 NotifyChange(bp_sp
, eBreakpointEventTypeRemoved
);
93 m_breakpoints
.clear();
96 void BreakpointList::RemoveAllowed(bool notify
) {
97 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
99 for (const auto &bp_sp
: m_breakpoints
) {
100 if (bp_sp
->AllowDelete())
101 bp_sp
->ClearAllBreakpointSites();
103 NotifyChange(bp_sp
, eBreakpointEventTypeRemoved
);
106 llvm::erase_if(m_breakpoints
,
107 [&](const BreakpointSP
&bp
) { return bp
->AllowDelete(); });
110 BreakpointList::bp_collection::iterator
111 BreakpointList::GetBreakpointIDIterator(break_id_t break_id
) {
113 m_breakpoints
.begin(), m_breakpoints
.end(),
114 [&](const BreakpointSP
&bp
) { return bp
->GetID() == break_id
; });
117 BreakpointList::bp_collection::const_iterator
118 BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id
) const {
120 m_breakpoints
.begin(), m_breakpoints
.end(),
121 [&](const BreakpointSP
&bp
) { return bp
->GetID() == break_id
; });
124 BreakpointSP
BreakpointList::FindBreakpointByID(break_id_t break_id
) const {
125 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
127 auto it
= GetBreakpointIDConstIterator(break_id
);
128 if (it
!= m_breakpoints
.end())
133 llvm::Expected
<std::vector
<lldb::BreakpointSP
>>
134 BreakpointList::FindBreakpointsByName(const char *name
) {
136 return llvm::createStringError(llvm::errc::invalid_argument
,
137 "FindBreakpointsByName requires a name");
140 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name
), error
))
141 return error
.ToError();
143 std::vector
<lldb::BreakpointSP
> matching_bps
;
144 for (BreakpointSP bkpt_sp
: Breakpoints()) {
145 if (bkpt_sp
->MatchesName(name
)) {
146 matching_bps
.push_back(bkpt_sp
);
153 void BreakpointList::Dump(Stream
*s
) const {
154 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
155 s
->Printf("%p: ", static_cast<const void *>(this));
157 s
->Printf("BreakpointList with %u Breakpoints:\n",
158 (uint32_t)m_breakpoints
.size());
160 for (const auto &bp_sp
: m_breakpoints
)
165 BreakpointSP
BreakpointList::GetBreakpointAtIndex(size_t i
) const {
166 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
167 if (i
< m_breakpoints
.size())
168 return m_breakpoints
[i
];
172 void BreakpointList::UpdateBreakpoints(ModuleList
&module_list
, bool added
,
173 bool delete_locations
) {
174 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
175 for (const auto &bp_sp
: m_breakpoints
)
176 bp_sp
->ModulesChanged(module_list
, added
, delete_locations
);
179 void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(
180 ModuleSP old_module_sp
, ModuleSP new_module_sp
) {
181 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
182 for (const auto &bp_sp
: m_breakpoints
)
183 bp_sp
->ModuleReplaced(old_module_sp
, new_module_sp
);
186 void BreakpointList::ClearAllBreakpointSites() {
187 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
188 for (const auto &bp_sp
: m_breakpoints
)
189 bp_sp
->ClearAllBreakpointSites();
192 void BreakpointList::ResetHitCounts() {
193 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
194 for (const auto &bp_sp
: m_breakpoints
)
195 bp_sp
->ResetHitCount();
198 void BreakpointList::GetListMutex(
199 std::unique_lock
<std::recursive_mutex
> &lock
) {
200 lock
= std::unique_lock
<std::recursive_mutex
>(m_mutex
);