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