1 //===-- BreakpointList.cpp --------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Breakpoint/BreakpointList.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Target/Target.h" 17 18 using namespace lldb; 19 using namespace lldb_private; 20 21 BreakpointList::BreakpointList(bool is_internal) 22 : m_mutex(), m_breakpoints(), m_next_break_id(0), 23 m_is_internal(is_internal) {} 24 25 BreakpointList::~BreakpointList() {} 26 27 break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) { 28 std::lock_guard<std::recursive_mutex> guard(m_mutex); 29 // Internal breakpoint IDs are negative, normal ones are positive 30 bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id); 31 32 m_breakpoints.push_back(bp_sp); 33 if (notify) { 34 if (bp_sp->GetTarget().EventTypeHasListeners( 35 Target::eBroadcastBitBreakpointChanged)) 36 bp_sp->GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, 37 new Breakpoint::BreakpointEventData( 38 eBreakpointEventTypeAdded, bp_sp)); 39 } 40 return bp_sp->GetID(); 41 } 42 43 bool BreakpointList::Remove(break_id_t break_id, bool notify) { 44 std::lock_guard<std::recursive_mutex> guard(m_mutex); 45 bp_collection::iterator pos = GetBreakpointIDIterator(break_id); // Predicate 46 if (pos != m_breakpoints.end()) { 47 BreakpointSP bp_sp(*pos); 48 m_breakpoints.erase(pos); 49 if (notify) { 50 if (bp_sp->GetTarget().EventTypeHasListeners( 51 Target::eBroadcastBitBreakpointChanged)) 52 bp_sp->GetTarget().BroadcastEvent( 53 Target::eBroadcastBitBreakpointChanged, 54 new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved, 55 bp_sp)); 56 } 57 return true; 58 } 59 return false; 60 } 61 62 void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) { 63 std::lock_guard<std::recursive_mutex> guard(m_mutex); 64 for (const auto &bp_sp : m_breakpoints) 65 bp_sp->RemoveInvalidLocations(arch); 66 } 67 68 void BreakpointList::SetEnabledAll(bool enabled) { 69 std::lock_guard<std::recursive_mutex> guard(m_mutex); 70 for (const auto &bp_sp : m_breakpoints) 71 bp_sp->SetEnabled(enabled); 72 } 73 74 void BreakpointList::SetEnabledAllowed(bool enabled) { 75 std::lock_guard<std::recursive_mutex> guard(m_mutex); 76 for (const auto &bp_sp : m_breakpoints) 77 if (bp_sp->AllowDisable()) 78 bp_sp->SetEnabled(enabled); 79 } 80 81 void BreakpointList::RemoveAll(bool notify) { 82 std::lock_guard<std::recursive_mutex> guard(m_mutex); 83 ClearAllBreakpointSites(); 84 85 if (notify) { 86 bp_collection::iterator pos, end = m_breakpoints.end(); 87 for (pos = m_breakpoints.begin(); pos != end; ++pos) { 88 if ((*pos)->GetTarget().EventTypeHasListeners( 89 Target::eBroadcastBitBreakpointChanged)) { 90 (*pos)->GetTarget().BroadcastEvent( 91 Target::eBroadcastBitBreakpointChanged, 92 new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved, 93 *pos)); 94 } 95 } 96 } 97 m_breakpoints.erase(m_breakpoints.begin(), m_breakpoints.end()); 98 } 99 100 void BreakpointList::RemoveAllowed(bool notify) { 101 std::lock_guard<std::recursive_mutex> guard(m_mutex); 102 103 bp_collection::iterator pos, end = m_breakpoints.end(); 104 if (notify) { 105 for (pos = m_breakpoints.begin(); pos != end; ++pos) { 106 if(!(*pos)->AllowDelete()) 107 continue; 108 if ((*pos)->GetTarget().EventTypeHasListeners( 109 Target::eBroadcastBitBreakpointChanged)) { 110 (*pos)->GetTarget().BroadcastEvent( 111 Target::eBroadcastBitBreakpointChanged, 112 new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved, 113 *pos)); 114 } 115 } 116 } 117 pos = m_breakpoints.begin(); 118 while ( pos != end) { 119 auto bp = *pos; 120 if (bp->AllowDelete()) { 121 bp->ClearAllBreakpointSites(); 122 pos = m_breakpoints.erase(pos); 123 } else 124 pos++; 125 } 126 } 127 128 class BreakpointIDMatches { 129 public: 130 BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {} 131 132 bool operator()(const BreakpointSP &bp) const { 133 return m_break_id == bp->GetID(); 134 } 135 136 private: 137 const break_id_t m_break_id; 138 }; 139 140 BreakpointList::bp_collection::iterator 141 BreakpointList::GetBreakpointIDIterator(break_id_t break_id) { 142 return std::find_if(m_breakpoints.begin(), 143 m_breakpoints.end(), // Search full range 144 BreakpointIDMatches(break_id)); // Predicate 145 } 146 147 BreakpointList::bp_collection::const_iterator 148 BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const { 149 return std::find_if(m_breakpoints.begin(), 150 m_breakpoints.end(), // Search full range 151 BreakpointIDMatches(break_id)); // Predicate 152 } 153 154 BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) { 155 std::lock_guard<std::recursive_mutex> guard(m_mutex); 156 BreakpointSP stop_sp; 157 bp_collection::iterator pos = GetBreakpointIDIterator(break_id); 158 if (pos != m_breakpoints.end()) 159 stop_sp = *pos; 160 161 return stop_sp; 162 } 163 164 const BreakpointSP 165 BreakpointList::FindBreakpointByID(break_id_t break_id) const { 166 std::lock_guard<std::recursive_mutex> guard(m_mutex); 167 BreakpointSP stop_sp; 168 bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id); 169 if (pos != m_breakpoints.end()) 170 stop_sp = *pos; 171 172 return stop_sp; 173 } 174 175 bool BreakpointList::FindBreakpointsByName(const char *name, 176 BreakpointList &matching_bps) { 177 Status error; 178 if (!name) 179 return false; 180 181 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error)) 182 return false; 183 184 for (BreakpointSP bkpt_sp : Breakpoints()) { 185 if (bkpt_sp->MatchesName(name)) { 186 matching_bps.Add(bkpt_sp, false); 187 } 188 } 189 return true; 190 } 191 192 void BreakpointList::Dump(Stream *s) const { 193 std::lock_guard<std::recursive_mutex> guard(m_mutex); 194 s->Printf("%p: ", static_cast<const void *>(this)); 195 s->Indent(); 196 s->Printf("BreakpointList with %u Breakpoints:\n", 197 (uint32_t)m_breakpoints.size()); 198 s->IndentMore(); 199 for (const auto &bp_sp : m_breakpoints) 200 bp_sp->Dump(s); 201 s->IndentLess(); 202 } 203 204 BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) { 205 std::lock_guard<std::recursive_mutex> guard(m_mutex); 206 BreakpointSP stop_sp; 207 bp_collection::iterator end = m_breakpoints.end(); 208 bp_collection::iterator pos; 209 size_t curr_i = 0; 210 for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) { 211 if (curr_i == i) 212 stop_sp = *pos; 213 } 214 return stop_sp; 215 } 216 217 const BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const { 218 std::lock_guard<std::recursive_mutex> guard(m_mutex); 219 BreakpointSP stop_sp; 220 bp_collection::const_iterator end = m_breakpoints.end(); 221 bp_collection::const_iterator pos; 222 size_t curr_i = 0; 223 for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) { 224 if (curr_i == i) 225 stop_sp = *pos; 226 } 227 return stop_sp; 228 } 229 230 void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added, 231 bool delete_locations) { 232 std::lock_guard<std::recursive_mutex> guard(m_mutex); 233 for (const auto &bp_sp : m_breakpoints) 234 bp_sp->ModulesChanged(module_list, added, delete_locations); 235 } 236 237 void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced( 238 ModuleSP old_module_sp, ModuleSP new_module_sp) { 239 std::lock_guard<std::recursive_mutex> guard(m_mutex); 240 for (const auto &bp_sp : m_breakpoints) 241 bp_sp->ModuleReplaced(old_module_sp, new_module_sp); 242 } 243 244 void BreakpointList::ClearAllBreakpointSites() { 245 std::lock_guard<std::recursive_mutex> guard(m_mutex); 246 for (const auto &bp_sp : m_breakpoints) 247 bp_sp->ClearAllBreakpointSites(); 248 } 249 250 void BreakpointList::GetListMutex( 251 std::unique_lock<std::recursive_mutex> &lock) { 252 lock = std::unique_lock<std::recursive_mutex>(m_mutex); 253 } 254