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::user_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::user_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::user_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::user_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::user_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::user_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::user_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::user_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::user_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::user_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 196 static int 197 FindLocationByAddress (Address *addr_ptr, const BreakpointLocationSP *bp_loc_sp_ptr) 198 { 199 return Address::CompareModulePointerAndOffset(*addr_ptr, (*bp_loc_sp_ptr)->GetAddress()); 200 } 201 202 const BreakpointLocationSP 203 BreakpointLocationList::FindByAddress (Address &addr) const 204 { 205 Mutex::Locker locker (m_mutex); 206 BreakpointLocationSP stop_sp; 207 if (!m_locations.empty()) 208 { 209 addr_map::const_iterator pos = m_address_to_location.find (addr); 210 if (pos != m_address_to_location.end()) 211 stop_sp = pos->second; 212 } 213 214 return stop_sp; 215 } 216 217 void 218 BreakpointLocationList::Dump (Stream *s) const 219 { 220 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); 221 s->Indent(); 222 Mutex::Locker locker (m_mutex); 223 s->Printf("BreakpointLocationList with %zu BreakpointLocations:\n", m_locations.size()); 224 s->IndentMore(); 225 collection::const_iterator pos, end = m_locations.end(); 226 for (pos = m_locations.begin(); pos != end; ++pos) 227 (*pos).get()->Dump(s); 228 s->IndentLess(); 229 } 230 231 232 BreakpointLocationSP 233 BreakpointLocationList::GetByIndex (uint32_t i) 234 { 235 Mutex::Locker locker (m_mutex); 236 BreakpointLocationSP stop_sp; 237 if (i >= 0 && i < m_locations.size()) 238 stop_sp = m_locations[i]; 239 240 return stop_sp; 241 } 242 243 const BreakpointLocationSP 244 BreakpointLocationList::GetByIndex (uint32_t i) const 245 { 246 Mutex::Locker locker (m_mutex); 247 BreakpointLocationSP stop_sp; 248 if (i >= 0 && i < m_locations.size()) 249 stop_sp = m_locations[i]; 250 251 return stop_sp; 252 } 253 254 void 255 BreakpointLocationList::ClearAllBreakpointSites () 256 { 257 Mutex::Locker locker (m_mutex); 258 collection::iterator pos, end = m_locations.end(); 259 for (pos = m_locations.begin(); pos != end; ++pos) 260 (*pos)->ClearBreakpointSite(); 261 } 262 263 void 264 BreakpointLocationList::ResolveAllBreakpointSites () 265 { 266 Mutex::Locker locker (m_mutex); 267 collection::iterator pos, end = m_locations.end(); 268 269 for (pos = m_locations.begin(); pos != end; ++pos) 270 (*pos)->ResolveBreakpointSite(); 271 } 272 273 size_t 274 BreakpointLocationList::GetNumResolvedLocations() const 275 { 276 Mutex::Locker locker (m_mutex); 277 size_t resolve_count = 0; 278 collection::const_iterator pos, end = m_locations.end(); 279 for (pos = m_locations.begin(); pos != end; ++pos) 280 { 281 if ((*pos)->IsResolved()) 282 ++resolve_count; 283 } 284 return resolve_count; 285 } 286 287 break_id_t 288 BreakpointLocationList::GetNextID() 289 { 290 return ++m_next_id; 291 } 292 293 void 294 BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level) 295 { 296 Mutex::Locker locker (m_mutex); 297 collection::iterator pos, end = m_locations.end(); 298 299 for (pos = m_locations.begin(); pos != end; ++pos) 300 { 301 s->Printf(" "); 302 (*pos)->GetDescription(s, level); 303 } 304 } 305 306