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