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 17 #include "lldb/Breakpoint/BreakpointLocation.h" 18 #include "lldb/Breakpoint/Breakpoint.h" 19 #include "lldb/Core/ArchSpec.h" 20 #include "lldb/Core/Module.h" 21 #include "lldb/Core/Section.h" 22 #include "lldb/Target/Target.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 27 BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) : 28 m_owner (owner), 29 m_locations(), 30 m_address_to_location (), 31 m_mutex (Mutex::eMutexTypeRecursive), 32 m_next_id (0), 33 m_new_location_recorder (NULL) 34 { 35 } 36 37 BreakpointLocationList::~BreakpointLocationList() 38 { 39 } 40 41 BreakpointLocationSP 42 BreakpointLocationList::Create (const Address &addr) 43 { 44 Mutex::Locker locker (m_mutex); 45 // The location ID is just the size of the location list + 1 46 lldb::break_id_t bp_loc_id = ++m_next_id; 47 BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware())); 48 m_locations.push_back (bp_loc_sp); 49 m_address_to_location[addr] = bp_loc_sp; 50 return bp_loc_sp; 51 } 52 53 bool 54 BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id) 55 { 56 BreakpointLocationSP bp = FindByID (break_id); 57 if (bp) 58 { 59 // Let the BreakpointLocation decide if it should stop here (could not have 60 // reached it's target hit count yet, or it could have a callback 61 // that decided it shouldn't stop (shared library loads/unloads). 62 return bp->ShouldStop (context); 63 } 64 // We should stop here since this BreakpointLocation isn't valid anymore or it 65 // doesn't exist. 66 return true; 67 } 68 69 lldb::break_id_t 70 BreakpointLocationList::FindIDByAddress (const Address &addr) 71 { 72 BreakpointLocationSP bp_loc_sp = FindByAddress (addr); 73 if (bp_loc_sp) 74 { 75 return bp_loc_sp->GetID(); 76 } 77 return LLDB_INVALID_BREAK_ID; 78 } 79 80 BreakpointLocationSP 81 BreakpointLocationList::FindByID (lldb::break_id_t break_id) const 82 { 83 BreakpointLocationSP bp_loc_sp; 84 Mutex::Locker locker (m_mutex); 85 // We never remove a breakpoint locations, so the ID can be translated into 86 // the location index by subtracting 1 87 uint32_t idx = break_id - 1; 88 if (idx <= m_locations.size()) 89 { 90 bp_loc_sp = m_locations[idx]; 91 } 92 return bp_loc_sp; 93 } 94 95 size_t 96 BreakpointLocationList::FindInModule (Module *module, 97 BreakpointLocationCollection& bp_loc_list) 98 { 99 Mutex::Locker locker (m_mutex); 100 const size_t orig_size = bp_loc_list.GetSize(); 101 collection::iterator pos, end = m_locations.end(); 102 103 for (pos = m_locations.begin(); pos != end; ++pos) 104 { 105 BreakpointLocationSP break_loc = (*pos); 106 SectionSP section_sp (break_loc->GetAddress().GetSection()); 107 if (section_sp && section_sp->GetModule().get() == module) 108 { 109 bp_loc_list.Add (break_loc); 110 } 111 } 112 return bp_loc_list.GetSize() - orig_size; 113 } 114 115 const BreakpointLocationSP 116 BreakpointLocationList::FindByAddress (const Address &addr) const 117 { 118 Mutex::Locker locker (m_mutex); 119 BreakpointLocationSP bp_loc_sp; 120 if (!m_locations.empty()) 121 { 122 Address so_addr; 123 124 if (addr.IsSectionOffset()) 125 { 126 so_addr = addr; 127 } 128 else 129 { 130 // Try and resolve as a load address if possible. 131 m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr); 132 if (!so_addr.IsValid()) 133 { 134 // The address didn't resolve, so just set to passed in addr. 135 so_addr = addr; 136 } 137 } 138 139 addr_map::const_iterator pos = m_address_to_location.find (so_addr); 140 if (pos != m_address_to_location.end()) 141 bp_loc_sp = pos->second; 142 } 143 144 return bp_loc_sp; 145 } 146 147 void 148 BreakpointLocationList::Dump (Stream *s) const 149 { 150 s->Printf("%p: ", this); 151 //s->Indent(); 152 Mutex::Locker locker (m_mutex); 153 s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size()); 154 s->IndentMore(); 155 collection::const_iterator pos, end = m_locations.end(); 156 for (pos = m_locations.begin(); pos != end; ++pos) 157 (*pos).get()->Dump(s); 158 s->IndentLess(); 159 } 160 161 162 BreakpointLocationSP 163 BreakpointLocationList::GetByIndex (size_t i) 164 { 165 Mutex::Locker locker (m_mutex); 166 BreakpointLocationSP bp_loc_sp; 167 if (i < m_locations.size()) 168 bp_loc_sp = m_locations[i]; 169 170 return bp_loc_sp; 171 } 172 173 const BreakpointLocationSP 174 BreakpointLocationList::GetByIndex (size_t i) const 175 { 176 Mutex::Locker locker (m_mutex); 177 BreakpointLocationSP bp_loc_sp; 178 if (i < m_locations.size()) 179 bp_loc_sp = m_locations[i]; 180 181 return bp_loc_sp; 182 } 183 184 void 185 BreakpointLocationList::ClearAllBreakpointSites () 186 { 187 Mutex::Locker locker (m_mutex); 188 collection::iterator pos, end = m_locations.end(); 189 for (pos = m_locations.begin(); pos != end; ++pos) 190 (*pos)->ClearBreakpointSite(); 191 } 192 193 void 194 BreakpointLocationList::ResolveAllBreakpointSites () 195 { 196 Mutex::Locker locker (m_mutex); 197 collection::iterator pos, end = m_locations.end(); 198 199 for (pos = m_locations.begin(); pos != end; ++pos) 200 { 201 if ((*pos)->IsEnabled()) 202 (*pos)->ResolveBreakpointSite(); 203 } 204 } 205 206 uint32_t 207 BreakpointLocationList::GetHitCount () const 208 { 209 uint32_t hit_count = 0; 210 Mutex::Locker locker (m_mutex); 211 collection::const_iterator pos, end = m_locations.end(); 212 for (pos = m_locations.begin(); pos != end; ++pos) 213 hit_count += (*pos)->GetHitCount(); 214 return hit_count; 215 } 216 217 size_t 218 BreakpointLocationList::GetNumResolvedLocations() const 219 { 220 Mutex::Locker locker (m_mutex); 221 size_t resolve_count = 0; 222 collection::const_iterator pos, end = m_locations.end(); 223 for (pos = m_locations.begin(); pos != end; ++pos) 224 { 225 if ((*pos)->IsResolved()) 226 ++resolve_count; 227 } 228 return resolve_count; 229 } 230 231 void 232 BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level) 233 { 234 Mutex::Locker locker (m_mutex); 235 collection::iterator pos, end = m_locations.end(); 236 237 for (pos = m_locations.begin(); pos != end; ++pos) 238 { 239 s->Printf(" "); 240 (*pos)->GetDescription(s, level); 241 } 242 } 243 244 BreakpointLocationSP 245 BreakpointLocationList::AddLocation (const Address &addr, bool *new_location) 246 { 247 Mutex::Locker locker (m_mutex); 248 249 if (new_location) 250 *new_location = false; 251 BreakpointLocationSP bp_loc_sp (FindByAddress(addr)); 252 if (!bp_loc_sp) 253 { 254 bp_loc_sp = Create (addr); 255 if (bp_loc_sp) 256 { 257 bp_loc_sp->ResolveBreakpointSite(); 258 259 if (new_location) 260 *new_location = true; 261 if(m_new_location_recorder) 262 { 263 m_new_location_recorder->Add(bp_loc_sp); 264 } 265 } 266 } 267 return bp_loc_sp; 268 } 269 270 bool 271 BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp) 272 { 273 if (bp_loc_sp) 274 { 275 Mutex::Locker locker (m_mutex); 276 277 m_address_to_location.erase (bp_loc_sp->GetAddress()); 278 279 collection::iterator pos, end = m_locations.end(); 280 for (pos = m_locations.begin(); pos != end; ++pos) 281 { 282 if ((*pos).get() == bp_loc_sp.get()) 283 { 284 m_locations.erase (pos); 285 return true; 286 } 287 } 288 } 289 return false; 290 } 291 292 void 293 BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch) 294 { 295 Mutex::Locker locker (m_mutex); 296 size_t idx = 0; 297 // Don't cache m_location.size() as it will change since we might 298 // remove locations from our vector... 299 while (idx < m_locations.size()) 300 { 301 BreakpointLocation *bp_loc = m_locations[idx].get(); 302 if (bp_loc->GetAddress().SectionWasDeleted()) 303 { 304 // Section was deleted which means this breakpoint comes from a module 305 // that is no longer valid, so we should remove it. 306 m_locations.erase(m_locations.begin() + idx); 307 continue; 308 } 309 if (arch.IsValid()) 310 { 311 ModuleSP module_sp (bp_loc->GetAddress().GetModule()); 312 if (module_sp) 313 { 314 if (!arch.IsCompatibleMatch(module_sp->GetArchitecture())) 315 { 316 // The breakpoint was in a module whose architecture is no longer 317 // compatible with "arch", so we need to remove it 318 m_locations.erase(m_locations.begin() + idx); 319 continue; 320 } 321 } 322 } 323 // Only increment the index if we didn't remove the locations at index "idx" 324 ++idx; 325 } 326 } 327 328 void 329 BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations) 330 { 331 Mutex::Locker locker (m_mutex); 332 assert (m_new_location_recorder == NULL); 333 m_new_location_recorder = &new_locations; 334 } 335 336 void 337 BreakpointLocationList::StopRecordingNewLocations () 338 { 339 Mutex::Locker locker (m_mutex); 340 m_new_location_recorder = NULL; 341 } 342 343