1 //===-- BreakpointLocation.cpp --------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Breakpoint/BreakpointLocation.h" 10 #include "lldb/Breakpoint/BreakpointID.h" 11 #include "lldb/Breakpoint/StoppointCallbackContext.h" 12 #include "lldb/Core/Debugger.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/ValueObject.h" 15 #include "lldb/Expression/DiagnosticManager.h" 16 #include "lldb/Expression/ExpressionVariable.h" 17 #include "lldb/Expression/UserExpression.h" 18 #include "lldb/Symbol/CompileUnit.h" 19 #include "lldb/Symbol/Symbol.h" 20 #include "lldb/Symbol/TypeSystem.h" 21 #include "lldb/Target/Process.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Target/Thread.h" 24 #include "lldb/Target/ThreadSpec.h" 25 #include "lldb/Utility/LLDBLog.h" 26 #include "lldb/Utility/Log.h" 27 #include "lldb/Utility/StreamString.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner, 33 const Address &addr, lldb::tid_t tid, 34 bool hardware, bool check_for_resolver) 35 : m_should_resolve_indirect_functions(false), m_is_reexported(false), 36 m_is_indirect(false), m_address(addr), m_owner(owner), 37 m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() { 38 if (check_for_resolver) { 39 Symbol *symbol = m_address.CalculateSymbolContextSymbol(); 40 if (symbol && symbol->IsIndirect()) { 41 SetShouldResolveIndirectFunctions(true); 42 } 43 } 44 45 SetThreadIDInternal(tid); 46 } 47 48 BreakpointLocation::~BreakpointLocation() { ClearBreakpointSite(); } 49 50 lldb::addr_t BreakpointLocation::GetLoadAddress() const { 51 return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()); 52 } 53 54 const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind( 55 BreakpointOptions::OptionKind kind) const { 56 if (m_options_up && m_options_up->IsOptionSet(kind)) 57 return *m_options_up; 58 else 59 return m_owner.GetOptions(); 60 } 61 62 Address &BreakpointLocation::GetAddress() { return m_address; } 63 64 Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; } 65 66 Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); } 67 68 bool BreakpointLocation::IsEnabled() const { 69 if (!m_owner.IsEnabled()) 70 return false; 71 else if (m_options_up != nullptr) 72 return m_options_up->IsEnabled(); 73 else 74 return true; 75 } 76 77 void BreakpointLocation::SetEnabled(bool enabled) { 78 GetLocationOptions().SetEnabled(enabled); 79 if (enabled) { 80 ResolveBreakpointSite(); 81 } else { 82 ClearBreakpointSite(); 83 } 84 SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled 85 : eBreakpointEventTypeDisabled); 86 } 87 88 bool BreakpointLocation::IsAutoContinue() const { 89 if (m_options_up && 90 m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue)) 91 return m_options_up->IsAutoContinue(); 92 else 93 return m_owner.IsAutoContinue(); 94 } 95 96 void BreakpointLocation::SetAutoContinue(bool auto_continue) { 97 GetLocationOptions().SetAutoContinue(auto_continue); 98 SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged); 99 } 100 101 void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) { 102 SetThreadIDInternal(thread_id); 103 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged); 104 } 105 106 lldb::tid_t BreakpointLocation::GetThreadID() { 107 const ThreadSpec *thread_spec = 108 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 109 .GetThreadSpecNoCreate(); 110 if (thread_spec) 111 return thread_spec->GetTID(); 112 else 113 return LLDB_INVALID_THREAD_ID; 114 } 115 116 void BreakpointLocation::SetThreadIndex(uint32_t index) { 117 if (index != 0) 118 GetLocationOptions().GetThreadSpec()->SetIndex(index); 119 else { 120 // If we're resetting this to an invalid thread id, then don't make an 121 // options pointer just to do that. 122 if (m_options_up != nullptr) 123 m_options_up->GetThreadSpec()->SetIndex(index); 124 } 125 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged); 126 } 127 128 uint32_t BreakpointLocation::GetThreadIndex() const { 129 const ThreadSpec *thread_spec = 130 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 131 .GetThreadSpecNoCreate(); 132 if (thread_spec) 133 return thread_spec->GetIndex(); 134 else 135 return 0; 136 } 137 138 void BreakpointLocation::SetThreadName(const char *thread_name) { 139 if (thread_name != nullptr) 140 GetLocationOptions().GetThreadSpec()->SetName(thread_name); 141 else { 142 // If we're resetting this to an invalid thread id, then don't make an 143 // options pointer just to do that. 144 if (m_options_up != nullptr) 145 m_options_up->GetThreadSpec()->SetName(thread_name); 146 } 147 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged); 148 } 149 150 const char *BreakpointLocation::GetThreadName() const { 151 const ThreadSpec *thread_spec = 152 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 153 .GetThreadSpecNoCreate(); 154 if (thread_spec) 155 return thread_spec->GetName(); 156 else 157 return nullptr; 158 } 159 160 void BreakpointLocation::SetQueueName(const char *queue_name) { 161 if (queue_name != nullptr) 162 GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name); 163 else { 164 // If we're resetting this to an invalid thread id, then don't make an 165 // options pointer just to do that. 166 if (m_options_up != nullptr) 167 m_options_up->GetThreadSpec()->SetQueueName(queue_name); 168 } 169 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged); 170 } 171 172 const char *BreakpointLocation::GetQueueName() const { 173 const ThreadSpec *thread_spec = 174 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 175 .GetThreadSpecNoCreate(); 176 if (thread_spec) 177 return thread_spec->GetQueueName(); 178 else 179 return nullptr; 180 } 181 182 bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) { 183 if (m_options_up != nullptr && m_options_up->HasCallback()) 184 return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID()); 185 else 186 return m_owner.InvokeCallback(context, GetID()); 187 } 188 189 bool BreakpointLocation::IsCallbackSynchronous() { 190 if (m_options_up != nullptr && m_options_up->HasCallback()) 191 return m_options_up->IsCallbackSynchronous(); 192 else 193 return m_owner.GetOptions().IsCallbackSynchronous(); 194 } 195 196 void BreakpointLocation::SetCallback(BreakpointHitCallback callback, 197 void *baton, bool is_synchronous) { 198 // The default "Baton" class will keep a copy of "baton" and won't free or 199 // delete it when it goes out of scope. 200 GetLocationOptions().SetCallback( 201 callback, std::make_shared<UntypedBaton>(baton), is_synchronous); 202 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged); 203 } 204 205 void BreakpointLocation::SetCallback(BreakpointHitCallback callback, 206 const BatonSP &baton_sp, 207 bool is_synchronous) { 208 GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous); 209 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged); 210 } 211 212 void BreakpointLocation::ClearCallback() { 213 GetLocationOptions().ClearCallback(); 214 } 215 216 void BreakpointLocation::SetCondition(const char *condition) { 217 GetLocationOptions().SetCondition(condition); 218 SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged); 219 } 220 221 const char *BreakpointLocation::GetConditionText(size_t *hash) const { 222 return GetOptionsSpecifyingKind(BreakpointOptions::eCondition) 223 .GetConditionText(hash); 224 } 225 226 bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, 227 Status &error) { 228 Log *log = GetLog(LLDBLog::Breakpoints); 229 230 std::lock_guard<std::mutex> guard(m_condition_mutex); 231 232 size_t condition_hash; 233 const char *condition_text = GetConditionText(&condition_hash); 234 235 if (!condition_text) { 236 m_user_expression_sp.reset(); 237 return false; 238 } 239 240 error.Clear(); 241 242 DiagnosticManager diagnostics; 243 244 if (condition_hash != m_condition_hash || !m_user_expression_sp || 245 !m_user_expression_sp->IsParseCacheable() || 246 !m_user_expression_sp->MatchesContext(exe_ctx)) { 247 LanguageType language = eLanguageTypeUnknown; 248 // See if we can figure out the language from the frame, otherwise use the 249 // default language: 250 CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit(); 251 if (comp_unit) 252 language = comp_unit->GetLanguage(); 253 254 m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage( 255 condition_text, llvm::StringRef(), language, Expression::eResultTypeAny, 256 EvaluateExpressionOptions(), nullptr, error)); 257 if (error.Fail()) { 258 LLDB_LOGF(log, "Error getting condition expression: %s.", 259 error.AsCString()); 260 m_user_expression_sp.reset(); 261 return true; 262 } 263 264 if (!m_user_expression_sp->Parse(diagnostics, exe_ctx, 265 eExecutionPolicyOnlyWhenNeeded, true, 266 false)) { 267 error.SetErrorStringWithFormat( 268 "Couldn't parse conditional expression:\n%s", 269 diagnostics.GetString().c_str()); 270 m_user_expression_sp.reset(); 271 return true; 272 } 273 274 m_condition_hash = condition_hash; 275 } 276 277 // We need to make sure the user sees any parse errors in their condition, so 278 // we'll hook the constructor errors up to the debugger's Async I/O. 279 280 ValueObjectSP result_value_sp; 281 282 EvaluateExpressionOptions options; 283 options.SetUnwindOnError(true); 284 options.SetIgnoreBreakpoints(true); 285 options.SetTryAllThreads(true); 286 options.SetSuppressPersistentResult( 287 true); // Don't generate a user variable for condition expressions. 288 289 Status expr_error; 290 291 diagnostics.Clear(); 292 293 ExpressionVariableSP result_variable_sp; 294 295 ExpressionResults result_code = m_user_expression_sp->Execute( 296 diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp); 297 298 bool ret; 299 300 if (result_code == eExpressionCompleted) { 301 if (!result_variable_sp) { 302 error.SetErrorString("Expression did not return a result"); 303 return false; 304 } 305 306 result_value_sp = result_variable_sp->GetValueObject(); 307 308 if (result_value_sp) { 309 ret = result_value_sp->IsLogicalTrue(error); 310 if (log) { 311 if (error.Success()) { 312 LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n", 313 ret ? "true" : "false"); 314 } else { 315 error.SetErrorString( 316 "Failed to get an integer result from the expression"); 317 ret = false; 318 } 319 } 320 } else { 321 ret = false; 322 error.SetErrorString("Failed to get any result from the expression"); 323 } 324 } else { 325 ret = false; 326 error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", 327 diagnostics.GetString().c_str()); 328 } 329 330 return ret; 331 } 332 333 uint32_t BreakpointLocation::GetIgnoreCount() const { 334 return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount) 335 .GetIgnoreCount(); 336 } 337 338 void BreakpointLocation::SetIgnoreCount(uint32_t n) { 339 GetLocationOptions().SetIgnoreCount(n); 340 SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged); 341 } 342 343 void BreakpointLocation::DecrementIgnoreCount() { 344 if (m_options_up != nullptr) { 345 uint32_t loc_ignore = m_options_up->GetIgnoreCount(); 346 if (loc_ignore != 0) 347 m_options_up->SetIgnoreCount(loc_ignore - 1); 348 } 349 } 350 351 bool BreakpointLocation::IgnoreCountShouldStop() { 352 uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount(); 353 uint32_t loc_ignore = 0; 354 if (m_options_up != nullptr) 355 loc_ignore = m_options_up->GetIgnoreCount(); 356 357 if (loc_ignore != 0 || owner_ignore != 0) { 358 m_owner.DecrementIgnoreCount(); 359 DecrementIgnoreCount(); // Have to decrement our owners' ignore count, 360 // since it won't get a chance to. 361 return false; 362 } 363 return true; 364 } 365 366 BreakpointOptions &BreakpointLocation::GetLocationOptions() { 367 // If we make the copy we don't copy the callbacks because that is 368 // potentially expensive and we don't want to do that for the simple case 369 // where someone is just disabling the location. 370 if (m_options_up == nullptr) 371 m_options_up = std::make_unique<BreakpointOptions>(false); 372 373 return *m_options_up; 374 } 375 376 bool BreakpointLocation::ValidForThisThread(Thread &thread) { 377 return thread.MatchesSpec( 378 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 379 .GetThreadSpecNoCreate()); 380 } 381 382 // RETURNS - true if we should stop at this breakpoint, false if we 383 // should continue. Note, we don't check the thread spec for the breakpoint 384 // here, since if the breakpoint is not for this thread, then the event won't 385 // even get reported, so the check is redundant. 386 387 bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) { 388 bool should_stop = true; 389 Log *log = GetLog(LLDBLog::Breakpoints); 390 391 // Do this first, if a location is disabled, it shouldn't increment its hit 392 // count. 393 if (!IsEnabled()) 394 return false; 395 396 // We only run synchronous callbacks in ShouldStop: 397 context->is_synchronous = true; 398 should_stop = InvokeCallback(context); 399 400 if (log) { 401 StreamString s; 402 GetDescription(&s, lldb::eDescriptionLevelVerbose); 403 LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(), 404 should_stop ? "stopping" : "continuing"); 405 } 406 407 return should_stop; 408 } 409 410 void BreakpointLocation::BumpHitCount() { 411 if (IsEnabled()) { 412 // Step our hit count, and also step the hit count of the owner. 413 m_hit_counter.Increment(); 414 m_owner.m_hit_counter.Increment(); 415 } 416 } 417 418 void BreakpointLocation::UndoBumpHitCount() { 419 if (IsEnabled()) { 420 // Step our hit count, and also step the hit count of the owner. 421 m_hit_counter.Decrement(); 422 m_owner.m_hit_counter.Decrement(); 423 } 424 } 425 426 bool BreakpointLocation::IsResolved() const { 427 return m_bp_site_sp.get() != nullptr; 428 } 429 430 lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const { 431 return m_bp_site_sp; 432 } 433 434 bool BreakpointLocation::ResolveBreakpointSite() { 435 if (m_bp_site_sp) 436 return true; 437 438 Process *process = m_owner.GetTarget().GetProcessSP().get(); 439 if (process == nullptr) 440 return false; 441 442 lldb::break_id_t new_id = 443 process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware()); 444 445 if (new_id == LLDB_INVALID_BREAK_ID) { 446 Log *log = GetLog(LLDBLog::Breakpoints); 447 if (log) 448 log->Warning("Failed to add breakpoint site at 0x%" PRIx64, 449 m_address.GetOpcodeLoadAddress(&m_owner.GetTarget())); 450 } 451 452 return IsResolved(); 453 } 454 455 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) { 456 m_bp_site_sp = bp_site_sp; 457 SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved); 458 return true; 459 } 460 461 bool BreakpointLocation::ClearBreakpointSite() { 462 if (m_bp_site_sp.get()) { 463 ProcessSP process_sp(m_owner.GetTarget().GetProcessSP()); 464 // If the process exists, get it to remove the owner, it will remove the 465 // physical implementation of the breakpoint as well if there are no more 466 // owners. Otherwise just remove this owner. 467 if (process_sp) 468 process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(), 469 GetID(), m_bp_site_sp); 470 else 471 m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID()); 472 473 m_bp_site_sp.reset(); 474 return true; 475 } 476 return false; 477 } 478 479 void BreakpointLocation::GetDescription(Stream *s, 480 lldb::DescriptionLevel level) { 481 SymbolContext sc; 482 483 // If the description level is "initial" then the breakpoint is printing out 484 // our initial state, and we should let it decide how it wants to print our 485 // label. 486 if (level != eDescriptionLevelInitial) { 487 s->Indent(); 488 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 489 } 490 491 if (level == lldb::eDescriptionLevelBrief) 492 return; 493 494 if (level != eDescriptionLevelInitial) 495 s->PutCString(": "); 496 497 if (level == lldb::eDescriptionLevelVerbose) 498 s->IndentMore(); 499 500 if (m_address.IsSectionOffset()) { 501 m_address.CalculateSymbolContext(&sc); 502 503 if (level == lldb::eDescriptionLevelFull || 504 level == eDescriptionLevelInitial) { 505 if (IsReExported()) 506 s->PutCString("re-exported target = "); 507 else 508 s->PutCString("where = "); 509 sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address, 510 false, true, false, true, true, true); 511 } else { 512 if (sc.module_sp) { 513 s->EOL(); 514 s->Indent("module = "); 515 sc.module_sp->GetFileSpec().Dump(s->AsRawOstream()); 516 } 517 518 if (sc.comp_unit != nullptr) { 519 s->EOL(); 520 s->Indent("compile unit = "); 521 sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s); 522 523 if (sc.function != nullptr) { 524 s->EOL(); 525 s->Indent("function = "); 526 s->PutCString(sc.function->GetName().AsCString("<unknown>")); 527 if (ConstString mangled_name = 528 sc.function->GetMangled().GetMangledName()) { 529 s->EOL(); 530 s->Indent("mangled function = "); 531 s->PutCString(mangled_name.AsCString()); 532 } 533 } 534 535 if (sc.line_entry.line > 0) { 536 s->EOL(); 537 s->Indent("location = "); 538 sc.line_entry.DumpStopContext(s, true); 539 } 540 541 } else { 542 // If we don't have a comp unit, see if we have a symbol we can print. 543 if (sc.symbol) { 544 s->EOL(); 545 if (IsReExported()) 546 s->Indent("re-exported target = "); 547 else 548 s->Indent("symbol = "); 549 s->PutCString(sc.symbol->GetName().AsCString("<unknown>")); 550 } 551 } 552 } 553 } 554 555 if (level == lldb::eDescriptionLevelVerbose) { 556 s->EOL(); 557 s->Indent(); 558 } 559 560 if (m_address.IsSectionOffset() && 561 (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)) 562 s->Printf(", "); 563 s->Printf("address = "); 564 565 ExecutionContextScope *exe_scope = nullptr; 566 Target *target = &m_owner.GetTarget(); 567 if (target) 568 exe_scope = target->GetProcessSP().get(); 569 if (exe_scope == nullptr) 570 exe_scope = target; 571 572 if (level == eDescriptionLevelInitial) 573 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, 574 Address::DumpStyleFileAddress); 575 else 576 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, 577 Address::DumpStyleModuleWithFileAddress); 578 579 if (IsIndirect() && m_bp_site_sp) { 580 Address resolved_address; 581 resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target); 582 Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol(); 583 if (resolved_symbol) { 584 if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial) 585 s->Printf(", "); 586 else if (level == lldb::eDescriptionLevelVerbose) { 587 s->EOL(); 588 s->Indent(); 589 } 590 s->Printf("indirect target = %s", 591 resolved_symbol->GetName().GetCString()); 592 } 593 } 594 595 bool is_resolved = IsResolved(); 596 bool is_hardware = is_resolved && m_bp_site_sp->IsHardware(); 597 598 if (level == lldb::eDescriptionLevelVerbose) { 599 s->EOL(); 600 s->Indent(); 601 s->Printf("resolved = %s\n", is_resolved ? "true" : "false"); 602 s->Indent(); 603 s->Printf("hardware = %s\n", is_hardware ? "true" : "false"); 604 s->Indent(); 605 s->Printf("hit count = %-4u\n", GetHitCount()); 606 607 if (m_options_up) { 608 s->Indent(); 609 m_options_up->GetDescription(s, level); 610 s->EOL(); 611 } 612 s->IndentLess(); 613 } else if (level != eDescriptionLevelInitial) { 614 s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"), 615 (is_hardware ? "hardware, " : ""), GetHitCount()); 616 if (m_options_up) { 617 m_options_up->GetDescription(s, level); 618 } 619 } 620 } 621 622 void BreakpointLocation::Dump(Stream *s) const { 623 if (s == nullptr) 624 return; 625 626 bool is_resolved = IsResolved(); 627 bool is_hardware = is_resolved && m_bp_site_sp->IsHardware(); 628 629 lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 630 .GetThreadSpecNoCreate() 631 ->GetTID(); 632 s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 633 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint " 634 "hit_count = %-4u ignore_count = %-4u", 635 GetID(), tid, 636 (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()), 637 (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled()) 638 ? "enabled " 639 : "disabled", 640 is_hardware ? "hardware" : "software", GetHitCount(), 641 GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount) 642 .GetIgnoreCount()); 643 } 644 645 void BreakpointLocation::SendBreakpointLocationChangedEvent( 646 lldb::BreakpointEventType eventKind) { 647 if (!m_owner.IsInternal() && m_owner.GetTarget().EventTypeHasListeners( 648 Target::eBroadcastBitBreakpointChanged)) { 649 auto data_sp = std::make_shared<Breakpoint::BreakpointEventData>( 650 eventKind, m_owner.shared_from_this()); 651 data_sp->GetBreakpointLocationCollection().Add(shared_from_this()); 652 m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, 653 data_sp); 654 } 655 } 656 657 void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) { 658 m_address = swap_from->m_address; 659 m_should_resolve_indirect_functions = 660 swap_from->m_should_resolve_indirect_functions; 661 m_is_reexported = swap_from->m_is_reexported; 662 m_is_indirect = swap_from->m_is_indirect; 663 m_user_expression_sp.reset(); 664 } 665 666 void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) { 667 if (thread_id != LLDB_INVALID_THREAD_ID) 668 GetLocationOptions().SetThreadID(thread_id); 669 else { 670 // If we're resetting this to an invalid thread id, then don't make an 671 // options pointer just to do that. 672 if (m_options_up != nullptr) 673 m_options_up->SetThreadID(thread_id); 674 } 675 } 676