823 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Breakpoint/BreakpointLocation.h"10#include "lldb/Breakpoint/BreakpointID.h"11#include "lldb/Breakpoint/BreakpointResolver.h"12#include "lldb/Breakpoint/BreakpointResolverScripted.h"13#include "lldb/Breakpoint/StoppointCallbackContext.h"14#include "lldb/Core/Debugger.h"15#include "lldb/Core/Module.h"16#include "lldb/Expression/DiagnosticManager.h"17#include "lldb/Expression/ExpressionVariable.h"18#include "lldb/Expression/UserExpression.h"19#include "lldb/Symbol/CompileUnit.h"20#include "lldb/Symbol/Symbol.h"21#include "lldb/Symbol/TypeSystem.h"22#include "lldb/Target/Process.h"23#include "lldb/Target/Target.h"24#include "lldb/Target/Thread.h"25#include "lldb/Target/ThreadSpec.h"26#include "lldb/Utility/LLDBLog.h"27#include "lldb/Utility/Log.h"28#include "lldb/Utility/StreamString.h"29#include "lldb/ValueObject/ValueObject.h"30 31using namespace lldb;32using namespace lldb_private;33 34BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner,35 const Address &addr, lldb::tid_t tid,36 bool check_for_resolver)37 : m_should_resolve_indirect_functions(false), m_is_reexported(false),38 m_is_indirect(false), m_address(addr), m_owner(owner),39 m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() {40 if (check_for_resolver) {41 Symbol *symbol = m_address.CalculateSymbolContextSymbol();42 if (symbol && symbol->IsIndirect()) {43 SetShouldResolveIndirectFunctions(true);44 }45 }46 47 SetThreadIDInternal(tid);48}49 50BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner)51 : m_should_resolve_indirect_functions(false), m_is_reexported(false),52 m_is_indirect(false), m_address(LLDB_INVALID_ADDRESS), m_owner(owner),53 m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() {54 SetThreadIDInternal(LLDB_INVALID_THREAD_ID);55}56 57BreakpointLocation::~BreakpointLocation() {58 llvm::consumeError(ClearBreakpointSite());59}60 61lldb::addr_t BreakpointLocation::GetLoadAddress() const {62 return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());63}64 65const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind(66 BreakpointOptions::OptionKind kind) const {67 if (m_options_up && m_options_up->IsOptionSet(kind))68 return *m_options_up;69 return m_owner.GetOptions();70}71 72Address &BreakpointLocation::GetAddress() { return m_address; }73 74Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }75 76Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }77 78bool BreakpointLocation::IsEnabled() const {79 if (!m_owner.IsEnabled())80 return false;81 if (m_options_up != nullptr)82 return m_options_up->IsEnabled();83 return true;84}85 86llvm::Error BreakpointLocation::SetEnabled(bool enabled) {87 GetLocationOptions().SetEnabled(enabled);88 llvm::Error error = enabled ? ResolveBreakpointSite() : ClearBreakpointSite();89 SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled90 : eBreakpointEventTypeDisabled);91 return error;92}93 94bool BreakpointLocation::IsAutoContinue() const {95 if (m_options_up &&96 m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue))97 return m_options_up->IsAutoContinue();98 return m_owner.IsAutoContinue();99}100 101void BreakpointLocation::SetAutoContinue(bool auto_continue) {102 GetLocationOptions().SetAutoContinue(auto_continue);103 SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);104}105 106void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {107 SetThreadIDInternal(thread_id);108 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);109}110 111lldb::tid_t BreakpointLocation::GetThreadID() {112 const ThreadSpec *thread_spec =113 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)114 .GetThreadSpecNoCreate();115 if (thread_spec)116 return thread_spec->GetTID();117 return LLDB_INVALID_THREAD_ID;118}119 120void BreakpointLocation::SetThreadIndex(uint32_t index) {121 if (index != 0)122 GetLocationOptions().GetThreadSpec()->SetIndex(index);123 else {124 // If we're resetting this to an invalid thread id, then don't make an125 // options pointer just to do that.126 if (m_options_up != nullptr)127 m_options_up->GetThreadSpec()->SetIndex(index);128 }129 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);130}131 132uint32_t BreakpointLocation::GetThreadIndex() const {133 const ThreadSpec *thread_spec =134 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)135 .GetThreadSpecNoCreate();136 if (thread_spec)137 return thread_spec->GetIndex();138 return 0;139}140 141void BreakpointLocation::SetThreadName(const char *thread_name) {142 if (thread_name != nullptr)143 GetLocationOptions().GetThreadSpec()->SetName(thread_name);144 else {145 // If we're resetting this to an invalid thread id, then don't make an146 // options pointer just to do that.147 if (m_options_up != nullptr)148 m_options_up->GetThreadSpec()->SetName(thread_name);149 }150 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);151}152 153const char *BreakpointLocation::GetThreadName() const {154 const ThreadSpec *thread_spec =155 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)156 .GetThreadSpecNoCreate();157 if (thread_spec)158 return thread_spec->GetName();159 return nullptr;160}161 162void BreakpointLocation::SetQueueName(const char *queue_name) {163 if (queue_name != nullptr)164 GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name);165 else {166 // If we're resetting this to an invalid thread id, then don't make an167 // options pointer just to do that.168 if (m_options_up != nullptr)169 m_options_up->GetThreadSpec()->SetQueueName(queue_name);170 }171 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);172}173 174const char *BreakpointLocation::GetQueueName() const {175 const ThreadSpec *thread_spec =176 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)177 .GetThreadSpecNoCreate();178 if (thread_spec)179 return thread_spec->GetQueueName();180 return nullptr;181}182 183bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {184 if (m_options_up != nullptr && m_options_up->HasCallback())185 return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID());186 return m_owner.InvokeCallback(context, GetID());187}188 189bool BreakpointLocation::IsCallbackSynchronous() {190 if (m_options_up != nullptr && m_options_up->HasCallback())191 return m_options_up->IsCallbackSynchronous();192 return m_owner.GetOptions().IsCallbackSynchronous();193}194 195void BreakpointLocation::SetCallback(BreakpointHitCallback callback,196 void *baton, bool is_synchronous) {197 // The default "Baton" class will keep a copy of "baton" and won't free or198 // delete it when it goes out of scope.199 GetLocationOptions().SetCallback(200 callback, std::make_shared<UntypedBaton>(baton), is_synchronous);201 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);202}203 204void BreakpointLocation::SetCallback(BreakpointHitCallback callback,205 const BatonSP &baton_sp,206 bool is_synchronous) {207 GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous);208 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);209}210 211void BreakpointLocation::ClearCallback() {212 GetLocationOptions().ClearCallback();213}214 215void BreakpointLocation::SetCondition(StopCondition condition) {216 GetLocationOptions().SetCondition(std::move(condition));217 SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);218}219 220const StopCondition &BreakpointLocation::GetCondition() const {221 return GetOptionsSpecifyingKind(BreakpointOptions::eCondition).GetCondition();222}223 224bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,225 Status &error) {226 Log *log = GetLog(LLDBLog::Breakpoints);227 228 std::lock_guard<std::mutex> guard(m_condition_mutex);229 230 StopCondition condition = GetCondition();231 232 if (!condition) {233 m_user_expression_sp.reset();234 return false;235 }236 237 error.Clear();238 239 DiagnosticManager diagnostics;240 241 if (condition.GetHash() != m_condition_hash || !m_user_expression_sp ||242 !m_user_expression_sp->IsParseCacheable() ||243 !m_user_expression_sp->MatchesContext(exe_ctx)) {244 LanguageType language = condition.GetLanguage();245 if (language == lldb::eLanguageTypeUnknown) {246 // See if we can figure out the language from the frame, otherwise use the247 // default language:248 if (CompileUnit *comp_unit =249 m_address.CalculateSymbolContextCompileUnit())250 language = comp_unit->GetLanguage();251 }252 253 m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(254 condition.GetText(), llvm::StringRef(), SourceLanguage{language},255 Expression::eResultTypeAny, EvaluateExpressionOptions(), nullptr,256 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.GetHash();276 }277 278 // We need to make sure the user sees any parse errors in their condition, so279 // 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 335uint32_t BreakpointLocation::GetIgnoreCount() const {336 return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)337 .GetIgnoreCount();338}339 340void BreakpointLocation::SetIgnoreCount(uint32_t n) {341 GetLocationOptions().SetIgnoreCount(n);342 SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);343}344 345void 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 353bool 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 368BreakpointOptions &BreakpointLocation::GetLocationOptions() {369 // If we make the copy we don't copy the callbacks because that is370 // potentially expensive and we don't want to do that for the simple case371 // 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 378bool BreakpointLocation::ValidForThisThread(Thread &thread) {379 return thread.MatchesSpec(380 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)381 .GetThreadSpecNoCreate());382}383 384BreakpointLocationSP385BreakpointLocation::WasHit(StoppointCallbackContext *context) {386 // Only the BreakpointResolverScripted provides WasHit.387 BreakpointResolverSP resolver_sp = GetBreakpoint().GetResolver();388 BreakpointResolverScripted *scripted =389 llvm::dyn_cast<BreakpointResolverScripted>(resolver_sp.get());390 if (!scripted)391 return shared_from_this();392 393 StackFrameSP frame_sp = context->exe_ctx_ref.GetFrameSP();394 if (!frame_sp)395 return shared_from_this();396 397 BreakpointLocationSP return_loc_sp =398 scripted->WasHit(frame_sp, shared_from_this());399 // If this is a facade location, then we won't have bumped its hit count400 // while processing the original location hit. Do so here. We don't need401 // to bump the breakpoint's hit count, however, since hitting the real402 // location would have already done that.403 // Also we have to check the enabled state here, since we would never have404 // gotten here with a real location...405 if (return_loc_sp && return_loc_sp->IsFacade()) {406 if (return_loc_sp->IsEnabled())407 return_loc_sp->m_hit_counter.Increment();408 else409 return {};410 }411 return return_loc_sp;412}413 414// RETURNS - true if we should stop at this breakpoint, false if we415// should continue. Note, we don't check the thread spec for the breakpoint416// here, since if the breakpoint is not for this thread, then the event won't417// even get reported, so the check is redundant.418 419bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context,420 lldb::BreakpointLocationSP &facade_loc_sp) {421 bool should_stop = true;422 Log *log = GetLog(LLDBLog::Breakpoints);423 424 // Do this first, if a location is disabled, it shouldn't increment its hit425 // count.426 if (!IsEnabled())427 return false;428 429 // Next check WasHit:430 BreakpointLocationSP loc_hit_sp = WasHit(context);431 432 if (!loc_hit_sp) {433 // We bump the hit counts in StopInfoBreakpoint::ShouldStopSynchronous,434 // before we call into each location's ShouldStop. So we need to undo435 // that here.436 UndoBumpHitCount();437 return false;438 }439 440 // If the location hit was not us, it was a facade location, in which case441 // we should use the facade location's callbacks, etc. Those will all be442 // run in the asynchronous phase, so for now we just have to record the fact443 // that we should treat this as a facade hit. This is strictly an out444 // parameter, so clear it if this isn't a facade hit.445 if (loc_hit_sp.get() != this)446 facade_loc_sp = loc_hit_sp;447 else448 facade_loc_sp.reset();449 450 // We only run synchronous callbacks in ShouldStop:451 context->is_synchronous = true;452 should_stop = InvokeCallback(context);453 454 if (log) {455 StreamString s;456 GetDescription(&s, lldb::eDescriptionLevelVerbose);457 LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),458 should_stop ? "stopping" : "continuing");459 if (facade_loc_sp) {460 s.Clear();461 facade_loc_sp->GetDescription(&s, lldb::eDescriptionLevelVerbose);462 LLDB_LOGF(log, "Attributing to facade location: %s.\n", s.GetData());463 }464 }465 466 return should_stop;467}468 469void BreakpointLocation::BumpHitCount() {470 if (IsEnabled()) {471 // Step our hit count, and also step the hit count of the owner.472 m_hit_counter.Increment();473 m_owner.m_hit_counter.Increment();474 }475}476 477void BreakpointLocation::UndoBumpHitCount() {478 if (IsEnabled()) {479 // Step our hit count, and also step the hit count of the owner.480 m_hit_counter.Decrement();481 m_owner.m_hit_counter.Decrement();482 }483}484 485bool BreakpointLocation::IsResolved() const {486 487 bool has_site = m_bp_site_sp.get() != nullptr;488 // Facade locations are currently always considered resolved.489 return has_site || IsFacade();490}491 492lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {493 return m_bp_site_sp;494}495 496llvm::Error BreakpointLocation::ResolveBreakpointSite() {497 // This might be a facade location, which doesn't have an address.498 // In that case, don't attempt to make a site.499 if (m_bp_site_sp || IsFacade())500 return llvm::Error::success();501 502 Process *process = m_owner.GetTarget().GetProcessSP().get();503 if (process == nullptr)504 return llvm::createStringError("no process");505 506 lldb::break_id_t new_id =507 process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());508 509 if (new_id == LLDB_INVALID_BREAK_ID)510 return llvm::createStringError(511 llvm::formatv("Failed to add breakpoint site at {0:x}",512 m_address.GetOpcodeLoadAddress(&m_owner.GetTarget())));513 514 if (!IsResolved())515 return llvm::createStringError(516 "breakpoint site created but location is still unresolved");517 518 return llvm::Error::success();519}520 521bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {522 m_bp_site_sp = bp_site_sp;523 SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);524 return true;525}526 527llvm::Error BreakpointLocation::ClearBreakpointSite() {528 if (!m_bp_site_sp) {529 // This might be a Facade Location, which don't have sites or addresses530 if (IsFacade())531 return llvm::Error::success();532 return llvm::createStringError("no breakpoint site to clear");533 }534 535 // If the process exists, get it to remove the owner, it will remove the536 // physical implementation of the breakpoint as well if there are no more537 // owners. Otherwise just remove this owner.538 if (ProcessSP process_sp = m_owner.GetTarget().GetProcessSP())539 process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(),540 GetID(), m_bp_site_sp);541 else542 m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID());543 544 m_bp_site_sp.reset();545 return llvm::Error::success();546}547 548void BreakpointLocation::GetDescription(Stream *s,549 lldb::DescriptionLevel level) {550 SymbolContext sc;551 552 // If this is a scripted breakpoint, give it a chance to describe its553 // locations:554 std::optional<std::string> scripted_opt;555 BreakpointResolverSP resolver_sp = GetBreakpoint().GetResolver();556 BreakpointResolverScripted *scripted =557 llvm::dyn_cast<BreakpointResolverScripted>(resolver_sp.get());558 if (scripted)559 scripted_opt = scripted->GetLocationDescription(shared_from_this(), level);560 561 bool is_scripted_desc = scripted_opt.has_value();562 563 // If the description level is "initial" then the breakpoint is printing out564 // our initial state, and we should let it decide how it wants to print our565 // label.566 if (level != eDescriptionLevelInitial) {567 s->Indent();568 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());569 }570 571 if (level == lldb::eDescriptionLevelBrief)572 return;573 574 if (level != eDescriptionLevelInitial)575 s->PutCString(": ");576 577 if (level == lldb::eDescriptionLevelVerbose)578 s->IndentMore();579 580 if (is_scripted_desc) {581 s->PutCString(scripted_opt->c_str());582 } else if (m_address.IsSectionOffset()) {583 m_address.CalculateSymbolContext(&sc);584 585 if (level == lldb::eDescriptionLevelFull ||586 level == eDescriptionLevelInitial) {587 if (IsReExported())588 s->PutCString("re-exported target = ");589 else590 s->PutCString("where = ");591 592 // If there's a preferred line entry for printing, use that.593 bool show_function_info = true;594 if (auto preferred = GetPreferredLineEntry()) {595 sc.line_entry = *preferred;596 // FIXME: We're going to get the function name wrong when the preferred597 // line entry is not the lowest one. For now, just leave the function598 // out in this case, but we really should also figure out how to easily599 // fake the function name here.600 show_function_info = false;601 }602 sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,603 false, true, false, show_function_info,604 show_function_info, show_function_info);605 } else {606 if (sc.module_sp) {607 s->EOL();608 s->Indent("module = ");609 sc.module_sp->GetFileSpec().Dump(s->AsRawOstream());610 }611 612 if (sc.comp_unit != nullptr) {613 s->EOL();614 s->Indent("compile unit = ");615 sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s);616 617 if (sc.function != nullptr) {618 s->EOL();619 s->Indent("function = ");620 s->PutCString(sc.function->GetName().AsCString("<unknown>"));621 if (ConstString mangled_name =622 sc.function->GetMangled().GetMangledName()) {623 s->EOL();624 s->Indent("mangled function = ");625 s->PutCString(mangled_name.AsCString());626 }627 }628 629 if (sc.line_entry.line > 0) {630 s->EOL();631 s->Indent("location = ");632 if (auto preferred = GetPreferredLineEntry())633 preferred->DumpStopContext(s, true);634 else635 sc.line_entry.DumpStopContext(s, true);636 }637 638 } else {639 // If we don't have a comp unit, see if we have a symbol we can print.640 if (sc.symbol) {641 s->EOL();642 if (IsReExported())643 s->Indent("re-exported target = ");644 else645 s->Indent("symbol = ");646 s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));647 }648 }649 }650 }651 652 if (level == lldb::eDescriptionLevelVerbose) {653 s->EOL();654 s->Indent();655 }656 657 if (!is_scripted_desc) {658 if (m_address.IsSectionOffset() &&659 (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))660 s->Printf(", ");661 s->Printf("address = ");662 663 ExecutionContextScope *exe_scope = nullptr;664 Target *target = &m_owner.GetTarget();665 if (target)666 exe_scope = target->GetProcessSP().get();667 if (exe_scope == nullptr)668 exe_scope = target;669 670 if (level == eDescriptionLevelInitial)671 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,672 Address::DumpStyleFileAddress);673 else674 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,675 Address::DumpStyleModuleWithFileAddress);676 677 if (IsIndirect() && m_bp_site_sp) {678 Address resolved_address;679 resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);680 Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();681 if (resolved_symbol) {682 if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)683 s->Printf(", ");684 else if (level == lldb::eDescriptionLevelVerbose) {685 s->EOL();686 s->Indent();687 }688 s->Printf("indirect target = %s",689 resolved_symbol->GetName().GetCString());690 }691 }692 }693 694 // FIXME: scripted breakpoint are currently always resolved. Does this seem695 // right? If they don't add any scripted locations, we shouldn't consider them696 // resolved.697 bool is_resolved = is_scripted_desc || IsResolved();698 // A scripted breakpoint might be resolved but not have a site. Be sure to699 // check for that.700 bool is_hardware = !is_scripted_desc && IsResolved() && m_bp_site_sp &&701 m_bp_site_sp->IsHardware();702 703 if (level == lldb::eDescriptionLevelVerbose) {704 s->EOL();705 s->Indent();706 s->Printf("resolved = %s\n", is_resolved ? "true" : "false");707 s->Indent();708 s->Printf("hardware = %s\n", is_hardware ? "true" : "false");709 s->Indent();710 s->Printf("hit count = %-4u\n", GetHitCount());711 712 if (m_options_up) {713 s->Indent();714 m_options_up->GetDescription(s, level);715 s->EOL();716 }717 s->IndentLess();718 } else if (level != eDescriptionLevelInitial) {719 s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"),720 (is_hardware ? "hardware, " : ""), GetHitCount());721 if (m_options_up) {722 m_options_up->GetDescription(s, level);723 }724 }725}726 727void BreakpointLocation::Dump(Stream *s) const {728 if (s == nullptr)729 return;730 731 bool is_resolved = IsResolved();732 bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();733 734 lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)735 .GetThreadSpecNoCreate()736 ->GetTID();737 s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64738 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint "739 "hit_count = %-4u ignore_count = %-4u",740 GetID(), tid,741 (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),742 (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())743 ? "enabled "744 : "disabled",745 is_hardware ? "hardware" : "software", GetHitCount(),746 GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)747 .GetIgnoreCount());748}749 750void BreakpointLocation::SendBreakpointLocationChangedEvent(751 lldb::BreakpointEventType eventKind) {752 if (!m_owner.IsInternal()) {753 auto data_sp = std::make_shared<Breakpoint::BreakpointEventData>(754 eventKind, m_owner.shared_from_this());755 data_sp->GetBreakpointLocationCollection().Add(shared_from_this());756 m_owner.GetTarget().NotifyBreakpointChanged(m_owner, data_sp);757 }758}759 760std::optional<uint32_t> BreakpointLocation::GetSuggestedStackFrameIndex() {761 auto preferred_opt = GetPreferredLineEntry();762 if (!preferred_opt)763 return {};764 LineEntry preferred = *preferred_opt;765 SymbolContext sc;766 if (!m_address.CalculateSymbolContext(&sc))767 return {};768 // Don't return anything special if frame 0 is the preferred line entry.769 // We not really telling the stack frame list to do anything special in that770 // case.771 if (!LineEntry::Compare(sc.line_entry, preferred))772 return {};773 774 if (!sc.block)775 return {};776 777 // Blocks have their line info in Declaration form, so make one here:778 Declaration preferred_decl(preferred.GetFile(), preferred.line,779 preferred.column);780 781 uint32_t depth = 0;782 Block *inlined_block = sc.block->GetContainingInlinedBlock();783 while (inlined_block) {784 // If we've moved to a block that this isn't the start of, that's not785 // our inlining info or call site, so we can stop here.786 Address start_address;787 if (!inlined_block->GetStartAddress(start_address) ||788 start_address != m_address)789 return {};790 791 const InlineFunctionInfo *info = inlined_block->GetInlinedFunctionInfo();792 if (info) {793 if (preferred_decl == info->GetDeclaration())794 return depth;795 if (preferred_decl == info->GetCallSite())796 return depth + 1;797 }798 inlined_block = inlined_block->GetInlinedParent();799 depth++;800 }801 return {};802}803 804void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {805 m_address = swap_from->m_address;806 m_should_resolve_indirect_functions =807 swap_from->m_should_resolve_indirect_functions;808 m_is_reexported = swap_from->m_is_reexported;809 m_is_indirect = swap_from->m_is_indirect;810 m_user_expression_sp.reset();811}812 813void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) {814 if (thread_id != LLDB_INVALID_THREAD_ID) {815 GetLocationOptions().SetThreadID(thread_id);816 } else {817 // If we're resetting this to an invalid thread id, then don't make an818 // options pointer just to do that.819 if (m_options_up != nullptr)820 m_options_up->SetThreadID(thread_id);821 }822}823