1 //===-- BreakpointLocationList.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 11 // C Includes 12 // C++ Includes 13 // Other libraries and framework includes 14 // Project includes 15 #include "lldb/Breakpoint/BreakpointLocationList.h" 16 #include "lldb/Breakpoint/BreakpointLocation.h" 17 #include "lldb/Core/ModuleList.h" 18 #include "lldb/Target/Target.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 BreakpointLocationList::BreakpointLocationList() : 24 m_locations(), 25 m_address_to_location (), 26 m_mutex (Mutex::eMutexTypeRecursive), 27 m_next_id (0) 28 { 29 } 30 31 BreakpointLocationList::~BreakpointLocationList() 32 { 33 } 34 35 lldb::break_id_t 36 BreakpointLocationList::Add (BreakpointLocationSP &bp_loc_sp) 37 { 38 if (bp_loc_sp) 39 { 40 Mutex::Locker locker (m_mutex); 41 m_locations.push_back (bp_loc_sp); 42 m_address_to_location[bp_loc_sp->GetAddress()] = bp_loc_sp; 43 return bp_loc_sp->GetID(); 44 } 45 return LLDB_INVALID_BREAK_ID; 46 } 47 48 bool 49 BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id) 50 { 51 BreakpointLocationSP bp = FindByID (break_id); 52 if (bp) 53 { 54 // Let the BreakpointLocation decide if it should stop here (could not have 55 // reached it's target hit count yet, or it could have a callback 56 // that decided it shouldn't stop (shared library loads/unloads). 57 return bp->ShouldStop (context); 58 } 59 // We should stop here since this BreakpointLocation isn't valid anymore or it 60 // doesn't exist. 61 return true; 62 } 63 64 lldb::break_id_t 65 BreakpointLocationList::FindIDByAddress (Address &addr) 66 { 67 BreakpointLocationSP bp_loc_sp = FindByAddress (addr); 68 if (bp_loc_sp) 69 { 70 return bp_loc_sp->GetID(); 71 } 72 return LLDB_INVALID_BREAK_ID; 73 } 74 75 bool 76 BreakpointLocationList::Remove (lldb::break_id_t break_id) 77 { 78 Mutex::Locker locker (m_mutex); 79 collection::iterator pos = GetIDIterator(break_id); // Predicate 80 if (pos != m_locations.end()) 81 { 82 m_address_to_location.erase ((*pos)->GetAddress()); 83 m_locations.erase(pos); 84 return true; 85 } 86 return false; 87 } 88 89 90 class BreakpointLocationIDMatches 91 { 92 public: 93 BreakpointLocationIDMatches (lldb::break_id_t break_id) : 94 m_break_id(break_id) 95 { 96 } 97 98 bool operator() (const BreakpointLocationSP &bp_loc_sp) const 99 { 100 return m_break_id == bp_loc_sp->GetID(); 101 } 102 103 private: 104 const lldb::break_id_t m_break_id; 105 }; 106 107 class BreakpointLocationAddressMatches 108 { 109 public: 110 BreakpointLocationAddressMatches (Address& addr) : 111 m_addr(addr) 112 { 113 } 114 115 bool operator() (const BreakpointLocationSP& bp_loc_sp) const 116 { 117 return Address::CompareFileAddress(m_addr, bp_loc_sp->GetAddress()) == 0; 118 } 119 120 private: 121 const Address &m_addr; 122 }; 123 124 BreakpointLocationList::collection::iterator 125 BreakpointLocationList::GetIDIterator (lldb::break_id_t break_id) 126 { 127 Mutex::Locker locker (m_mutex); 128 return std::find_if (m_locations.begin(), 129 m_locations.end(), 130 BreakpointLocationIDMatches(break_id)); 131 } 132 133 BreakpointLocationList::collection::const_iterator 134 BreakpointLocationList::GetIDConstIterator (lldb::break_id_t break_id) const 135 { 136 Mutex::Locker locker (m_mutex); 137 return std::find_if (m_locations.begin(), 138 m_locations.end(), 139 BreakpointLocationIDMatches(break_id)); 140 } 141 142 BreakpointLocationSP 143 BreakpointLocationList::FindByID (lldb::break_id_t break_id) 144 { 145 Mutex::Locker locker (m_mutex); 146 BreakpointLocationSP stop_sp; 147 collection::iterator pos = GetIDIterator(break_id); 148 if (pos != m_locations.end()) 149 stop_sp = *pos; 150 151 return stop_sp; 152 } 153 154 const BreakpointLocationSP 155 BreakpointLocationList::FindByID (lldb::break_id_t break_id) const 156 { 157 Mutex::Locker locker (m_mutex); 158 BreakpointLocationSP stop_sp; 159 collection::const_iterator pos = GetIDConstIterator(break_id); 160 if (pos != m_locations.end()) 161 stop_sp = *pos; 162 163 return stop_sp; 164 } 165 166 size_t 167 BreakpointLocationList::FindInModule (Module *module, 168 BreakpointLocationCollection& bp_loc_list) 169 { 170 Mutex::Locker locker (m_mutex); 171 const size_t orig_size = bp_loc_list.GetSize(); 172 collection::iterator pos, end = m_locations.end(); 173 174 for (pos = m_locations.begin(); pos != end; ++pos) 175 { 176 bool seen = false; 177 BreakpointLocationSP break_loc = (*pos); 178 const Section *section = break_loc->GetAddress().GetSection(); 179 if (section) 180 { 181 if (section->GetModule() == module) 182 { 183 if (!seen) 184 { 185 seen = true; 186 bp_loc_list.Add (break_loc); 187 } 188 189 } 190 } 191 } 192 return bp_loc_list.GetSize() - orig_size; 193 } 194 195 const BreakpointLocationSP 196 BreakpointLocationList::FindByAddress (Address &addr) const 197 { 198 Mutex::Locker locker (m_mutex); 199 BreakpointLocationSP stop_sp; 200 if (!m_locations.empty()) 201 { 202 addr_map::const_iterator pos = m_address_to_location.find (addr); 203 if (pos != m_address_to_location.end()) 204 stop_sp = pos->second; 205 } 206 207 return stop_sp; 208 } 209 210 void 211 BreakpointLocationList::Dump (Stream *s) const 212 { 213 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 214 s->Indent(); 215 Mutex::Locker locker (m_mutex); 216 s->Printf("BreakpointLocationList with %zu BreakpointLocations:\n", m_locations.size()); 217 s->IndentMore(); 218 collection::const_iterator pos, end = m_locations.end(); 219 for (pos = m_locations.begin(); pos != end; ++pos) 220 (*pos).get()->Dump(s); 221 s->IndentLess(); 222 } 223 224 225 BreakpointLocationSP 226 BreakpointLocationList::GetByIndex (uint32_t i) 227 { 228 Mutex::Locker locker (m_mutex); 229 BreakpointLocationSP stop_sp; 230 if (i < m_locations.size()) 231 stop_sp = m_locations[i]; 232 233 return stop_sp; 234 } 235 236 const BreakpointLocationSP 237 BreakpointLocationList::GetByIndex (uint32_t i) const 238 { 239 Mutex::Locker locker (m_mutex); 240 BreakpointLocationSP stop_sp; 241 if (i < m_locations.size()) 242 stop_sp = m_locations[i]; 243 244 return stop_sp; 245 } 246 247 void 248 BreakpointLocationList::ClearAllBreakpointSites () 249 { 250 Mutex::Locker locker (m_mutex); 251 collection::iterator pos, end = m_locations.end(); 252 for (pos = m_locations.begin(); pos != end; ++pos) 253 (*pos)->ClearBreakpointSite(); 254 } 255 256 void 257 BreakpointLocationList::ResolveAllBreakpointSites () 258 { 259 Mutex::Locker locker (m_mutex); 260 collection::iterator pos, end = m_locations.end(); 261 262 for (pos = m_locations.begin(); pos != end; ++pos) 263 { 264 if ((*pos)->IsEnabled()) 265 (*pos)->ResolveBreakpointSite(); 266 } 267 } 268 269 uint32_t 270 BreakpointLocationList::GetHitCount () const 271 { 272 uint32_t hit_count = 0; 273 Mutex::Locker locker (m_mutex); 274 collection::const_iterator pos, end = m_locations.end(); 275 for (pos = m_locations.begin(); pos != end; ++pos) 276 hit_count += (*pos)->GetHitCount(); 277 return hit_count; 278 } 279 280 size_t 281 BreakpointLocationList::GetNumResolvedLocations() const 282 { 283 Mutex::Locker locker (m_mutex); 284 size_t resolve_count = 0; 285 collection::const_iterator pos, end = m_locations.end(); 286 for (pos = m_locations.begin(); pos != end; ++pos) 287 { 288 if ((*pos)->IsResolved()) 289 ++resolve_count; 290 } 291 return resolve_count; 292 } 293 294 break_id_t 295 BreakpointLocationList::GetNextID() 296 { 297 return ++m_next_id; 298 } 299 300 void 301 BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level) 302 { 303 Mutex::Locker locker (m_mutex); 304 collection::iterator pos, end = m_locations.end(); 305 306 for (pos = m_locations.begin(); pos != end; ++pos) 307 { 308 s->Printf(" "); 309 (*pos)->GetDescription(s, level); 310 } 311 } 312 313