BreakpointLocationList.cpp revision 296417
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// C Includes 11// C++ Includes 12// Other libraries and framework includes 13// Project includes 14#include "lldb/Breakpoint/BreakpointLocationList.h" 15 16#include "lldb/Breakpoint/BreakpointLocation.h" 17#include "lldb/Breakpoint/Breakpoint.h" 18#include "lldb/Core/ArchSpec.h" 19#include "lldb/Core/Module.h" 20#include "lldb/Core/Section.h" 21#include "lldb/Target/SectionLoadList.h" 22#include "lldb/Target/Target.h" 23 24using namespace lldb; 25using namespace lldb_private; 26 27BreakpointLocationList::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 (nullptr) 34{ 35} 36 37BreakpointLocationList::~BreakpointLocationList() = default; 38 39BreakpointLocationSP 40BreakpointLocationList::Create (const Address &addr, bool resolve_indirect_symbols) 41{ 42 Mutex::Locker locker (m_mutex); 43 // The location ID is just the size of the location list + 1 44 lldb::break_id_t bp_loc_id = ++m_next_id; 45 BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware(), resolve_indirect_symbols)); 46 m_locations.push_back (bp_loc_sp); 47 m_address_to_location[addr] = bp_loc_sp; 48 return bp_loc_sp; 49} 50 51bool 52BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id) 53{ 54 BreakpointLocationSP bp = FindByID (break_id); 55 if (bp) 56 { 57 // Let the BreakpointLocation decide if it should stop here (could not have 58 // reached it's target hit count yet, or it could have a callback 59 // that decided it shouldn't stop (shared library loads/unloads). 60 return bp->ShouldStop (context); 61 } 62 // We should stop here since this BreakpointLocation isn't valid anymore or it 63 // doesn't exist. 64 return true; 65} 66 67lldb::break_id_t 68BreakpointLocationList::FindIDByAddress (const Address &addr) 69{ 70 BreakpointLocationSP bp_loc_sp = FindByAddress (addr); 71 if (bp_loc_sp) 72 { 73 return bp_loc_sp->GetID(); 74 } 75 return LLDB_INVALID_BREAK_ID; 76} 77 78static bool 79Compare (BreakpointLocationSP lhs, lldb::break_id_t val) 80{ 81 return lhs->GetID() < val; 82} 83 84BreakpointLocationSP 85BreakpointLocationList::FindByID (lldb::break_id_t break_id) const 86{ 87 Mutex::Locker locker (m_mutex); 88 collection::const_iterator end = m_locations.end(); 89 collection::const_iterator pos = std::lower_bound(m_locations.begin(), end, break_id, Compare); 90 if (pos != end && (*pos)->GetID() == break_id) 91 return *(pos); 92 else 93 return BreakpointLocationSP(); 94} 95 96size_t 97BreakpointLocationList::FindInModule (Module *module, 98 BreakpointLocationCollection& bp_loc_list) 99{ 100 Mutex::Locker locker (m_mutex); 101 const size_t orig_size = bp_loc_list.GetSize(); 102 collection::iterator pos, end = m_locations.end(); 103 104 for (pos = m_locations.begin(); pos != end; ++pos) 105 { 106 BreakpointLocationSP break_loc = (*pos); 107 SectionSP section_sp (break_loc->GetAddress().GetSection()); 108 if (section_sp && section_sp->GetModule().get() == module) 109 { 110 bp_loc_list.Add (break_loc); 111 } 112 } 113 return bp_loc_list.GetSize() - orig_size; 114} 115 116const BreakpointLocationSP 117BreakpointLocationList::FindByAddress (const Address &addr) const 118{ 119 Mutex::Locker locker (m_mutex); 120 BreakpointLocationSP bp_loc_sp; 121 if (!m_locations.empty()) 122 { 123 Address so_addr; 124 125 if (addr.IsSectionOffset()) 126 { 127 so_addr = addr; 128 } 129 else 130 { 131 // Try and resolve as a load address if possible. 132 m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr); 133 if (!so_addr.IsValid()) 134 { 135 // The address didn't resolve, so just set to passed in addr. 136 so_addr = addr; 137 } 138 } 139 140 addr_map::const_iterator pos = m_address_to_location.find (so_addr); 141 if (pos != m_address_to_location.end()) 142 bp_loc_sp = pos->second; 143 } 144 145 return bp_loc_sp; 146} 147 148void 149BreakpointLocationList::Dump (Stream *s) const 150{ 151 s->Printf("%p: ", static_cast<const void*>(this)); 152 //s->Indent(); 153 Mutex::Locker locker (m_mutex); 154 s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size()); 155 s->IndentMore(); 156 collection::const_iterator pos, end = m_locations.end(); 157 for (pos = m_locations.begin(); pos != end; ++pos) 158 (*pos).get()->Dump(s); 159 s->IndentLess(); 160} 161 162BreakpointLocationSP 163BreakpointLocationList::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 173const BreakpointLocationSP 174BreakpointLocationList::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 184void 185BreakpointLocationList::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 193void 194BreakpointLocationList::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 206uint32_t 207BreakpointLocationList::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 217size_t 218BreakpointLocationList::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 231void 232BreakpointLocationList::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 244BreakpointLocationSP 245BreakpointLocationList::AddLocation (const Address &addr, bool resolve_indirect_symbols, 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, resolve_indirect_symbols); 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 270void 271BreakpointLocationList::SwapLocation (BreakpointLocationSP to_location_sp, BreakpointLocationSP from_location_sp) 272{ 273 if (!from_location_sp || !to_location_sp) 274 return; 275 276 m_address_to_location.erase(to_location_sp->GetAddress()); 277 to_location_sp->SwapLocation(from_location_sp); 278 RemoveLocation(from_location_sp); 279 m_address_to_location[to_location_sp->GetAddress()] = to_location_sp; 280 to_location_sp->ResolveBreakpointSite(); 281} 282 283bool 284BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp) 285{ 286 if (bp_loc_sp) 287 { 288 Mutex::Locker locker (m_mutex); 289 290 m_address_to_location.erase (bp_loc_sp->GetAddress()); 291 292 collection::iterator pos, end = m_locations.end(); 293 for (pos = m_locations.begin(); pos != end; ++pos) 294 { 295 if ((*pos).get() == bp_loc_sp.get()) 296 { 297 m_locations.erase (pos); 298 return true; 299 } 300 } 301 } 302 return false; 303} 304 305void 306BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch) 307{ 308 Mutex::Locker locker (m_mutex); 309 size_t idx = 0; 310 // Don't cache m_location.size() as it will change since we might 311 // remove locations from our vector... 312 while (idx < m_locations.size()) 313 { 314 BreakpointLocation *bp_loc = m_locations[idx].get(); 315 if (bp_loc->GetAddress().SectionWasDeleted()) 316 { 317 // Section was deleted which means this breakpoint comes from a module 318 // that is no longer valid, so we should remove it. 319 m_locations.erase(m_locations.begin() + idx); 320 continue; 321 } 322 if (arch.IsValid()) 323 { 324 ModuleSP module_sp (bp_loc->GetAddress().GetModule()); 325 if (module_sp) 326 { 327 if (!arch.IsCompatibleMatch(module_sp->GetArchitecture())) 328 { 329 // The breakpoint was in a module whose architecture is no longer 330 // compatible with "arch", so we need to remove it 331 m_locations.erase(m_locations.begin() + idx); 332 continue; 333 } 334 } 335 } 336 // Only increment the index if we didn't remove the locations at index "idx" 337 ++idx; 338 } 339} 340 341void 342BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations) 343{ 344 Mutex::Locker locker (m_mutex); 345 assert(m_new_location_recorder == nullptr); 346 m_new_location_recorder = &new_locations; 347} 348 349void 350BreakpointLocationList::StopRecordingNewLocations () 351{ 352 Mutex::Locker locker (m_mutex); 353 m_new_location_recorder = nullptr; 354} 355 356void 357BreakpointLocationList::Compact() 358{ 359 lldb::break_id_t highest_id = 0; 360 361 for (BreakpointLocationSP loc_sp : m_locations) 362 { 363 lldb::break_id_t cur_id = loc_sp->GetID(); 364 if (cur_id > highest_id) 365 highest_id = cur_id; 366 } 367 m_next_id = highest_id; 368} 369