xref: /llvm-project/lldb/source/Breakpoint/BreakpointLocation.cpp (revision 7dbbd2b251412b7b0809aabe672f3f57f0805dbb)
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