xref: /openbsd-src/gnu/llvm/lldb/source/Breakpoint/BreakpointList.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- BreakpointList.cpp ------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Breakpoint/BreakpointList.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Target/Target.h"
12061da546Spatrick 
13061da546Spatrick #include "llvm/Support/Errc.h"
14061da546Spatrick 
15061da546Spatrick using namespace lldb;
16061da546Spatrick using namespace lldb_private;
17061da546Spatrick 
NotifyChange(const BreakpointSP & bp,BreakpointEventType event)18061da546Spatrick static void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) {
19061da546Spatrick   Target &target = bp->GetTarget();
20061da546Spatrick   if (target.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
21061da546Spatrick     target.BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
22061da546Spatrick                           new Breakpoint::BreakpointEventData(event, bp));
23061da546Spatrick }
24061da546Spatrick 
BreakpointList(bool is_internal)25061da546Spatrick BreakpointList::BreakpointList(bool is_internal)
26*f6aab3d8Srobert     : m_next_break_id(0), m_is_internal(is_internal) {}
27061da546Spatrick 
28be691f3bSpatrick BreakpointList::~BreakpointList() = default;
29061da546Spatrick 
Add(BreakpointSP & bp_sp,bool notify)30061da546Spatrick break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
31061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
32061da546Spatrick 
33061da546Spatrick   // Internal breakpoint IDs are negative, normal ones are positive
34061da546Spatrick   bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);
35061da546Spatrick 
36061da546Spatrick   m_breakpoints.push_back(bp_sp);
37061da546Spatrick 
38061da546Spatrick   if (notify)
39061da546Spatrick     NotifyChange(bp_sp, eBreakpointEventTypeAdded);
40061da546Spatrick 
41061da546Spatrick   return bp_sp->GetID();
42061da546Spatrick }
43061da546Spatrick 
Remove(break_id_t break_id,bool notify)44061da546Spatrick bool BreakpointList::Remove(break_id_t break_id, bool notify) {
45061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
46061da546Spatrick 
47061da546Spatrick   auto it = std::find_if(
48061da546Spatrick       m_breakpoints.begin(), m_breakpoints.end(),
49061da546Spatrick       [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
50061da546Spatrick 
51061da546Spatrick   if (it == m_breakpoints.end())
52061da546Spatrick     return false;
53061da546Spatrick 
54061da546Spatrick   if (notify)
55061da546Spatrick     NotifyChange(*it, eBreakpointEventTypeRemoved);
56061da546Spatrick 
57061da546Spatrick   m_breakpoints.erase(it);
58061da546Spatrick 
59061da546Spatrick   return true;
60061da546Spatrick }
61061da546Spatrick 
RemoveInvalidLocations(const ArchSpec & arch)62061da546Spatrick void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {
63061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
64061da546Spatrick   for (const auto &bp_sp : m_breakpoints)
65061da546Spatrick     bp_sp->RemoveInvalidLocations(arch);
66061da546Spatrick }
67061da546Spatrick 
SetEnabledAll(bool enabled)68061da546Spatrick void BreakpointList::SetEnabledAll(bool enabled) {
69061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
70061da546Spatrick   for (const auto &bp_sp : m_breakpoints)
71061da546Spatrick     bp_sp->SetEnabled(enabled);
72061da546Spatrick }
73061da546Spatrick 
SetEnabledAllowed(bool enabled)74061da546Spatrick void BreakpointList::SetEnabledAllowed(bool enabled) {
75061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
76061da546Spatrick   for (const auto &bp_sp : m_breakpoints)
77061da546Spatrick     if (bp_sp->AllowDisable())
78061da546Spatrick       bp_sp->SetEnabled(enabled);
79061da546Spatrick }
80061da546Spatrick 
RemoveAll(bool notify)81061da546Spatrick void BreakpointList::RemoveAll(bool notify) {
82061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
83061da546Spatrick   ClearAllBreakpointSites();
84061da546Spatrick 
85061da546Spatrick   if (notify) {
86061da546Spatrick     for (const auto &bp_sp : m_breakpoints)
87061da546Spatrick       NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
88061da546Spatrick   }
89061da546Spatrick 
90061da546Spatrick   m_breakpoints.clear();
91061da546Spatrick }
92061da546Spatrick 
RemoveAllowed(bool notify)93061da546Spatrick void BreakpointList::RemoveAllowed(bool notify) {
94061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
95061da546Spatrick 
96061da546Spatrick   for (const auto &bp_sp : m_breakpoints) {
97061da546Spatrick     if (bp_sp->AllowDelete())
98061da546Spatrick       bp_sp->ClearAllBreakpointSites();
99061da546Spatrick     if (notify)
100061da546Spatrick       NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
101061da546Spatrick   }
102061da546Spatrick 
103*f6aab3d8Srobert   llvm::erase_if(m_breakpoints,
104*f6aab3d8Srobert                  [&](const BreakpointSP &bp) { return bp->AllowDelete(); });
105061da546Spatrick }
106061da546Spatrick 
107061da546Spatrick BreakpointList::bp_collection::iterator
GetBreakpointIDIterator(break_id_t break_id)108061da546Spatrick BreakpointList::GetBreakpointIDIterator(break_id_t break_id) {
109061da546Spatrick   return std::find_if(
110061da546Spatrick       m_breakpoints.begin(), m_breakpoints.end(),
111061da546Spatrick       [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
112061da546Spatrick }
113061da546Spatrick 
114061da546Spatrick BreakpointList::bp_collection::const_iterator
GetBreakpointIDConstIterator(break_id_t break_id) const115061da546Spatrick BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {
116061da546Spatrick   return std::find_if(
117061da546Spatrick       m_breakpoints.begin(), m_breakpoints.end(),
118061da546Spatrick       [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
119061da546Spatrick }
120061da546Spatrick 
FindBreakpointByID(break_id_t break_id) const121061da546Spatrick BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const {
122061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
123061da546Spatrick 
124061da546Spatrick   auto it = GetBreakpointIDConstIterator(break_id);
125061da546Spatrick   if (it != m_breakpoints.end())
126061da546Spatrick     return *it;
127061da546Spatrick   return {};
128061da546Spatrick }
129061da546Spatrick 
130061da546Spatrick llvm::Expected<std::vector<lldb::BreakpointSP>>
FindBreakpointsByName(const char * name)131061da546Spatrick BreakpointList::FindBreakpointsByName(const char *name) {
132061da546Spatrick   if (!name)
133061da546Spatrick     return llvm::createStringError(llvm::errc::invalid_argument,
134061da546Spatrick                                    "FindBreakpointsByName requires a name");
135061da546Spatrick 
136061da546Spatrick   Status error;
137061da546Spatrick   if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))
138061da546Spatrick     return error.ToError();
139061da546Spatrick 
140061da546Spatrick   std::vector<lldb::BreakpointSP> matching_bps;
141061da546Spatrick   for (BreakpointSP bkpt_sp : Breakpoints()) {
142061da546Spatrick     if (bkpt_sp->MatchesName(name)) {
143061da546Spatrick       matching_bps.push_back(bkpt_sp);
144061da546Spatrick     }
145061da546Spatrick   }
146061da546Spatrick 
147061da546Spatrick   return matching_bps;
148061da546Spatrick }
149061da546Spatrick 
Dump(Stream * s) const150061da546Spatrick void BreakpointList::Dump(Stream *s) const {
151061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
152061da546Spatrick   s->Printf("%p: ", static_cast<const void *>(this));
153061da546Spatrick   s->Indent();
154061da546Spatrick   s->Printf("BreakpointList with %u Breakpoints:\n",
155061da546Spatrick             (uint32_t)m_breakpoints.size());
156061da546Spatrick   s->IndentMore();
157061da546Spatrick   for (const auto &bp_sp : m_breakpoints)
158061da546Spatrick     bp_sp->Dump(s);
159061da546Spatrick   s->IndentLess();
160061da546Spatrick }
161061da546Spatrick 
GetBreakpointAtIndex(size_t i) const162061da546Spatrick BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
163061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
164061da546Spatrick   if (i < m_breakpoints.size())
165061da546Spatrick     return m_breakpoints[i];
166061da546Spatrick   return {};
167061da546Spatrick }
168061da546Spatrick 
UpdateBreakpoints(ModuleList & module_list,bool added,bool delete_locations)169061da546Spatrick void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,
170061da546Spatrick                                        bool delete_locations) {
171061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
172061da546Spatrick   for (const auto &bp_sp : m_breakpoints)
173061da546Spatrick     bp_sp->ModulesChanged(module_list, added, delete_locations);
174061da546Spatrick }
175061da546Spatrick 
UpdateBreakpointsWhenModuleIsReplaced(ModuleSP old_module_sp,ModuleSP new_module_sp)176061da546Spatrick void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(
177061da546Spatrick     ModuleSP old_module_sp, ModuleSP new_module_sp) {
178061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
179061da546Spatrick   for (const auto &bp_sp : m_breakpoints)
180061da546Spatrick     bp_sp->ModuleReplaced(old_module_sp, new_module_sp);
181061da546Spatrick }
182061da546Spatrick 
ClearAllBreakpointSites()183061da546Spatrick void BreakpointList::ClearAllBreakpointSites() {
184061da546Spatrick   std::lock_guard<std::recursive_mutex> guard(m_mutex);
185061da546Spatrick   for (const auto &bp_sp : m_breakpoints)
186061da546Spatrick     bp_sp->ClearAllBreakpointSites();
187061da546Spatrick }
188061da546Spatrick 
ResetHitCounts()189*f6aab3d8Srobert void BreakpointList::ResetHitCounts() {
190*f6aab3d8Srobert   std::lock_guard<std::recursive_mutex> guard(m_mutex);
191*f6aab3d8Srobert   for (const auto &bp_sp : m_breakpoints)
192*f6aab3d8Srobert     bp_sp->ResetHitCount();
193*f6aab3d8Srobert }
194*f6aab3d8Srobert 
GetListMutex(std::unique_lock<std::recursive_mutex> & lock)195061da546Spatrick void BreakpointList::GetListMutex(
196061da546Spatrick     std::unique_lock<std::recursive_mutex> &lock) {
197061da546Spatrick   lock = std::unique_lock<std::recursive_mutex>(m_mutex);
198061da546Spatrick }
199