1 //===-- BreakpointList.cpp --------------------------------------*- C++ -*-===//
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"
14 using namespace lldb_private;
16 static void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) {
17 Target &target = bp->GetTarget();
18 if (target.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
19 target.BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
20 new Breakpoint::BreakpointEventData(event, bp));
23 BreakpointList::BreakpointList(bool is_internal)
24 : m_mutex(), m_breakpoints(), m_next_break_id(0),
25 m_is_internal(is_internal) {}
27 BreakpointList::~BreakpointList() {}
29 break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
30 std::lock_guard<std::recursive_mutex> guard(m_mutex);
32 // Internal breakpoint IDs are negative, normal ones are positive
33 bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);
35 m_breakpoints.push_back(bp_sp);
38 NotifyChange(bp_sp, eBreakpointEventTypeAdded);
40 return bp_sp->GetID();
43 bool BreakpointList::Remove(break_id_t break_id, bool notify) {
44 std::lock_guard<std::recursive_mutex> guard(m_mutex);
46 auto it = std::find_if(
47 m_breakpoints.begin(), m_breakpoints.end(),
48 [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
50 if (it == m_breakpoints.end())
54 NotifyChange(*it, eBreakpointEventTypeRemoved);
56 m_breakpoints.erase(it);
61 void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {
62 std::lock_guard<std::recursive_mutex> guard(m_mutex);
63 for (const auto &bp_sp : m_breakpoints)
64 bp_sp->RemoveInvalidLocations(arch);
67 void BreakpointList::SetEnabledAll(bool enabled) {
68 std::lock_guard<std::recursive_mutex> guard(m_mutex);
69 for (const auto &bp_sp : m_breakpoints)
70 bp_sp->SetEnabled(enabled);
73 void BreakpointList::SetEnabledAllowed(bool enabled) {
74 std::lock_guard<std::recursive_mutex> guard(m_mutex);
75 for (const auto &bp_sp : m_breakpoints)
76 if (bp_sp->AllowDisable())
77 bp_sp->SetEnabled(enabled);
80 void BreakpointList::RemoveAll(bool notify) {
81 std::lock_guard<std::recursive_mutex> guard(m_mutex);
82 ClearAllBreakpointSites();
85 for (const auto &bp_sp : m_breakpoints)
86 NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
89 m_breakpoints.clear();
92 void BreakpointList::RemoveAllowed(bool notify) {
93 std::lock_guard<std::recursive_mutex> guard(m_mutex);
95 for (const auto &bp_sp : m_breakpoints) {
96 if (bp_sp->AllowDelete())
97 bp_sp->ClearAllBreakpointSites();
99 NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
103 std::remove_if(m_breakpoints.begin(), m_breakpoints.end(),
104 [&](const BreakpointSP &bp) { return bp->AllowDelete(); }),
105 m_breakpoints.end());
108 BreakpointList::bp_collection::iterator
109 BreakpointList::GetBreakpointIDIterator(break_id_t break_id) {
111 m_breakpoints.begin(), m_breakpoints.end(),
112 [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
115 BreakpointList::bp_collection::const_iterator
116 BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {
118 m_breakpoints.begin(), m_breakpoints.end(),
119 [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
122 BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const {
123 std::lock_guard<std::recursive_mutex> guard(m_mutex);
125 auto it = GetBreakpointIDConstIterator(break_id);
126 if (it != m_breakpoints.end())
131 bool BreakpointList::FindBreakpointsByName(const char *name,
132 BreakpointList &matching_bps) {
137 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))
140 for (BreakpointSP bkpt_sp : Breakpoints()) {
141 if (bkpt_sp->MatchesName(name)) {
142 matching_bps.Add(bkpt_sp, false);
149 void BreakpointList::Dump(Stream *s) const {
150 std::lock_guard<std::recursive_mutex> guard(m_mutex);
151 s->Printf("%p: ", static_cast<const void *>(this));
153 s->Printf("BreakpointList with %u Breakpoints:\n",
154 (uint32_t)m_breakpoints.size());
156 for (const auto &bp_sp : m_breakpoints)
161 BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
162 std::lock_guard<std::recursive_mutex> guard(m_mutex);
163 if (i < m_breakpoints.size())
164 return m_breakpoints[i];
168 void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,
169 bool delete_locations) {
170 std::lock_guard<std::recursive_mutex> guard(m_mutex);
171 for (const auto &bp_sp : m_breakpoints)
172 bp_sp->ModulesChanged(module_list, added, delete_locations);
175 void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(
176 ModuleSP old_module_sp, ModuleSP new_module_sp) {
177 std::lock_guard<std::recursive_mutex> guard(m_mutex);
178 for (const auto &bp_sp : m_breakpoints)
179 bp_sp->ModuleReplaced(old_module_sp, new_module_sp);
182 void BreakpointList::ClearAllBreakpointSites() {
183 std::lock_guard<std::recursive_mutex> guard(m_mutex);
184 for (const auto &bp_sp : m_breakpoints)
185 bp_sp->ClearAllBreakpointSites();
188 void BreakpointList::GetListMutex(
189 std::unique_lock<std::recursive_mutex> &lock) {
190 lock = std::unique_lock<std::recursive_mutex>(m_mutex);