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 if((*pos)->AllowDelete()) 120 pos = m_breakpoints.erase(pos); 121 else 122 pos++; 123 } 124 } 125 126 class BreakpointIDMatches { 127 public: 128 BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {} 129 130 bool operator()(const BreakpointSP &bp) const { 131 return m_break_id == bp->GetID(); 132 } 133 134 private: 135 const break_id_t m_break_id; 136 }; 137 138 BreakpointList::bp_collection::iterator 139 BreakpointList::GetBreakpointIDIterator(break_id_t break_id) { 140 return std::find_if(m_breakpoints.begin(), 141 m_breakpoints.end(), // Search full range 142 BreakpointIDMatches(break_id)); // Predicate 143 } 144 145 BreakpointList::bp_collection::const_iterator 146 BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const { 147 return std::find_if(m_breakpoints.begin(), 148 m_breakpoints.end(), // Search full range 149 BreakpointIDMatches(break_id)); // Predicate 150 } 151 152 BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) { 153 std::lock_guard<std::recursive_mutex> guard(m_mutex); 154 BreakpointSP stop_sp; 155 bp_collection::iterator pos = GetBreakpointIDIterator(break_id); 156 if (pos != m_breakpoints.end()) 157 stop_sp = *pos; 158 159 return stop_sp; 160 } 161 162 const BreakpointSP 163 BreakpointList::FindBreakpointByID(break_id_t break_id) const { 164 std::lock_guard<std::recursive_mutex> guard(m_mutex); 165 BreakpointSP stop_sp; 166 bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id); 167 if (pos != m_breakpoints.end()) 168 stop_sp = *pos; 169 170 return stop_sp; 171 } 172 173 bool BreakpointList::FindBreakpointsByName(const char *name, 174 BreakpointList &matching_bps) { 175 Status error; 176 if (!name) 177 return false; 178 179 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error)) 180 return false; 181 182 for (BreakpointSP bkpt_sp : Breakpoints()) { 183 if (bkpt_sp->MatchesName(name)) { 184 matching_bps.Add(bkpt_sp, false); 185 } 186 } 187 return true; 188 } 189 190 void BreakpointList::Dump(Stream *s) const { 191 std::lock_guard<std::recursive_mutex> guard(m_mutex); 192 s->Printf("%p: ", static_cast<const void *>(this)); 193 s->Indent(); 194 s->Printf("BreakpointList with %u Breakpoints:\n", 195 (uint32_t)m_breakpoints.size()); 196 s->IndentMore(); 197 for (const auto &bp_sp : m_breakpoints) 198 bp_sp->Dump(s); 199 s->IndentLess(); 200 } 201 202 BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) { 203 std::lock_guard<std::recursive_mutex> guard(m_mutex); 204 BreakpointSP stop_sp; 205 bp_collection::iterator end = m_breakpoints.end(); 206 bp_collection::iterator pos; 207 size_t curr_i = 0; 208 for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) { 209 if (curr_i == i) 210 stop_sp = *pos; 211 } 212 return stop_sp; 213 } 214 215 const BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const { 216 std::lock_guard<std::recursive_mutex> guard(m_mutex); 217 BreakpointSP stop_sp; 218 bp_collection::const_iterator end = m_breakpoints.end(); 219 bp_collection::const_iterator pos; 220 size_t curr_i = 0; 221 for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) { 222 if (curr_i == i) 223 stop_sp = *pos; 224 } 225 return stop_sp; 226 } 227 228 void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added, 229 bool delete_locations) { 230 std::lock_guard<std::recursive_mutex> guard(m_mutex); 231 for (const auto &bp_sp : m_breakpoints) 232 bp_sp->ModulesChanged(module_list, added, delete_locations); 233 } 234 235 void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced( 236 ModuleSP old_module_sp, ModuleSP new_module_sp) { 237 std::lock_guard<std::recursive_mutex> guard(m_mutex); 238 for (const auto &bp_sp : m_breakpoints) 239 bp_sp->ModuleReplaced(old_module_sp, new_module_sp); 240 } 241 242 void BreakpointList::ClearAllBreakpointSites() { 243 std::lock_guard<std::recursive_mutex> guard(m_mutex); 244 for (const auto &bp_sp : m_breakpoints) 245 bp_sp->ClearAllBreakpointSites(); 246 } 247 248 void BreakpointList::GetListMutex( 249 std::unique_lock<std::recursive_mutex> &lock) { 250 lock = std::unique_lock<std::recursive_mutex>(m_mutex); 251 } 252