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/Expression/DiagnosticManager.h" 15 #include "lldb/Expression/ExpressionVariable.h" 16 #include "lldb/Expression/UserExpression.h" 17 #include "lldb/Symbol/CompileUnit.h" 18 #include "lldb/Symbol/Symbol.h" 19 #include "lldb/Symbol/TypeSystem.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/Target.h" 22 #include "lldb/Target/Thread.h" 23 #include "lldb/Target/ThreadSpec.h" 24 #include "lldb/Utility/LLDBLog.h" 25 #include "lldb/Utility/Log.h" 26 #include "lldb/Utility/StreamString.h" 27 #include "lldb/ValueObject/ValueObject.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 = Status::FromError( 268 diagnostics.GetAsError(lldb::eExpressionParseError, 269 "Couldn't parse conditional expression:")); 270 271 m_user_expression_sp.reset(); 272 return true; 273 } 274 275 m_condition_hash = condition_hash; 276 } 277 278 // We need to make sure the user sees any parse errors in their condition, so 279 // we'll hook the constructor errors up to the debugger's Async I/O. 280 281 ValueObjectSP result_value_sp; 282 283 EvaluateExpressionOptions options; 284 options.SetUnwindOnError(true); 285 options.SetIgnoreBreakpoints(true); 286 options.SetTryAllThreads(true); 287 options.SetSuppressPersistentResult( 288 true); // Don't generate a user variable for condition expressions. 289 290 Status expr_error; 291 292 diagnostics.Clear(); 293 294 ExpressionVariableSP result_variable_sp; 295 296 ExpressionResults result_code = m_user_expression_sp->Execute( 297 diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp); 298 299 bool ret; 300 301 if (result_code == eExpressionCompleted) { 302 if (!result_variable_sp) { 303 error = Status::FromErrorString("Expression did not return a result"); 304 return false; 305 } 306 307 result_value_sp = result_variable_sp->GetValueObject(); 308 309 if (result_value_sp) { 310 ret = result_value_sp->IsLogicalTrue(error); 311 if (log) { 312 if (error.Success()) { 313 LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n", 314 ret ? "true" : "false"); 315 } else { 316 error = Status::FromErrorString( 317 "Failed to get an integer result from the expression"); 318 ret = false; 319 } 320 } 321 } else { 322 ret = false; 323 error = Status::FromErrorString( 324 "Failed to get any result from the expression"); 325 } 326 } else { 327 ret = false; 328 error = Status::FromError(diagnostics.GetAsError( 329 lldb::eExpressionParseError, "Couldn't execute expression:")); 330 } 331 332 return ret; 333 } 334 335 uint32_t BreakpointLocation::GetIgnoreCount() const { 336 return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount) 337 .GetIgnoreCount(); 338 } 339 340 void BreakpointLocation::SetIgnoreCount(uint32_t n) { 341 GetLocationOptions().SetIgnoreCount(n); 342 SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged); 343 } 344 345 void BreakpointLocation::DecrementIgnoreCount() { 346 if (m_options_up != nullptr) { 347 uint32_t loc_ignore = m_options_up->GetIgnoreCount(); 348 if (loc_ignore != 0) 349 m_options_up->SetIgnoreCount(loc_ignore - 1); 350 } 351 } 352 353 bool BreakpointLocation::IgnoreCountShouldStop() { 354 uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount(); 355 uint32_t loc_ignore = 0; 356 if (m_options_up != nullptr) 357 loc_ignore = m_options_up->GetIgnoreCount(); 358 359 if (loc_ignore != 0 || owner_ignore != 0) { 360 m_owner.DecrementIgnoreCount(); 361 DecrementIgnoreCount(); // Have to decrement our owners' ignore count, 362 // since it won't get a chance to. 363 return false; 364 } 365 return true; 366 } 367 368 BreakpointOptions &BreakpointLocation::GetLocationOptions() { 369 // If we make the copy we don't copy the callbacks because that is 370 // potentially expensive and we don't want to do that for the simple case 371 // where someone is just disabling the location. 372 if (m_options_up == nullptr) 373 m_options_up = std::make_unique<BreakpointOptions>(false); 374 375 return *m_options_up; 376 } 377 378 bool BreakpointLocation::ValidForThisThread(Thread &thread) { 379 return thread.MatchesSpec( 380 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 381 .GetThreadSpecNoCreate()); 382 } 383 384 // RETURNS - true if we should stop at this breakpoint, false if we 385 // should continue. Note, we don't check the thread spec for the breakpoint 386 // here, since if the breakpoint is not for this thread, then the event won't 387 // even get reported, so the check is redundant. 388 389 bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) { 390 bool should_stop = true; 391 Log *log = GetLog(LLDBLog::Breakpoints); 392 393 // Do this first, if a location is disabled, it shouldn't increment its hit 394 // count. 395 if (!IsEnabled()) 396 return false; 397 398 // We only run synchronous callbacks in ShouldStop: 399 context->is_synchronous = true; 400 should_stop = InvokeCallback(context); 401 402 if (log) { 403 StreamString s; 404 GetDescription(&s, lldb::eDescriptionLevelVerbose); 405 LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(), 406 should_stop ? "stopping" : "continuing"); 407 } 408 409 return should_stop; 410 } 411 412 void BreakpointLocation::BumpHitCount() { 413 if (IsEnabled()) { 414 // Step our hit count, and also step the hit count of the owner. 415 m_hit_counter.Increment(); 416 m_owner.m_hit_counter.Increment(); 417 } 418 } 419 420 void BreakpointLocation::UndoBumpHitCount() { 421 if (IsEnabled()) { 422 // Step our hit count, and also step the hit count of the owner. 423 m_hit_counter.Decrement(); 424 m_owner.m_hit_counter.Decrement(); 425 } 426 } 427 428 bool BreakpointLocation::IsResolved() const { 429 return m_bp_site_sp.get() != nullptr; 430 } 431 432 lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const { 433 return m_bp_site_sp; 434 } 435 436 bool BreakpointLocation::ResolveBreakpointSite() { 437 if (m_bp_site_sp) 438 return true; 439 440 Process *process = m_owner.GetTarget().GetProcessSP().get(); 441 if (process == nullptr) 442 return false; 443 444 lldb::break_id_t new_id = 445 process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware()); 446 447 if (new_id == LLDB_INVALID_BREAK_ID) { 448 Log *log = GetLog(LLDBLog::Breakpoints); 449 if (log) 450 log->Warning("Failed to add breakpoint site at 0x%" PRIx64, 451 m_address.GetOpcodeLoadAddress(&m_owner.GetTarget())); 452 } 453 454 return IsResolved(); 455 } 456 457 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) { 458 m_bp_site_sp = bp_site_sp; 459 SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved); 460 return true; 461 } 462 463 bool BreakpointLocation::ClearBreakpointSite() { 464 if (m_bp_site_sp.get()) { 465 ProcessSP process_sp(m_owner.GetTarget().GetProcessSP()); 466 // If the process exists, get it to remove the owner, it will remove the 467 // physical implementation of the breakpoint as well if there are no more 468 // owners. Otherwise just remove this owner. 469 if (process_sp) 470 process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(), 471 GetID(), m_bp_site_sp); 472 else 473 m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID()); 474 475 m_bp_site_sp.reset(); 476 return true; 477 } 478 return false; 479 } 480 481 void BreakpointLocation::GetDescription(Stream *s, 482 lldb::DescriptionLevel level) { 483 SymbolContext sc; 484 485 // If the description level is "initial" then the breakpoint is printing out 486 // our initial state, and we should let it decide how it wants to print our 487 // label. 488 if (level != eDescriptionLevelInitial) { 489 s->Indent(); 490 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 491 } 492 493 if (level == lldb::eDescriptionLevelBrief) 494 return; 495 496 if (level != eDescriptionLevelInitial) 497 s->PutCString(": "); 498 499 if (level == lldb::eDescriptionLevelVerbose) 500 s->IndentMore(); 501 502 if (m_address.IsSectionOffset()) { 503 m_address.CalculateSymbolContext(&sc); 504 505 if (level == lldb::eDescriptionLevelFull || 506 level == eDescriptionLevelInitial) { 507 if (IsReExported()) 508 s->PutCString("re-exported target = "); 509 else 510 s->PutCString("where = "); 511 512 // If there's a preferred line entry for printing, use that. 513 bool show_function_info = true; 514 if (auto preferred = GetPreferredLineEntry()) { 515 sc.line_entry = *preferred; 516 // FIXME: We're going to get the function name wrong when the preferred 517 // line entry is not the lowest one. For now, just leave the function 518 // out in this case, but we really should also figure out how to easily 519 // fake the function name here. 520 show_function_info = false; 521 } 522 sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address, 523 false, true, false, show_function_info, 524 show_function_info, show_function_info); 525 } else { 526 if (sc.module_sp) { 527 s->EOL(); 528 s->Indent("module = "); 529 sc.module_sp->GetFileSpec().Dump(s->AsRawOstream()); 530 } 531 532 if (sc.comp_unit != nullptr) { 533 s->EOL(); 534 s->Indent("compile unit = "); 535 sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s); 536 537 if (sc.function != nullptr) { 538 s->EOL(); 539 s->Indent("function = "); 540 s->PutCString(sc.function->GetName().AsCString("<unknown>")); 541 if (ConstString mangled_name = 542 sc.function->GetMangled().GetMangledName()) { 543 s->EOL(); 544 s->Indent("mangled function = "); 545 s->PutCString(mangled_name.AsCString()); 546 } 547 } 548 549 if (sc.line_entry.line > 0) { 550 s->EOL(); 551 s->Indent("location = "); 552 if (auto preferred = GetPreferredLineEntry()) 553 preferred->DumpStopContext(s, true); 554 else 555 sc.line_entry.DumpStopContext(s, true); 556 } 557 558 } else { 559 // If we don't have a comp unit, see if we have a symbol we can print. 560 if (sc.symbol) { 561 s->EOL(); 562 if (IsReExported()) 563 s->Indent("re-exported target = "); 564 else 565 s->Indent("symbol = "); 566 s->PutCString(sc.symbol->GetName().AsCString("<unknown>")); 567 } 568 } 569 } 570 } 571 572 if (level == lldb::eDescriptionLevelVerbose) { 573 s->EOL(); 574 s->Indent(); 575 } 576 577 if (m_address.IsSectionOffset() && 578 (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)) 579 s->Printf(", "); 580 s->Printf("address = "); 581 582 ExecutionContextScope *exe_scope = nullptr; 583 Target *target = &m_owner.GetTarget(); 584 if (target) 585 exe_scope = target->GetProcessSP().get(); 586 if (exe_scope == nullptr) 587 exe_scope = target; 588 589 if (level == eDescriptionLevelInitial) 590 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, 591 Address::DumpStyleFileAddress); 592 else 593 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, 594 Address::DumpStyleModuleWithFileAddress); 595 596 if (IsIndirect() && m_bp_site_sp) { 597 Address resolved_address; 598 resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target); 599 Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol(); 600 if (resolved_symbol) { 601 if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial) 602 s->Printf(", "); 603 else if (level == lldb::eDescriptionLevelVerbose) { 604 s->EOL(); 605 s->Indent(); 606 } 607 s->Printf("indirect target = %s", 608 resolved_symbol->GetName().GetCString()); 609 } 610 } 611 612 bool is_resolved = IsResolved(); 613 bool is_hardware = is_resolved && m_bp_site_sp->IsHardware(); 614 615 if (level == lldb::eDescriptionLevelVerbose) { 616 s->EOL(); 617 s->Indent(); 618 s->Printf("resolved = %s\n", is_resolved ? "true" : "false"); 619 s->Indent(); 620 s->Printf("hardware = %s\n", is_hardware ? "true" : "false"); 621 s->Indent(); 622 s->Printf("hit count = %-4u\n", GetHitCount()); 623 624 if (m_options_up) { 625 s->Indent(); 626 m_options_up->GetDescription(s, level); 627 s->EOL(); 628 } 629 s->IndentLess(); 630 } else if (level != eDescriptionLevelInitial) { 631 s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"), 632 (is_hardware ? "hardware, " : ""), GetHitCount()); 633 if (m_options_up) { 634 m_options_up->GetDescription(s, level); 635 } 636 } 637 } 638 639 void BreakpointLocation::Dump(Stream *s) const { 640 if (s == nullptr) 641 return; 642 643 bool is_resolved = IsResolved(); 644 bool is_hardware = is_resolved && m_bp_site_sp->IsHardware(); 645 646 lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 647 .GetThreadSpecNoCreate() 648 ->GetTID(); 649 s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 650 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint " 651 "hit_count = %-4u ignore_count = %-4u", 652 GetID(), tid, 653 (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()), 654 (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled()) 655 ? "enabled " 656 : "disabled", 657 is_hardware ? "hardware" : "software", GetHitCount(), 658 GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount) 659 .GetIgnoreCount()); 660 } 661 662 void BreakpointLocation::SendBreakpointLocationChangedEvent( 663 lldb::BreakpointEventType eventKind) { 664 if (!m_owner.IsInternal() && m_owner.GetTarget().EventTypeHasListeners( 665 Target::eBroadcastBitBreakpointChanged)) { 666 auto data_sp = std::make_shared<Breakpoint::BreakpointEventData>( 667 eventKind, m_owner.shared_from_this()); 668 data_sp->GetBreakpointLocationCollection().Add(shared_from_this()); 669 m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, 670 data_sp); 671 } 672 } 673 674 std::optional<uint32_t> BreakpointLocation::GetSuggestedStackFrameIndex() { 675 auto preferred_opt = GetPreferredLineEntry(); 676 if (!preferred_opt) 677 return {}; 678 LineEntry preferred = *preferred_opt; 679 SymbolContext sc; 680 if (!m_address.CalculateSymbolContext(&sc)) 681 return {}; 682 // Don't return anything special if frame 0 is the preferred line entry. 683 // We not really telling the stack frame list to do anything special in that 684 // case. 685 if (!LineEntry::Compare(sc.line_entry, preferred)) 686 return {}; 687 688 if (!sc.block) 689 return {}; 690 691 // Blocks have their line info in Declaration form, so make one here: 692 Declaration preferred_decl(preferred.GetFile(), preferred.line, 693 preferred.column); 694 695 uint32_t depth = 0; 696 Block *inlined_block = sc.block->GetContainingInlinedBlock(); 697 while (inlined_block) { 698 // If we've moved to a block that this isn't the start of, that's not 699 // our inlining info or call site, so we can stop here. 700 Address start_address; 701 if (!inlined_block->GetStartAddress(start_address) || 702 start_address != m_address) 703 return {}; 704 705 const InlineFunctionInfo *info = inlined_block->GetInlinedFunctionInfo(); 706 if (info) { 707 if (preferred_decl == info->GetDeclaration()) 708 return depth; 709 if (preferred_decl == info->GetCallSite()) 710 return depth + 1; 711 } 712 inlined_block = inlined_block->GetInlinedParent(); 713 depth++; 714 } 715 return {}; 716 } 717 718 void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) { 719 m_address = swap_from->m_address; 720 m_should_resolve_indirect_functions = 721 swap_from->m_should_resolve_indirect_functions; 722 m_is_reexported = swap_from->m_is_reexported; 723 m_is_indirect = swap_from->m_is_indirect; 724 m_user_expression_sp.reset(); 725 } 726 727 void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) { 728 if (thread_id != LLDB_INVALID_THREAD_ID) 729 GetLocationOptions().SetThreadID(thread_id); 730 else { 731 // If we're resetting this to an invalid thread id, then don't make an 732 // options pointer just to do that. 733 if (m_options_up != nullptr) 734 m_options_up->SetThreadID(thread_id); 735 } 736 } 737