BreakpointLocationList.cpp revision 280031
1200483Srwatson//===-- BreakpointLocationList.cpp ------------------------------*- C++ -*-===// 2200483Srwatson// 3200483Srwatson// The LLVM Compiler Infrastructure 4200483Srwatson// 5200483Srwatson// This file is distributed under the University of Illinois Open Source 6200483Srwatson// License. See LICENSE.TXT for details. 7200483Srwatson// 8200483Srwatson//===----------------------------------------------------------------------===// 9200483Srwatson 10200483Srwatson 11200483Srwatson// C Includes 12200483Srwatson// C++ Includes 13200483Srwatson// Other libraries and framework includes 14200483Srwatson// Project includes 15200483Srwatson#include "lldb/Breakpoint/BreakpointLocationList.h" 16200483Srwatson 17200483Srwatson#include "lldb/Breakpoint/BreakpointLocation.h" 18200483Srwatson#include "lldb/Breakpoint/Breakpoint.h" 19200483Srwatson#include "lldb/Core/ArchSpec.h" 20200483Srwatson#include "lldb/Core/Module.h" 21200483Srwatson#include "lldb/Core/Section.h" 22200483Srwatson#include "lldb/Target/SectionLoadList.h" 23200483Srwatson#include "lldb/Target/Target.h" 24200483Srwatson 25200483Srwatson 26200483Srwatsonusing namespace lldb; 27200483Srwatsonusing namespace lldb_private; 28200483Srwatson 29200483SrwatsonBreakpointLocationList::BreakpointLocationList(Breakpoint &owner) : 30200483Srwatson m_owner (owner), 31200483Srwatson m_locations(), 32200483Srwatson m_address_to_location (), 33200483Srwatson m_mutex (Mutex::eMutexTypeRecursive), 34200483Srwatson m_next_id (0), 35200483Srwatson m_new_location_recorder (NULL) 36200483Srwatson{ 37200483Srwatson} 38200483Srwatson 39200483SrwatsonBreakpointLocationList::~BreakpointLocationList() 40200483Srwatson{ 41200483Srwatson} 42200483Srwatson 43200483SrwatsonBreakpointLocationSP 44200483SrwatsonBreakpointLocationList::Create (const Address &addr, bool resolve_indirect_symbols) 45200483Srwatson{ 46200483Srwatson Mutex::Locker locker (m_mutex); 47200483Srwatson // The location ID is just the size of the location list + 1 48200483Srwatson lldb::break_id_t bp_loc_id = ++m_next_id; 49200483Srwatson BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware(), resolve_indirect_symbols)); 50200483Srwatson m_locations.push_back (bp_loc_sp); 51200483Srwatson m_address_to_location[addr] = bp_loc_sp; 52200483Srwatson return bp_loc_sp; 53200483Srwatson} 54200483Srwatson 55200483Srwatsonbool 56200483SrwatsonBreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id) 57200483Srwatson{ 58200483Srwatson BreakpointLocationSP bp = FindByID (break_id); 59200483Srwatson if (bp) 60200483Srwatson { 61200483Srwatson // Let the BreakpointLocation decide if it should stop here (could not have 62200483Srwatson // reached it's target hit count yet, or it could have a callback 63200483Srwatson // that decided it shouldn't stop (shared library loads/unloads). 64200483Srwatson return bp->ShouldStop (context); 65200483Srwatson } 66200483Srwatson // We should stop here since this BreakpointLocation isn't valid anymore or it 67200483Srwatson // doesn't exist. 68200483Srwatson return true; 69200483Srwatson} 70200483Srwatson 71200483Srwatsonlldb::break_id_t 72200483SrwatsonBreakpointLocationList::FindIDByAddress (const Address &addr) 73200483Srwatson{ 74200483Srwatson BreakpointLocationSP bp_loc_sp = FindByAddress (addr); 75200483Srwatson if (bp_loc_sp) 76200483Srwatson { 77200483Srwatson return bp_loc_sp->GetID(); 78200483Srwatson } 79200483Srwatson return LLDB_INVALID_BREAK_ID; 80200483Srwatson} 81200483Srwatson 82200483Srwatsonstatic bool 83200483SrwatsonCompare (BreakpointLocationSP lhs, lldb::break_id_t val) 84200483Srwatson{ 85200483Srwatson return lhs->GetID() < val; 86200483Srwatson} 87200483Srwatson 88200483SrwatsonBreakpointLocationSP 89200483SrwatsonBreakpointLocationList::FindByID (lldb::break_id_t break_id) const 90200483Srwatson{ 91200483Srwatson Mutex::Locker locker (m_mutex); 92200483Srwatson collection::const_iterator end = m_locations.end(); 93200483Srwatson collection::const_iterator pos = std::lower_bound(m_locations.begin(), end, break_id, Compare); 94200483Srwatson if (pos != end && (*pos)->GetID() == break_id) 95200483Srwatson return *(pos); 96200483Srwatson else 97200483Srwatson return BreakpointLocationSP(); 98200483Srwatson} 99200483Srwatson 100200483Srwatsonsize_t 101200483SrwatsonBreakpointLocationList::FindInModule (Module *module, 102200483Srwatson BreakpointLocationCollection& bp_loc_list) 103200483Srwatson{ 104200483Srwatson Mutex::Locker locker (m_mutex); 105200483Srwatson const size_t orig_size = bp_loc_list.GetSize(); 106200483Srwatson collection::iterator pos, end = m_locations.end(); 107200483Srwatson 108200483Srwatson for (pos = m_locations.begin(); pos != end; ++pos) 109200483Srwatson { 110200483Srwatson BreakpointLocationSP break_loc = (*pos); 111200483Srwatson SectionSP section_sp (break_loc->GetAddress().GetSection()); 112200483Srwatson if (section_sp && section_sp->GetModule().get() == module) 113200483Srwatson { 114200483Srwatson bp_loc_list.Add (break_loc); 115200483Srwatson } 116200483Srwatson } 117200483Srwatson return bp_loc_list.GetSize() - orig_size; 118200483Srwatson} 119200483Srwatson 120200483Srwatsonconst BreakpointLocationSP 121200483SrwatsonBreakpointLocationList::FindByAddress (const Address &addr) const 122200483Srwatson{ 123200483Srwatson Mutex::Locker locker (m_mutex); 124200483Srwatson BreakpointLocationSP bp_loc_sp; 125200483Srwatson if (!m_locations.empty()) 126200483Srwatson { 127200483Srwatson Address so_addr; 128200483Srwatson 129200483Srwatson if (addr.IsSectionOffset()) 130200483Srwatson { 131200483Srwatson so_addr = addr; 132200483Srwatson } 133200483Srwatson else 134200483Srwatson { 135200483Srwatson // Try and resolve as a load address if possible. 136200483Srwatson m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr); 137200483Srwatson if (!so_addr.IsValid()) 138200483Srwatson { 139200483Srwatson // The address didn't resolve, so just set to passed in addr. 140200483Srwatson so_addr = addr; 141200483Srwatson } 142200483Srwatson } 143200483Srwatson 144200483Srwatson addr_map::const_iterator pos = m_address_to_location.find (so_addr); 145200483Srwatson if (pos != m_address_to_location.end()) 146200483Srwatson bp_loc_sp = pos->second; 147200483Srwatson } 148200483Srwatson 149200483Srwatson return bp_loc_sp; 150200483Srwatson} 151200483Srwatson 152200483Srwatsonvoid 153200483SrwatsonBreakpointLocationList::Dump (Stream *s) const 154200483Srwatson{ 155200483Srwatson s->Printf("%p: ", static_cast<const void*>(this)); 156200483Srwatson //s->Indent(); 157200483Srwatson Mutex::Locker locker (m_mutex); 158200483Srwatson s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size()); 159200483Srwatson s->IndentMore(); 160200483Srwatson collection::const_iterator pos, end = m_locations.end(); 161200483Srwatson for (pos = m_locations.begin(); pos != end; ++pos) 162200483Srwatson (*pos).get()->Dump(s); 163200483Srwatson s->IndentLess(); 164200483Srwatson} 165200483Srwatson 166200483Srwatson 167200483SrwatsonBreakpointLocationSP 168200483SrwatsonBreakpointLocationList::GetByIndex (size_t i) 169200483Srwatson{ 170200483Srwatson Mutex::Locker locker (m_mutex); 171200483Srwatson BreakpointLocationSP bp_loc_sp; 172200483Srwatson if (i < m_locations.size()) 173200483Srwatson bp_loc_sp = m_locations[i]; 174200483Srwatson 175200483Srwatson return bp_loc_sp; 176200483Srwatson} 177200483Srwatson 178200483Srwatsonconst BreakpointLocationSP 179200483SrwatsonBreakpointLocationList::GetByIndex (size_t i) const 180200483Srwatson{ 181200483Srwatson Mutex::Locker locker (m_mutex); 182200483Srwatson BreakpointLocationSP bp_loc_sp; 183200483Srwatson if (i < m_locations.size()) 184200483Srwatson bp_loc_sp = m_locations[i]; 185200483Srwatson 186200483Srwatson return bp_loc_sp; 187200483Srwatson} 188200483Srwatson 189200483Srwatsonvoid 190200483SrwatsonBreakpointLocationList::ClearAllBreakpointSites () 191200483Srwatson{ 192200483Srwatson Mutex::Locker locker (m_mutex); 193200483Srwatson collection::iterator pos, end = m_locations.end(); 194200483Srwatson for (pos = m_locations.begin(); pos != end; ++pos) 195200483Srwatson (*pos)->ClearBreakpointSite(); 196200483Srwatson} 197200483Srwatson 198200483Srwatsonvoid 199200483SrwatsonBreakpointLocationList::ResolveAllBreakpointSites () 200200483Srwatson{ 201200483Srwatson Mutex::Locker locker (m_mutex); 202200483Srwatson collection::iterator pos, end = m_locations.end(); 203200483Srwatson 204200483Srwatson for (pos = m_locations.begin(); pos != end; ++pos) 205200483Srwatson { 206200483Srwatson if ((*pos)->IsEnabled()) 207200483Srwatson (*pos)->ResolveBreakpointSite(); 208200483Srwatson } 209200483Srwatson} 210200483Srwatson 211200483Srwatsonuint32_t 212200483SrwatsonBreakpointLocationList::GetHitCount () const 213200483Srwatson{ 214200483Srwatson uint32_t hit_count = 0; 215200483Srwatson Mutex::Locker locker (m_mutex); 216200483Srwatson collection::const_iterator pos, end = m_locations.end(); 217200483Srwatson for (pos = m_locations.begin(); pos != end; ++pos) 218200483Srwatson hit_count += (*pos)->GetHitCount(); 219200483Srwatson return hit_count; 220200483Srwatson} 221200483Srwatson 222200483Srwatsonsize_t 223200483SrwatsonBreakpointLocationList::GetNumResolvedLocations() const 224200483Srwatson{ 225200483Srwatson Mutex::Locker locker (m_mutex); 226200483Srwatson size_t resolve_count = 0; 227200483Srwatson collection::const_iterator pos, end = m_locations.end(); 228200483Srwatson for (pos = m_locations.begin(); pos != end; ++pos) 229200483Srwatson { 230200483Srwatson if ((*pos)->IsResolved()) 231200483Srwatson ++resolve_count; 232200483Srwatson } 233200483Srwatson return resolve_count; 234200483Srwatson} 235200483Srwatson 236200483Srwatsonvoid 237200483SrwatsonBreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level) 238200483Srwatson{ 239200483Srwatson Mutex::Locker locker (m_mutex); 240200483Srwatson collection::iterator pos, end = m_locations.end(); 241200483Srwatson 242200483Srwatson for (pos = m_locations.begin(); pos != end; ++pos) 243200483Srwatson { 244200483Srwatson s->Printf(" "); 245200483Srwatson (*pos)->GetDescription(s, level); 246200483Srwatson } 247200483Srwatson} 248200483Srwatson 249200483SrwatsonBreakpointLocationSP 250200483SrwatsonBreakpointLocationList::AddLocation (const Address &addr, bool resolve_indirect_symbols, bool *new_location) 251200483Srwatson{ 252200483Srwatson Mutex::Locker locker (m_mutex); 253200483Srwatson 254200483Srwatson if (new_location) 255200483Srwatson *new_location = false; 256200483Srwatson BreakpointLocationSP bp_loc_sp (FindByAddress(addr)); 257200483Srwatson if (!bp_loc_sp) 258200483Srwatson { 259200483Srwatson bp_loc_sp = Create (addr, resolve_indirect_symbols); 260200483Srwatson if (bp_loc_sp) 261200483Srwatson { 262200483Srwatson bp_loc_sp->ResolveBreakpointSite(); 263200483Srwatson 264200483Srwatson if (new_location) 265200483Srwatson *new_location = true; 266200483Srwatson if(m_new_location_recorder) 267 { 268 m_new_location_recorder->Add(bp_loc_sp); 269 } 270 } 271 } 272 return bp_loc_sp; 273} 274 275void 276BreakpointLocationList::SwapLocation (BreakpointLocationSP to_location_sp, BreakpointLocationSP from_location_sp) 277{ 278 if (!from_location_sp || !to_location_sp) 279 return; 280 281 m_address_to_location.erase(to_location_sp->GetAddress()); 282 to_location_sp->SwapLocation(from_location_sp); 283 RemoveLocation(from_location_sp); 284 m_address_to_location[to_location_sp->GetAddress()] = to_location_sp; 285 to_location_sp->ResolveBreakpointSite(); 286} 287 288 289bool 290BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp) 291{ 292 if (bp_loc_sp) 293 { 294 Mutex::Locker locker (m_mutex); 295 296 m_address_to_location.erase (bp_loc_sp->GetAddress()); 297 298 collection::iterator pos, end = m_locations.end(); 299 for (pos = m_locations.begin(); pos != end; ++pos) 300 { 301 if ((*pos).get() == bp_loc_sp.get()) 302 { 303 m_locations.erase (pos); 304 return true; 305 } 306 } 307 } 308 return false; 309} 310 311void 312BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch) 313{ 314 Mutex::Locker locker (m_mutex); 315 size_t idx = 0; 316 // Don't cache m_location.size() as it will change since we might 317 // remove locations from our vector... 318 while (idx < m_locations.size()) 319 { 320 BreakpointLocation *bp_loc = m_locations[idx].get(); 321 if (bp_loc->GetAddress().SectionWasDeleted()) 322 { 323 // Section was deleted which means this breakpoint comes from a module 324 // that is no longer valid, so we should remove it. 325 m_locations.erase(m_locations.begin() + idx); 326 continue; 327 } 328 if (arch.IsValid()) 329 { 330 ModuleSP module_sp (bp_loc->GetAddress().GetModule()); 331 if (module_sp) 332 { 333 if (!arch.IsCompatibleMatch(module_sp->GetArchitecture())) 334 { 335 // The breakpoint was in a module whose architecture is no longer 336 // compatible with "arch", so we need to remove it 337 m_locations.erase(m_locations.begin() + idx); 338 continue; 339 } 340 } 341 } 342 // Only increment the index if we didn't remove the locations at index "idx" 343 ++idx; 344 } 345} 346 347void 348BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations) 349{ 350 Mutex::Locker locker (m_mutex); 351 assert (m_new_location_recorder == NULL); 352 m_new_location_recorder = &new_locations; 353} 354 355void 356BreakpointLocationList::StopRecordingNewLocations () 357{ 358 Mutex::Locker locker (m_mutex); 359 m_new_location_recorder = NULL; 360} 361 362void 363BreakpointLocationList::Compact() 364{ 365 lldb::break_id_t highest_id = 0; 366 367 for (BreakpointLocationSP loc_sp : m_locations) 368 { 369 lldb::break_id_t cur_id = loc_sp->GetID(); 370 if (cur_id > highest_id) 371 highest_id = cur_id; 372 } 373 m_next_id = highest_id; 374} 375