180814287SRaphael Isemann //===-- BreakpointList.cpp ------------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointList.h"
1030fdc8d8SChris Lattner 
119fed0d85SGreg Clayton #include "lldb/Target/Target.h"
1230fdc8d8SChris Lattner 
1395b2e516SJoseph Tremoulet #include "llvm/Support/Errc.h"
1495b2e516SJoseph Tremoulet 
1530fdc8d8SChris Lattner using namespace lldb;
1630fdc8d8SChris Lattner using namespace lldb_private;
1730fdc8d8SChris Lattner 
NotifyChange(const BreakpointSP & bp,BreakpointEventType event)18dadbb45fSJonas Devlieghere static void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) {
19dadbb45fSJonas Devlieghere   Target &target = bp->GetTarget();
20dadbb45fSJonas Devlieghere   if (target.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
21dadbb45fSJonas Devlieghere     target.BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
22dadbb45fSJonas Devlieghere                           new Breakpoint::BreakpointEventData(event, bp));
23dadbb45fSJonas Devlieghere }
24dadbb45fSJonas Devlieghere 
BreakpointList(bool is_internal)25bb19a13cSSaleem Abdulrasool BreakpointList::BreakpointList(bool is_internal)
26*ee4b6cf5SKazu Hirata     : m_next_break_id(0), m_is_internal(is_internal) {}
2730fdc8d8SChris Lattner 
28fd2433e1SJonas Devlieghere BreakpointList::~BreakpointList() = default;
2930fdc8d8SChris Lattner 
Add(BreakpointSP & bp_sp,bool notify)30b9c1b51eSKate Stone break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
31bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
32dadbb45fSJonas Devlieghere 
3330fdc8d8SChris Lattner   // Internal breakpoint IDs are negative, normal ones are positive
349fed0d85SGreg Clayton   bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);
359fed0d85SGreg Clayton 
369fed0d85SGreg Clayton   m_breakpoints.push_back(bp_sp);
37dadbb45fSJonas Devlieghere 
38dadbb45fSJonas Devlieghere   if (notify)
39dadbb45fSJonas Devlieghere     NotifyChange(bp_sp, eBreakpointEventTypeAdded);
40dadbb45fSJonas Devlieghere 
419fed0d85SGreg Clayton   return bp_sp->GetID();
4230fdc8d8SChris Lattner }
4330fdc8d8SChris Lattner 
Remove(break_id_t break_id,bool notify)44b9c1b51eSKate Stone bool BreakpointList::Remove(break_id_t break_id, bool notify) {
45bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
46dadbb45fSJonas Devlieghere 
47dadbb45fSJonas Devlieghere   auto it = std::find_if(
48dadbb45fSJonas Devlieghere       m_breakpoints.begin(), m_breakpoints.end(),
49dadbb45fSJonas Devlieghere       [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
50dadbb45fSJonas Devlieghere 
51dadbb45fSJonas Devlieghere   if (it == m_breakpoints.end())
5230fdc8d8SChris Lattner     return false;
53dadbb45fSJonas Devlieghere 
54dadbb45fSJonas Devlieghere   if (notify)
55dadbb45fSJonas Devlieghere     NotifyChange(*it, eBreakpointEventTypeRemoved);
56dadbb45fSJonas Devlieghere 
57dadbb45fSJonas Devlieghere   m_breakpoints.erase(it);
58dadbb45fSJonas Devlieghere 
59dadbb45fSJonas Devlieghere   return true;
6030fdc8d8SChris Lattner }
6130fdc8d8SChris Lattner 
RemoveInvalidLocations(const ArchSpec & arch)62b9c1b51eSKate Stone void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {
63bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
64b35db639SGreg Clayton   for (const auto &bp_sp : m_breakpoints)
65b35db639SGreg Clayton     bp_sp->RemoveInvalidLocations(arch);
66b35db639SGreg Clayton }
67b35db639SGreg Clayton 
SetEnabledAll(bool enabled)68b9c1b51eSKate Stone void BreakpointList::SetEnabledAll(bool enabled) {
69bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
70b35db639SGreg Clayton   for (const auto &bp_sp : m_breakpoints)
71b35db639SGreg Clayton     bp_sp->SetEnabled(enabled);
7230fdc8d8SChris Lattner }
7330fdc8d8SChris Lattner 
SetEnabledAllowed(bool enabled)74b842f2ecSJim Ingham void BreakpointList::SetEnabledAllowed(bool enabled) {
75b842f2ecSJim Ingham   std::lock_guard<std::recursive_mutex> guard(m_mutex);
76b842f2ecSJim Ingham   for (const auto &bp_sp : m_breakpoints)
77b842f2ecSJim Ingham     if (bp_sp->AllowDisable())
78b842f2ecSJim Ingham       bp_sp->SetEnabled(enabled);
79b842f2ecSJim Ingham }
80b842f2ecSJim Ingham 
RemoveAll(bool notify)81b9c1b51eSKate Stone void BreakpointList::RemoveAll(bool notify) {
82bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
8330fdc8d8SChris Lattner   ClearAllBreakpointSites();
8430fdc8d8SChris Lattner 
85b9c1b51eSKate Stone   if (notify) {
86dadbb45fSJonas Devlieghere     for (const auto &bp_sp : m_breakpoints)
87dadbb45fSJonas Devlieghere       NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
881b5792e5SJim Ingham   }
89dadbb45fSJonas Devlieghere 
90dadbb45fSJonas Devlieghere   m_breakpoints.clear();
9130fdc8d8SChris Lattner }
9230fdc8d8SChris Lattner 
RemoveAllowed(bool notify)93b842f2ecSJim Ingham void BreakpointList::RemoveAllowed(bool notify) {
94b842f2ecSJim Ingham   std::lock_guard<std::recursive_mutex> guard(m_mutex);
95b842f2ecSJim Ingham 
96dadbb45fSJonas Devlieghere   for (const auto &bp_sp : m_breakpoints) {
97dadbb45fSJonas Devlieghere     if (bp_sp->AllowDelete())
98dadbb45fSJonas Devlieghere       bp_sp->ClearAllBreakpointSites();
99dadbb45fSJonas Devlieghere     if (notify)
100dadbb45fSJonas Devlieghere       NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
101b842f2ecSJim Ingham   }
102b842f2ecSJim Ingham 
1038568ca78SKazu Hirata   llvm::erase_if(m_breakpoints,
1048568ca78SKazu Hirata                  [&](const BreakpointSP &bp) { return bp->AllowDelete(); });
10530fdc8d8SChris Lattner }
10630fdc8d8SChris Lattner 
10730fdc8d8SChris Lattner BreakpointList::bp_collection::iterator
GetBreakpointIDIterator(break_id_t break_id)108b9c1b51eSKate Stone BreakpointList::GetBreakpointIDIterator(break_id_t break_id) {
109dadbb45fSJonas Devlieghere   return std::find_if(
110dadbb45fSJonas Devlieghere       m_breakpoints.begin(), m_breakpoints.end(),
111dadbb45fSJonas Devlieghere       [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
11230fdc8d8SChris Lattner }
11330fdc8d8SChris Lattner 
11430fdc8d8SChris Lattner BreakpointList::bp_collection::const_iterator
GetBreakpointIDConstIterator(break_id_t break_id) const115b9c1b51eSKate Stone BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {
116dadbb45fSJonas Devlieghere   return std::find_if(
117dadbb45fSJonas Devlieghere       m_breakpoints.begin(), m_breakpoints.end(),
118dadbb45fSJonas Devlieghere       [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
11930fdc8d8SChris Lattner }
12030fdc8d8SChris Lattner 
FindBreakpointByID(break_id_t break_id) const121dadbb45fSJonas Devlieghere BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const {
122bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
12330fdc8d8SChris Lattner 
124dadbb45fSJonas Devlieghere   auto it = GetBreakpointIDConstIterator(break_id);
125dadbb45fSJonas Devlieghere   if (it != m_breakpoints.end())
126dadbb45fSJonas Devlieghere     return *it;
127dadbb45fSJonas Devlieghere   return {};
12830fdc8d8SChris Lattner }
12930fdc8d8SChris Lattner 
13095b2e516SJoseph Tremoulet llvm::Expected<std::vector<lldb::BreakpointSP>>
FindBreakpointsByName(const char * name)13195b2e516SJoseph Tremoulet BreakpointList::FindBreakpointsByName(const char *name) {
132ff9a91eaSJim Ingham   if (!name)
13395b2e516SJoseph Tremoulet     return llvm::createStringError(llvm::errc::invalid_argument,
13495b2e516SJoseph Tremoulet                                    "FindBreakpointsByName requires a name");
135ff9a91eaSJim Ingham 
13695b2e516SJoseph Tremoulet   Status error;
137ff9a91eaSJim Ingham   if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))
13895b2e516SJoseph Tremoulet     return error.ToError();
139ff9a91eaSJim Ingham 
14095b2e516SJoseph Tremoulet   std::vector<lldb::BreakpointSP> matching_bps;
141ff9a91eaSJim Ingham   for (BreakpointSP bkpt_sp : Breakpoints()) {
142ff9a91eaSJim Ingham     if (bkpt_sp->MatchesName(name)) {
14395b2e516SJoseph Tremoulet       matching_bps.push_back(bkpt_sp);
144ff9a91eaSJim Ingham     }
145ff9a91eaSJim Ingham   }
146dadbb45fSJonas Devlieghere 
14795b2e516SJoseph Tremoulet   return matching_bps;
148ff9a91eaSJim Ingham }
149ff9a91eaSJim Ingham 
Dump(Stream * s) const150b9c1b51eSKate Stone void BreakpointList::Dump(Stream *s) const {
151bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
152324a1036SSaleem Abdulrasool   s->Printf("%p: ", static_cast<const void *>(this));
15330fdc8d8SChris Lattner   s->Indent();
154b9c1b51eSKate Stone   s->Printf("BreakpointList with %u Breakpoints:\n",
155b9c1b51eSKate Stone             (uint32_t)m_breakpoints.size());
15630fdc8d8SChris Lattner   s->IndentMore();
157b35db639SGreg Clayton   for (const auto &bp_sp : m_breakpoints)
158b35db639SGreg Clayton     bp_sp->Dump(s);
15930fdc8d8SChris Lattner   s->IndentLess();
16030fdc8d8SChris Lattner }
16130fdc8d8SChris Lattner 
GetBreakpointAtIndex(size_t i) const162dadbb45fSJonas Devlieghere BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
163bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
164dadbb45fSJonas Devlieghere   if (i < m_breakpoints.size())
165dadbb45fSJonas Devlieghere     return m_breakpoints[i];
166dadbb45fSJonas Devlieghere   return {};
16730fdc8d8SChris Lattner }
16830fdc8d8SChris Lattner 
UpdateBreakpoints(ModuleList & module_list,bool added,bool delete_locations)169b9c1b51eSKate Stone void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,
170b9c1b51eSKate Stone                                        bool delete_locations) {
171bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
172b35db639SGreg Clayton   for (const auto &bp_sp : m_breakpoints)
173b35db639SGreg Clayton     bp_sp->ModulesChanged(module_list, added, delete_locations);
17430fdc8d8SChris Lattner }
17530fdc8d8SChris Lattner 
UpdateBreakpointsWhenModuleIsReplaced(ModuleSP old_module_sp,ModuleSP new_module_sp)176b9c1b51eSKate Stone void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(
177b9c1b51eSKate Stone     ModuleSP old_module_sp, ModuleSP new_module_sp) {
178bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
179b35db639SGreg Clayton   for (const auto &bp_sp : m_breakpoints)
180b35db639SGreg Clayton     bp_sp->ModuleReplaced(old_module_sp, new_module_sp);
1814a94c910SJim Ingham }
1824a94c910SJim Ingham 
ClearAllBreakpointSites()183b9c1b51eSKate Stone void BreakpointList::ClearAllBreakpointSites() {
184bb19a13cSSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_mutex);
185b35db639SGreg Clayton   for (const auto &bp_sp : m_breakpoints)
186b35db639SGreg Clayton     bp_sp->ClearAllBreakpointSites();
18730fdc8d8SChris Lattner }
1881b54c88cSJim Ingham 
GetListMutex(std::unique_lock<std::recursive_mutex> & lock)189b9c1b51eSKate Stone void BreakpointList::GetListMutex(
190b9c1b51eSKate Stone     std::unique_lock<std::recursive_mutex> &lock) {
191bb19a13cSSaleem Abdulrasool   lock = std::unique_lock<std::recursive_mutex>(m_mutex);
1921b54c88cSJim Ingham }
193