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