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