1 //===-- BreakpointList.cpp ------------------------------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Breakpoint/BreakpointList.h" 10 11 #include "lldb/Target/Target.h" 12 13 #include "llvm/Support/Errc.h" 14 15 using namespace lldb; 16 using namespace lldb_private; 17 18 static void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) { 19 Target &target = bp->GetTarget(); 20 if (target.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) 21 target.BroadcastEvent(Target::eBroadcastBitBreakpointChanged, 22 new Breakpoint::BreakpointEventData(event, bp)); 23 } 24 25 BreakpointList::BreakpointList(bool is_internal) 26 : m_mutex(), m_breakpoints(), m_next_break_id(0), 27 m_is_internal(is_internal) {} 28 29 BreakpointList::~BreakpointList() = default; 30 31 break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) { 32 std::lock_guard<std::recursive_mutex> guard(m_mutex); 33 34 // Internal breakpoint IDs are negative, normal ones are positive 35 bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id); 36 37 m_breakpoints.push_back(bp_sp); 38 39 if (notify) 40 NotifyChange(bp_sp, eBreakpointEventTypeAdded); 41 42 return bp_sp->GetID(); 43 } 44 45 bool BreakpointList::Remove(break_id_t break_id, bool notify) { 46 std::lock_guard<std::recursive_mutex> guard(m_mutex); 47 48 auto it = std::find_if( 49 m_breakpoints.begin(), m_breakpoints.end(), 50 [&](const BreakpointSP &bp) { return bp->GetID() == break_id; }); 51 52 if (it == m_breakpoints.end()) 53 return false; 54 55 if (notify) 56 NotifyChange(*it, eBreakpointEventTypeRemoved); 57 58 m_breakpoints.erase(it); 59 60 return true; 61 } 62 63 void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) { 64 std::lock_guard<std::recursive_mutex> guard(m_mutex); 65 for (const auto &bp_sp : m_breakpoints) 66 bp_sp->RemoveInvalidLocations(arch); 67 } 68 69 void BreakpointList::SetEnabledAll(bool enabled) { 70 std::lock_guard<std::recursive_mutex> guard(m_mutex); 71 for (const auto &bp_sp : m_breakpoints) 72 bp_sp->SetEnabled(enabled); 73 } 74 75 void BreakpointList::SetEnabledAllowed(bool enabled) { 76 std::lock_guard<std::recursive_mutex> guard(m_mutex); 77 for (const auto &bp_sp : m_breakpoints) 78 if (bp_sp->AllowDisable()) 79 bp_sp->SetEnabled(enabled); 80 } 81 82 void BreakpointList::RemoveAll(bool notify) { 83 std::lock_guard<std::recursive_mutex> guard(m_mutex); 84 ClearAllBreakpointSites(); 85 86 if (notify) { 87 for (const auto &bp_sp : m_breakpoints) 88 NotifyChange(bp_sp, eBreakpointEventTypeRemoved); 89 } 90 91 m_breakpoints.clear(); 92 } 93 94 void BreakpointList::RemoveAllowed(bool notify) { 95 std::lock_guard<std::recursive_mutex> guard(m_mutex); 96 97 for (const auto &bp_sp : m_breakpoints) { 98 if (bp_sp->AllowDelete()) 99 bp_sp->ClearAllBreakpointSites(); 100 if (notify) 101 NotifyChange(bp_sp, eBreakpointEventTypeRemoved); 102 } 103 104 llvm::erase_if(m_breakpoints, 105 [&](const BreakpointSP &bp) { return bp->AllowDelete(); }); 106 } 107 108 BreakpointList::bp_collection::iterator 109 BreakpointList::GetBreakpointIDIterator(break_id_t break_id) { 110 return std::find_if( 111 m_breakpoints.begin(), m_breakpoints.end(), 112 [&](const BreakpointSP &bp) { return bp->GetID() == break_id; }); 113 } 114 115 BreakpointList::bp_collection::const_iterator 116 BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const { 117 return std::find_if( 118 m_breakpoints.begin(), m_breakpoints.end(), 119 [&](const BreakpointSP &bp) { return bp->GetID() == break_id; }); 120 } 121 122 BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const { 123 std::lock_guard<std::recursive_mutex> guard(m_mutex); 124 125 auto it = GetBreakpointIDConstIterator(break_id); 126 if (it != m_breakpoints.end()) 127 return *it; 128 return {}; 129 } 130 131 llvm::Expected<std::vector<lldb::BreakpointSP>> 132 BreakpointList::FindBreakpointsByName(const char *name) { 133 if (!name) 134 return llvm::createStringError(llvm::errc::invalid_argument, 135 "FindBreakpointsByName requires a name"); 136 137 Status error; 138 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error)) 139 return error.ToError(); 140 141 std::vector<lldb::BreakpointSP> matching_bps; 142 for (BreakpointSP bkpt_sp : Breakpoints()) { 143 if (bkpt_sp->MatchesName(name)) { 144 matching_bps.push_back(bkpt_sp); 145 } 146 } 147 148 return matching_bps; 149 } 150 151 void BreakpointList::Dump(Stream *s) const { 152 std::lock_guard<std::recursive_mutex> guard(m_mutex); 153 s->Printf("%p: ", static_cast<const void *>(this)); 154 s->Indent(); 155 s->Printf("BreakpointList with %u Breakpoints:\n", 156 (uint32_t)m_breakpoints.size()); 157 s->IndentMore(); 158 for (const auto &bp_sp : m_breakpoints) 159 bp_sp->Dump(s); 160 s->IndentLess(); 161 } 162 163 BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const { 164 std::lock_guard<std::recursive_mutex> guard(m_mutex); 165 if (i < m_breakpoints.size()) 166 return m_breakpoints[i]; 167 return {}; 168 } 169 170 void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added, 171 bool delete_locations) { 172 std::lock_guard<std::recursive_mutex> guard(m_mutex); 173 for (const auto &bp_sp : m_breakpoints) 174 bp_sp->ModulesChanged(module_list, added, delete_locations); 175 } 176 177 void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced( 178 ModuleSP old_module_sp, ModuleSP new_module_sp) { 179 std::lock_guard<std::recursive_mutex> guard(m_mutex); 180 for (const auto &bp_sp : m_breakpoints) 181 bp_sp->ModuleReplaced(old_module_sp, new_module_sp); 182 } 183 184 void BreakpointList::ClearAllBreakpointSites() { 185 std::lock_guard<std::recursive_mutex> guard(m_mutex); 186 for (const auto &bp_sp : m_breakpoints) 187 bp_sp->ClearAllBreakpointSites(); 188 } 189 190 void BreakpointList::GetListMutex( 191 std::unique_lock<std::recursive_mutex> &lock) { 192 lock = std::unique_lock<std::recursive_mutex>(m_mutex); 193 } 194