1 //===-- Breakpoint.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 #include "llvm/Support/Casting.h" 14 15 // Project includes 16 #include "lldb/Breakpoint/Breakpoint.h" 17 #include "lldb/Breakpoint/BreakpointLocation.h" 18 #include "lldb/Breakpoint/BreakpointLocationCollection.h" 19 #include "lldb/Breakpoint/BreakpointResolver.h" 20 #include "lldb/Breakpoint/BreakpointResolverFileLine.h" 21 #include "lldb/Core/Address.h" 22 #include "lldb/Core/Log.h" 23 #include "lldb/Core/Module.h" 24 #include "lldb/Core/ModuleList.h" 25 #include "lldb/Core/SearchFilter.h" 26 #include "lldb/Core/Section.h" 27 #include "lldb/Core/Stream.h" 28 #include "lldb/Core/StreamString.h" 29 #include "lldb/Symbol/CompileUnit.h" 30 #include "lldb/Symbol/Function.h" 31 #include "lldb/Symbol/SymbolContext.h" 32 #include "lldb/Target/Target.h" 33 #include "lldb/Target/ThreadSpec.h" 34 35 using namespace lldb; 36 using namespace lldb_private; 37 using namespace llvm; 38 39 const ConstString &Breakpoint::GetEventIdentifier() { 40 static ConstString g_identifier("event-identifier.breakpoint.changed"); 41 return g_identifier; 42 } 43 44 //---------------------------------------------------------------------- 45 // Breakpoint constructor 46 //---------------------------------------------------------------------- 47 Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, 48 BreakpointResolverSP &resolver_sp, bool hardware, 49 bool resolve_indirect_symbols) 50 : m_being_created(true), m_hardware(hardware), m_target(target), 51 m_filter_sp(filter_sp), m_resolver_sp(resolver_sp), m_options(), 52 m_locations(*this), m_resolve_indirect_symbols(resolve_indirect_symbols), 53 m_hit_count(0) { 54 m_being_created = false; 55 } 56 57 Breakpoint::Breakpoint(Target &new_target, Breakpoint &source_bp) 58 : m_being_created(true), m_hardware(source_bp.m_hardware), 59 m_target(new_target), m_name_list(source_bp.m_name_list), 60 m_options(source_bp.m_options), m_locations(*this), 61 m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols), 62 m_hit_count(0) { 63 // Now go through and copy the filter & resolver: 64 m_resolver_sp = source_bp.m_resolver_sp->CopyForBreakpoint(*this); 65 m_filter_sp = source_bp.m_filter_sp->CopyForBreakpoint(*this); 66 } 67 68 //---------------------------------------------------------------------- 69 // Destructor 70 //---------------------------------------------------------------------- 71 Breakpoint::~Breakpoint() = default; 72 73 const lldb::TargetSP Breakpoint::GetTargetSP() { 74 return m_target.shared_from_this(); 75 } 76 77 bool Breakpoint::IsInternal() const { return LLDB_BREAK_ID_IS_INTERNAL(m_bid); } 78 79 BreakpointLocationSP Breakpoint::AddLocation(const Address &addr, 80 bool *new_location) { 81 return m_locations.AddLocation(addr, m_resolve_indirect_symbols, 82 new_location); 83 } 84 85 BreakpointLocationSP Breakpoint::FindLocationByAddress(const Address &addr) { 86 return m_locations.FindByAddress(addr); 87 } 88 89 break_id_t Breakpoint::FindLocationIDByAddress(const Address &addr) { 90 return m_locations.FindIDByAddress(addr); 91 } 92 93 BreakpointLocationSP Breakpoint::FindLocationByID(break_id_t bp_loc_id) { 94 return m_locations.FindByID(bp_loc_id); 95 } 96 97 BreakpointLocationSP Breakpoint::GetLocationAtIndex(size_t index) { 98 return m_locations.GetByIndex(index); 99 } 100 101 void Breakpoint::RemoveInvalidLocations(const ArchSpec &arch) { 102 m_locations.RemoveInvalidLocations(arch); 103 } 104 105 // For each of the overall options we need to decide how they propagate to 106 // the location options. This will determine the precedence of options on 107 // the breakpoint vs. its locations. 108 109 // Disable at the breakpoint level should override the location settings. 110 // That way you can conveniently turn off a whole breakpoint without messing 111 // up the individual settings. 112 113 void Breakpoint::SetEnabled(bool enable) { 114 if (enable == m_options.IsEnabled()) 115 return; 116 117 m_options.SetEnabled(enable); 118 if (enable) 119 m_locations.ResolveAllBreakpointSites(); 120 else 121 m_locations.ClearAllBreakpointSites(); 122 123 SendBreakpointChangedEvent(enable ? eBreakpointEventTypeEnabled 124 : eBreakpointEventTypeDisabled); 125 } 126 127 bool Breakpoint::IsEnabled() { return m_options.IsEnabled(); } 128 129 void Breakpoint::SetIgnoreCount(uint32_t n) { 130 if (m_options.GetIgnoreCount() == n) 131 return; 132 133 m_options.SetIgnoreCount(n); 134 SendBreakpointChangedEvent(eBreakpointEventTypeIgnoreChanged); 135 } 136 137 void Breakpoint::DecrementIgnoreCount() { 138 uint32_t ignore = m_options.GetIgnoreCount(); 139 if (ignore != 0) 140 m_options.SetIgnoreCount(ignore - 1); 141 } 142 143 uint32_t Breakpoint::GetIgnoreCount() const { 144 return m_options.GetIgnoreCount(); 145 } 146 147 bool Breakpoint::IgnoreCountShouldStop() { 148 uint32_t ignore = GetIgnoreCount(); 149 if (ignore != 0) { 150 // When we get here we know the location that caused the stop doesn't have 151 // an ignore count, 152 // since by contract we call it first... So we don't have to find & 153 // decrement it, we only have 154 // to decrement our own ignore count. 155 DecrementIgnoreCount(); 156 return false; 157 } else 158 return true; 159 } 160 161 uint32_t Breakpoint::GetHitCount() const { return m_hit_count; } 162 163 bool Breakpoint::IsOneShot() const { return m_options.IsOneShot(); } 164 165 void Breakpoint::SetOneShot(bool one_shot) { m_options.SetOneShot(one_shot); } 166 167 void Breakpoint::SetThreadID(lldb::tid_t thread_id) { 168 if (m_options.GetThreadSpec()->GetTID() == thread_id) 169 return; 170 171 m_options.GetThreadSpec()->SetTID(thread_id); 172 SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged); 173 } 174 175 lldb::tid_t Breakpoint::GetThreadID() const { 176 if (m_options.GetThreadSpecNoCreate() == nullptr) 177 return LLDB_INVALID_THREAD_ID; 178 else 179 return m_options.GetThreadSpecNoCreate()->GetTID(); 180 } 181 182 void Breakpoint::SetThreadIndex(uint32_t index) { 183 if (m_options.GetThreadSpec()->GetIndex() == index) 184 return; 185 186 m_options.GetThreadSpec()->SetIndex(index); 187 SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged); 188 } 189 190 uint32_t Breakpoint::GetThreadIndex() const { 191 if (m_options.GetThreadSpecNoCreate() == nullptr) 192 return 0; 193 else 194 return m_options.GetThreadSpecNoCreate()->GetIndex(); 195 } 196 197 void Breakpoint::SetThreadName(const char *thread_name) { 198 if (m_options.GetThreadSpec()->GetName() != nullptr && 199 ::strcmp(m_options.GetThreadSpec()->GetName(), thread_name) == 0) 200 return; 201 202 m_options.GetThreadSpec()->SetName(thread_name); 203 SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged); 204 } 205 206 const char *Breakpoint::GetThreadName() const { 207 if (m_options.GetThreadSpecNoCreate() == nullptr) 208 return nullptr; 209 else 210 return m_options.GetThreadSpecNoCreate()->GetName(); 211 } 212 213 void Breakpoint::SetQueueName(const char *queue_name) { 214 if (m_options.GetThreadSpec()->GetQueueName() != nullptr && 215 ::strcmp(m_options.GetThreadSpec()->GetQueueName(), queue_name) == 0) 216 return; 217 218 m_options.GetThreadSpec()->SetQueueName(queue_name); 219 SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged); 220 } 221 222 const char *Breakpoint::GetQueueName() const { 223 if (m_options.GetThreadSpecNoCreate() == nullptr) 224 return nullptr; 225 else 226 return m_options.GetThreadSpecNoCreate()->GetQueueName(); 227 } 228 229 void Breakpoint::SetCondition(const char *condition) { 230 m_options.SetCondition(condition); 231 SendBreakpointChangedEvent(eBreakpointEventTypeConditionChanged); 232 } 233 234 const char *Breakpoint::GetConditionText() const { 235 return m_options.GetConditionText(); 236 } 237 238 // This function is used when "baton" doesn't need to be freed 239 void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton, 240 bool is_synchronous) { 241 // The default "Baton" class will keep a copy of "baton" and won't free 242 // or delete it when it goes goes out of scope. 243 m_options.SetCallback(callback, BatonSP(new Baton(baton)), is_synchronous); 244 245 SendBreakpointChangedEvent(eBreakpointEventTypeCommandChanged); 246 } 247 248 // This function is used when a baton needs to be freed and therefore is 249 // contained in a "Baton" subclass. 250 void Breakpoint::SetCallback(BreakpointHitCallback callback, 251 const BatonSP &callback_baton_sp, 252 bool is_synchronous) { 253 m_options.SetCallback(callback, callback_baton_sp, is_synchronous); 254 } 255 256 void Breakpoint::ClearCallback() { m_options.ClearCallback(); } 257 258 bool Breakpoint::InvokeCallback(StoppointCallbackContext *context, 259 break_id_t bp_loc_id) { 260 return m_options.InvokeCallback(context, GetID(), bp_loc_id); 261 } 262 263 BreakpointOptions *Breakpoint::GetOptions() { return &m_options; } 264 265 void Breakpoint::ResolveBreakpoint() { 266 if (m_resolver_sp) 267 m_resolver_sp->ResolveBreakpoint(*m_filter_sp); 268 } 269 270 void Breakpoint::ResolveBreakpointInModules( 271 ModuleList &module_list, BreakpointLocationCollection &new_locations) { 272 m_locations.StartRecordingNewLocations(new_locations); 273 274 m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list); 275 276 m_locations.StopRecordingNewLocations(); 277 } 278 279 void Breakpoint::ResolveBreakpointInModules(ModuleList &module_list, 280 bool send_event) { 281 if (m_resolver_sp) { 282 // If this is not an internal breakpoint, set up to record the new 283 // locations, then dispatch 284 // an event with the new locations. 285 if (!IsInternal() && send_event) { 286 BreakpointEventData *new_locations_event = new BreakpointEventData( 287 eBreakpointEventTypeLocationsAdded, shared_from_this()); 288 289 ResolveBreakpointInModules( 290 module_list, new_locations_event->GetBreakpointLocationCollection()); 291 292 if (new_locations_event->GetBreakpointLocationCollection().GetSize() != 293 0) { 294 SendBreakpointChangedEvent(new_locations_event); 295 } else 296 delete new_locations_event; 297 } else { 298 m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list); 299 } 300 } 301 } 302 303 void Breakpoint::ClearAllBreakpointSites() { 304 m_locations.ClearAllBreakpointSites(); 305 } 306 307 //---------------------------------------------------------------------- 308 // ModulesChanged: Pass in a list of new modules, and 309 //---------------------------------------------------------------------- 310 311 void Breakpoint::ModulesChanged(ModuleList &module_list, bool load, 312 bool delete_locations) { 313 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 314 if (log) 315 log->Printf("Breakpoint::ModulesChanged: num_modules: %zu load: %i " 316 "delete_locations: %i\n", 317 module_list.GetSize(), load, delete_locations); 318 319 std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); 320 if (load) { 321 // The logic for handling new modules is: 322 // 1) If the filter rejects this module, then skip it. 323 // 2) Run through the current location list and if there are any locations 324 // for that module, we mark the module as "seen" and we don't try to 325 // re-resolve 326 // breakpoint locations for that module. 327 // However, we do add breakpoint sites to these locations if needed. 328 // 3) If we don't see this module in our breakpoint location list, call 329 // ResolveInModules. 330 331 ModuleList new_modules; // We'll stuff the "unseen" modules in this list, 332 // and then resolve 333 // them after the locations pass. Have to do it this way because 334 // resolving breakpoints will add new locations potentially. 335 336 for (ModuleSP module_sp : module_list.ModulesNoLocking()) { 337 bool seen = false; 338 if (!m_filter_sp->ModulePasses(module_sp)) 339 continue; 340 341 for (BreakpointLocationSP break_loc_sp : 342 m_locations.BreakpointLocations()) { 343 if (!break_loc_sp->IsEnabled()) 344 continue; 345 SectionSP section_sp(break_loc_sp->GetAddress().GetSection()); 346 if (!section_sp || section_sp->GetModule() == module_sp) { 347 if (!seen) 348 seen = true; 349 350 if (!break_loc_sp->ResolveBreakpointSite()) { 351 if (log) 352 log->Printf("Warning: could not set breakpoint site for " 353 "breakpoint location %d of breakpoint %d.\n", 354 break_loc_sp->GetID(), GetID()); 355 } 356 } 357 } 358 359 if (!seen) 360 new_modules.AppendIfNeeded(module_sp); 361 } 362 363 if (new_modules.GetSize() > 0) { 364 ResolveBreakpointInModules(new_modules); 365 } 366 } else { 367 // Go through the currently set locations and if any have breakpoints in 368 // the module list, then remove their breakpoint sites, and their locations 369 // if asked to. 370 371 BreakpointEventData *removed_locations_event; 372 if (!IsInternal()) 373 removed_locations_event = new BreakpointEventData( 374 eBreakpointEventTypeLocationsRemoved, shared_from_this()); 375 else 376 removed_locations_event = nullptr; 377 378 size_t num_modules = module_list.GetSize(); 379 for (size_t i = 0; i < num_modules; i++) { 380 ModuleSP module_sp(module_list.GetModuleAtIndexUnlocked(i)); 381 if (m_filter_sp->ModulePasses(module_sp)) { 382 size_t loc_idx = 0; 383 size_t num_locations = m_locations.GetSize(); 384 BreakpointLocationCollection locations_to_remove; 385 for (loc_idx = 0; loc_idx < num_locations; loc_idx++) { 386 BreakpointLocationSP break_loc_sp(m_locations.GetByIndex(loc_idx)); 387 SectionSP section_sp(break_loc_sp->GetAddress().GetSection()); 388 if (section_sp && section_sp->GetModule() == module_sp) { 389 // Remove this breakpoint since the shared library is 390 // unloaded, but keep the breakpoint location around 391 // so we always get complete hit count and breakpoint 392 // lifetime info 393 break_loc_sp->ClearBreakpointSite(); 394 if (removed_locations_event) { 395 removed_locations_event->GetBreakpointLocationCollection().Add( 396 break_loc_sp); 397 } 398 if (delete_locations) 399 locations_to_remove.Add(break_loc_sp); 400 } 401 } 402 403 if (delete_locations) { 404 size_t num_locations_to_remove = locations_to_remove.GetSize(); 405 for (loc_idx = 0; loc_idx < num_locations_to_remove; loc_idx++) 406 m_locations.RemoveLocation(locations_to_remove.GetByIndex(loc_idx)); 407 } 408 } 409 } 410 SendBreakpointChangedEvent(removed_locations_event); 411 } 412 } 413 414 namespace { 415 static bool SymbolContextsMightBeEquivalent(SymbolContext &old_sc, 416 SymbolContext &new_sc) { 417 bool equivalent_scs = false; 418 419 if (old_sc.module_sp.get() == new_sc.module_sp.get()) { 420 // If these come from the same module, we can directly compare the pointers: 421 if (old_sc.comp_unit && new_sc.comp_unit && 422 (old_sc.comp_unit == new_sc.comp_unit)) { 423 if (old_sc.function && new_sc.function && 424 (old_sc.function == new_sc.function)) { 425 equivalent_scs = true; 426 } 427 } else if (old_sc.symbol && new_sc.symbol && 428 (old_sc.symbol == new_sc.symbol)) { 429 equivalent_scs = true; 430 } 431 } else { 432 // Otherwise we will compare by name... 433 if (old_sc.comp_unit && new_sc.comp_unit) { 434 if (FileSpec::Equal(*old_sc.comp_unit, *new_sc.comp_unit, true)) { 435 // Now check the functions: 436 if (old_sc.function && new_sc.function && 437 (old_sc.function->GetName() == new_sc.function->GetName())) { 438 equivalent_scs = true; 439 } 440 } 441 } else if (old_sc.symbol && new_sc.symbol) { 442 if (Mangled::Compare(old_sc.symbol->GetMangled(), 443 new_sc.symbol->GetMangled()) == 0) { 444 equivalent_scs = true; 445 } 446 } 447 } 448 return equivalent_scs; 449 } 450 } // anonymous namespace 451 452 void Breakpoint::ModuleReplaced(ModuleSP old_module_sp, 453 ModuleSP new_module_sp) { 454 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); 455 if (log) 456 log->Printf("Breakpoint::ModulesReplaced for %s\n", 457 old_module_sp->GetSpecificationDescription().c_str()); 458 // First find all the locations that are in the old module 459 460 BreakpointLocationCollection old_break_locs; 461 for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations()) { 462 SectionSP section_sp = break_loc_sp->GetAddress().GetSection(); 463 if (section_sp && section_sp->GetModule() == old_module_sp) { 464 old_break_locs.Add(break_loc_sp); 465 } 466 } 467 468 size_t num_old_locations = old_break_locs.GetSize(); 469 470 if (num_old_locations == 0) { 471 // There were no locations in the old module, so we just need to check if 472 // there were any in the new module. 473 ModuleList temp_list; 474 temp_list.Append(new_module_sp); 475 ResolveBreakpointInModules(temp_list); 476 } else { 477 // First search the new module for locations. 478 // Then compare this with the old list, copy over locations that "look the 479 // same" 480 // Then delete the old locations. 481 // Finally remember to post the creation event. 482 // 483 // Two locations are the same if they have the same comp unit & function (by 484 // name) and there are the same number 485 // of locations in the old function as in the new one. 486 487 ModuleList temp_list; 488 temp_list.Append(new_module_sp); 489 BreakpointLocationCollection new_break_locs; 490 ResolveBreakpointInModules(temp_list, new_break_locs); 491 BreakpointLocationCollection locations_to_remove; 492 BreakpointLocationCollection locations_to_announce; 493 494 size_t num_new_locations = new_break_locs.GetSize(); 495 496 if (num_new_locations > 0) { 497 // Break out the case of one location -> one location since that's the 498 // most common one, and there's no need 499 // to build up the structures needed for the merge in that case. 500 if (num_new_locations == 1 && num_old_locations == 1) { 501 bool equivalent_locations = false; 502 SymbolContext old_sc, new_sc; 503 // The only way the old and new location can be equivalent is if they 504 // have the same amount of information: 505 BreakpointLocationSP old_loc_sp = old_break_locs.GetByIndex(0); 506 BreakpointLocationSP new_loc_sp = new_break_locs.GetByIndex(0); 507 508 if (old_loc_sp->GetAddress().CalculateSymbolContext(&old_sc) == 509 new_loc_sp->GetAddress().CalculateSymbolContext(&new_sc)) { 510 equivalent_locations = 511 SymbolContextsMightBeEquivalent(old_sc, new_sc); 512 } 513 514 if (equivalent_locations) { 515 m_locations.SwapLocation(old_loc_sp, new_loc_sp); 516 } else { 517 locations_to_remove.Add(old_loc_sp); 518 locations_to_announce.Add(new_loc_sp); 519 } 520 } else { 521 // We don't want to have to keep computing the SymbolContexts for these 522 // addresses over and over, 523 // so lets get them up front: 524 525 typedef std::map<lldb::break_id_t, SymbolContext> IDToSCMap; 526 IDToSCMap old_sc_map; 527 for (size_t idx = 0; idx < num_old_locations; idx++) { 528 SymbolContext sc; 529 BreakpointLocationSP bp_loc_sp = old_break_locs.GetByIndex(idx); 530 lldb::break_id_t loc_id = bp_loc_sp->GetID(); 531 bp_loc_sp->GetAddress().CalculateSymbolContext(&old_sc_map[loc_id]); 532 } 533 534 std::map<lldb::break_id_t, SymbolContext> new_sc_map; 535 for (size_t idx = 0; idx < num_new_locations; idx++) { 536 SymbolContext sc; 537 BreakpointLocationSP bp_loc_sp = new_break_locs.GetByIndex(idx); 538 lldb::break_id_t loc_id = bp_loc_sp->GetID(); 539 bp_loc_sp->GetAddress().CalculateSymbolContext(&new_sc_map[loc_id]); 540 } 541 // Take an element from the old Symbol Contexts 542 while (old_sc_map.size() > 0) { 543 lldb::break_id_t old_id = old_sc_map.begin()->first; 544 SymbolContext &old_sc = old_sc_map.begin()->second; 545 546 // Count the number of entries equivalent to this SC for the old list: 547 std::vector<lldb::break_id_t> old_id_vec; 548 old_id_vec.push_back(old_id); 549 550 IDToSCMap::iterator tmp_iter; 551 for (tmp_iter = ++old_sc_map.begin(); tmp_iter != old_sc_map.end(); 552 tmp_iter++) { 553 if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second)) 554 old_id_vec.push_back(tmp_iter->first); 555 } 556 557 // Now find all the equivalent locations in the new list. 558 std::vector<lldb::break_id_t> new_id_vec; 559 for (tmp_iter = new_sc_map.begin(); tmp_iter != new_sc_map.end(); 560 tmp_iter++) { 561 if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second)) 562 new_id_vec.push_back(tmp_iter->first); 563 } 564 565 // Alright, if we have the same number of potentially equivalent 566 // locations in the old 567 // and new modules, we'll just map them one to one in ascending ID 568 // order (assuming the 569 // resolver's order would match the equivalent ones. 570 // Otherwise, we'll dump all the old ones, and just take the new ones, 571 // erasing the elements 572 // from both maps as we go. 573 574 if (old_id_vec.size() == new_id_vec.size()) { 575 sort(old_id_vec.begin(), old_id_vec.end()); 576 sort(new_id_vec.begin(), new_id_vec.end()); 577 size_t num_elements = old_id_vec.size(); 578 for (size_t idx = 0; idx < num_elements; idx++) { 579 BreakpointLocationSP old_loc_sp = 580 old_break_locs.FindByIDPair(GetID(), old_id_vec[idx]); 581 BreakpointLocationSP new_loc_sp = 582 new_break_locs.FindByIDPair(GetID(), new_id_vec[idx]); 583 m_locations.SwapLocation(old_loc_sp, new_loc_sp); 584 old_sc_map.erase(old_id_vec[idx]); 585 new_sc_map.erase(new_id_vec[idx]); 586 } 587 } else { 588 for (lldb::break_id_t old_id : old_id_vec) { 589 locations_to_remove.Add( 590 old_break_locs.FindByIDPair(GetID(), old_id)); 591 old_sc_map.erase(old_id); 592 } 593 for (lldb::break_id_t new_id : new_id_vec) { 594 locations_to_announce.Add( 595 new_break_locs.FindByIDPair(GetID(), new_id)); 596 new_sc_map.erase(new_id); 597 } 598 } 599 } 600 } 601 } 602 603 // Now remove the remaining old locations, and cons up a removed locations 604 // event. 605 // Note, we don't put the new locations that were swapped with an old 606 // location on the locations_to_remove 607 // list, so we don't need to worry about telling the world about removing a 608 // location we didn't tell them 609 // about adding. 610 611 BreakpointEventData *locations_event; 612 if (!IsInternal()) 613 locations_event = new BreakpointEventData( 614 eBreakpointEventTypeLocationsRemoved, shared_from_this()); 615 else 616 locations_event = nullptr; 617 618 for (BreakpointLocationSP loc_sp : 619 locations_to_remove.BreakpointLocations()) { 620 m_locations.RemoveLocation(loc_sp); 621 if (locations_event) 622 locations_event->GetBreakpointLocationCollection().Add(loc_sp); 623 } 624 SendBreakpointChangedEvent(locations_event); 625 626 // And announce the new ones. 627 628 if (!IsInternal()) { 629 locations_event = new BreakpointEventData( 630 eBreakpointEventTypeLocationsAdded, shared_from_this()); 631 for (BreakpointLocationSP loc_sp : 632 locations_to_announce.BreakpointLocations()) 633 locations_event->GetBreakpointLocationCollection().Add(loc_sp); 634 635 SendBreakpointChangedEvent(locations_event); 636 } 637 m_locations.Compact(); 638 } 639 } 640 641 void Breakpoint::Dump(Stream *) {} 642 643 size_t Breakpoint::GetNumResolvedLocations() const { 644 // Return the number of breakpoints that are actually resolved and set 645 // down in the inferior process. 646 return m_locations.GetNumResolvedLocations(); 647 } 648 649 size_t Breakpoint::GetNumLocations() const { return m_locations.GetSize(); } 650 651 bool Breakpoint::AddName(const char *new_name, Error &error) { 652 if (!new_name) 653 return false; 654 if (!BreakpointID::StringIsBreakpointName(new_name, error)) { 655 error.SetErrorStringWithFormat("input name \"%s\" not a breakpoint name.", 656 new_name); 657 return false; 658 } 659 if (!error.Success()) 660 return false; 661 662 m_name_list.insert(new_name); 663 return true; 664 } 665 666 void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level, 667 bool show_locations) { 668 assert(s != nullptr); 669 670 if (!m_kind_description.empty()) { 671 if (level == eDescriptionLevelBrief) { 672 s->PutCString(GetBreakpointKind()); 673 return; 674 } else 675 s->Printf("Kind: %s\n", GetBreakpointKind()); 676 } 677 678 const size_t num_locations = GetNumLocations(); 679 const size_t num_resolved_locations = GetNumResolvedLocations(); 680 681 // They just made the breakpoint, they don't need to be told HOW they made 682 // it... 683 // Also, we'll print the breakpoint number differently depending on whether 684 // there is 1 or more locations. 685 if (level != eDescriptionLevelInitial) { 686 s->Printf("%i: ", GetID()); 687 GetResolverDescription(s); 688 GetFilterDescription(s); 689 } 690 691 switch (level) { 692 case lldb::eDescriptionLevelBrief: 693 case lldb::eDescriptionLevelFull: 694 if (num_locations > 0) { 695 s->Printf(", locations = %" PRIu64, (uint64_t)num_locations); 696 if (num_resolved_locations > 0) 697 s->Printf(", resolved = %" PRIu64 ", hit count = %d", 698 (uint64_t)num_resolved_locations, GetHitCount()); 699 } else { 700 // Don't print the pending notification for exception resolvers since we 701 // don't generally 702 // know how to set them until the target is run. 703 if (m_resolver_sp->getResolverID() != 704 BreakpointResolver::ExceptionResolver) 705 s->Printf(", locations = 0 (pending)"); 706 } 707 708 GetOptions()->GetDescription(s, level); 709 710 if (m_precondition_sp) 711 m_precondition_sp->GetDescription(*s, level); 712 713 if (level == lldb::eDescriptionLevelFull) { 714 if (!m_name_list.empty()) { 715 s->EOL(); 716 s->Indent(); 717 s->Printf("Names:"); 718 s->EOL(); 719 s->IndentMore(); 720 for (std::string name : m_name_list) { 721 s->Indent(); 722 s->Printf("%s\n", name.c_str()); 723 } 724 s->IndentLess(); 725 } 726 s->IndentLess(); 727 s->EOL(); 728 } 729 break; 730 731 case lldb::eDescriptionLevelInitial: 732 s->Printf("Breakpoint %i: ", GetID()); 733 if (num_locations == 0) { 734 s->Printf("no locations (pending)."); 735 } else if (num_locations == 1 && !show_locations) { 736 // There is only one location, so we'll just print that location 737 // information. 738 GetLocationAtIndex(0)->GetDescription(s, level); 739 } else { 740 s->Printf("%" PRIu64 " locations.", static_cast<uint64_t>(num_locations)); 741 } 742 s->EOL(); 743 break; 744 745 case lldb::eDescriptionLevelVerbose: 746 // Verbose mode does a debug dump of the breakpoint 747 Dump(s); 748 s->EOL(); 749 // s->Indent(); 750 GetOptions()->GetDescription(s, level); 751 break; 752 753 default: 754 break; 755 } 756 757 // The brief description is just the location name (1.2 or whatever). That's 758 // pointless to 759 // show in the breakpoint's description, so suppress it. 760 if (show_locations && level != lldb::eDescriptionLevelBrief) { 761 s->IndentMore(); 762 for (size_t i = 0; i < num_locations; ++i) { 763 BreakpointLocation *loc = GetLocationAtIndex(i).get(); 764 loc->GetDescription(s, level); 765 s->EOL(); 766 } 767 s->IndentLess(); 768 } 769 } 770 771 void Breakpoint::GetResolverDescription(Stream *s) { 772 if (m_resolver_sp) 773 m_resolver_sp->GetDescription(s); 774 } 775 776 bool Breakpoint::GetMatchingFileLine(const ConstString &filename, 777 uint32_t line_number, 778 BreakpointLocationCollection &loc_coll) { 779 // TODO: To be correct, this method needs to fill the breakpoint location 780 // collection 781 // with the location IDs which match the filename and line_number. 782 // 783 784 if (m_resolver_sp) { 785 BreakpointResolverFileLine *resolverFileLine = 786 dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get()); 787 if (resolverFileLine && 788 resolverFileLine->m_file_spec.GetFilename() == filename && 789 resolverFileLine->m_line_number == line_number) { 790 return true; 791 } 792 } 793 return false; 794 } 795 796 void Breakpoint::GetFilterDescription(Stream *s) { 797 m_filter_sp->GetDescription(s); 798 } 799 800 bool Breakpoint::EvaluatePrecondition(StoppointCallbackContext &context) { 801 if (!m_precondition_sp) 802 return true; 803 804 return m_precondition_sp->EvaluatePrecondition(context); 805 } 806 807 bool Breakpoint::BreakpointPrecondition::EvaluatePrecondition( 808 StoppointCallbackContext &context) { 809 return true; 810 } 811 812 void Breakpoint::BreakpointPrecondition::GetDescription( 813 Stream &stream, lldb::DescriptionLevel level) {} 814 815 Error Breakpoint::BreakpointPrecondition::ConfigurePrecondition(Args &options) { 816 Error error; 817 error.SetErrorString("Base breakpoint precondition has no options."); 818 return error; 819 } 820 821 void Breakpoint::SendBreakpointChangedEvent( 822 lldb::BreakpointEventType eventKind) { 823 if (!m_being_created && !IsInternal() && 824 GetTarget().EventTypeHasListeners( 825 Target::eBroadcastBitBreakpointChanged)) { 826 BreakpointEventData *data = 827 new Breakpoint::BreakpointEventData(eventKind, shared_from_this()); 828 829 GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, data); 830 } 831 } 832 833 void Breakpoint::SendBreakpointChangedEvent(BreakpointEventData *data) { 834 if (data == nullptr) 835 return; 836 837 if (!m_being_created && !IsInternal() && 838 GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) 839 GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, data); 840 else 841 delete data; 842 } 843 844 Breakpoint::BreakpointEventData::BreakpointEventData( 845 BreakpointEventType sub_type, const BreakpointSP &new_breakpoint_sp) 846 : EventData(), m_breakpoint_event(sub_type), 847 m_new_breakpoint_sp(new_breakpoint_sp) {} 848 849 Breakpoint::BreakpointEventData::~BreakpointEventData() = default; 850 851 const ConstString &Breakpoint::BreakpointEventData::GetFlavorString() { 852 static ConstString g_flavor("Breakpoint::BreakpointEventData"); 853 return g_flavor; 854 } 855 856 const ConstString &Breakpoint::BreakpointEventData::GetFlavor() const { 857 return BreakpointEventData::GetFlavorString(); 858 } 859 860 BreakpointSP &Breakpoint::BreakpointEventData::GetBreakpoint() { 861 return m_new_breakpoint_sp; 862 } 863 864 BreakpointEventType 865 Breakpoint::BreakpointEventData::GetBreakpointEventType() const { 866 return m_breakpoint_event; 867 } 868 869 void Breakpoint::BreakpointEventData::Dump(Stream *s) const {} 870 871 const Breakpoint::BreakpointEventData * 872 Breakpoint::BreakpointEventData::GetEventDataFromEvent(const Event *event) { 873 if (event) { 874 const EventData *event_data = event->GetData(); 875 if (event_data && 876 event_data->GetFlavor() == BreakpointEventData::GetFlavorString()) 877 return static_cast<const BreakpointEventData *>(event->GetData()); 878 } 879 return nullptr; 880 } 881 882 BreakpointEventType 883 Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( 884 const EventSP &event_sp) { 885 const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get()); 886 887 if (data == nullptr) 888 return eBreakpointEventTypeInvalidType; 889 else 890 return data->GetBreakpointEventType(); 891 } 892 893 BreakpointSP Breakpoint::BreakpointEventData::GetBreakpointFromEvent( 894 const EventSP &event_sp) { 895 BreakpointSP bp_sp; 896 897 const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get()); 898 if (data) 899 bp_sp = data->m_new_breakpoint_sp; 900 901 return bp_sp; 902 } 903 904 size_t Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( 905 const EventSP &event_sp) { 906 const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get()); 907 if (data) 908 return data->m_locations.GetSize(); 909 910 return 0; 911 } 912 913 lldb::BreakpointLocationSP 914 Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent( 915 const lldb::EventSP &event_sp, uint32_t bp_loc_idx) { 916 lldb::BreakpointLocationSP bp_loc_sp; 917 918 const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get()); 919 if (data) { 920 bp_loc_sp = data->m_locations.GetByIndex(bp_loc_idx); 921 } 922 923 return bp_loc_sp; 924 } 925