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::RemoveAll(bool notify) { 75 std::lock_guard<std::recursive_mutex> guard(m_mutex); 76 ClearAllBreakpointSites(); 77 78 if (notify) { 79 bp_collection::iterator pos, end = m_breakpoints.end(); 80 for (pos = m_breakpoints.begin(); pos != end; ++pos) { 81 if ((*pos)->GetTarget().EventTypeHasListeners( 82 Target::eBroadcastBitBreakpointChanged)) { 83 (*pos)->GetTarget().BroadcastEvent( 84 Target::eBroadcastBitBreakpointChanged, 85 new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved, 86 *pos)); 87 } 88 } 89 } 90 m_breakpoints.erase(m_breakpoints.begin(), m_breakpoints.end()); 91 } 92 93 class BreakpointIDMatches { 94 public: 95 BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {} 96 97 bool operator()(const BreakpointSP &bp) const { 98 return m_break_id == bp->GetID(); 99 } 100 101 private: 102 const break_id_t m_break_id; 103 }; 104 105 BreakpointList::bp_collection::iterator 106 BreakpointList::GetBreakpointIDIterator(break_id_t break_id) { 107 return std::find_if(m_breakpoints.begin(), 108 m_breakpoints.end(), // Search full range 109 BreakpointIDMatches(break_id)); // Predicate 110 } 111 112 BreakpointList::bp_collection::const_iterator 113 BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const { 114 return std::find_if(m_breakpoints.begin(), 115 m_breakpoints.end(), // Search full range 116 BreakpointIDMatches(break_id)); // Predicate 117 } 118 119 BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) { 120 std::lock_guard<std::recursive_mutex> guard(m_mutex); 121 BreakpointSP stop_sp; 122 bp_collection::iterator pos = GetBreakpointIDIterator(break_id); 123 if (pos != m_breakpoints.end()) 124 stop_sp = *pos; 125 126 return stop_sp; 127 } 128 129 const BreakpointSP 130 BreakpointList::FindBreakpointByID(break_id_t break_id) const { 131 std::lock_guard<std::recursive_mutex> guard(m_mutex); 132 BreakpointSP stop_sp; 133 bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id); 134 if (pos != m_breakpoints.end()) 135 stop_sp = *pos; 136 137 return stop_sp; 138 } 139 140 bool BreakpointList::FindBreakpointsByName(const char *name, 141 BreakpointList &matching_bps) { 142 Error error; 143 if (!name) 144 return false; 145 146 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error)) 147 return false; 148 149 for (BreakpointSP bkpt_sp : Breakpoints()) { 150 if (bkpt_sp->MatchesName(name)) { 151 matching_bps.Add(bkpt_sp, false); 152 } 153 } 154 return true; 155 } 156 157 void BreakpointList::Dump(Stream *s) const { 158 std::lock_guard<std::recursive_mutex> guard(m_mutex); 159 s->Printf("%p: ", static_cast<const void *>(this)); 160 s->Indent(); 161 s->Printf("BreakpointList with %u Breakpoints:\n", 162 (uint32_t)m_breakpoints.size()); 163 s->IndentMore(); 164 for (const auto &bp_sp : m_breakpoints) 165 bp_sp->Dump(s); 166 s->IndentLess(); 167 } 168 169 BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) { 170 std::lock_guard<std::recursive_mutex> guard(m_mutex); 171 BreakpointSP stop_sp; 172 bp_collection::iterator end = m_breakpoints.end(); 173 bp_collection::iterator pos; 174 size_t curr_i = 0; 175 for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) { 176 if (curr_i == i) 177 stop_sp = *pos; 178 } 179 return stop_sp; 180 } 181 182 const BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const { 183 std::lock_guard<std::recursive_mutex> guard(m_mutex); 184 BreakpointSP stop_sp; 185 bp_collection::const_iterator end = m_breakpoints.end(); 186 bp_collection::const_iterator pos; 187 size_t curr_i = 0; 188 for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) { 189 if (curr_i == i) 190 stop_sp = *pos; 191 } 192 return stop_sp; 193 } 194 195 void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added, 196 bool delete_locations) { 197 std::lock_guard<std::recursive_mutex> guard(m_mutex); 198 for (const auto &bp_sp : m_breakpoints) 199 bp_sp->ModulesChanged(module_list, added, delete_locations); 200 } 201 202 void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced( 203 ModuleSP old_module_sp, ModuleSP new_module_sp) { 204 std::lock_guard<std::recursive_mutex> guard(m_mutex); 205 for (const auto &bp_sp : m_breakpoints) 206 bp_sp->ModuleReplaced(old_module_sp, new_module_sp); 207 } 208 209 void BreakpointList::ClearAllBreakpointSites() { 210 std::lock_guard<std::recursive_mutex> guard(m_mutex); 211 for (const auto &bp_sp : m_breakpoints) 212 bp_sp->ClearAllBreakpointSites(); 213 } 214 215 void BreakpointList::GetListMutex( 216 std::unique_lock<std::recursive_mutex> &lock) { 217 lock = std::unique_lock<std::recursive_mutex>(m_mutex); 218 } 219