• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/Log.h"
26 #include "lldb/Utility/StreamString.h"
27 
28 using namespace lldb;
29 using namespace lldb_private;
30 
BreakpointLocation(break_id_t loc_id,Breakpoint & owner,const Address & addr,lldb::tid_t tid,bool hardware,bool check_for_resolver)31 BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner,
32                                        const Address &addr, lldb::tid_t tid,
33                                        bool hardware, bool check_for_resolver)
34     : m_being_created(true), m_should_resolve_indirect_functions(false),
35       m_is_reexported(false), m_is_indirect(false), m_address(addr),
36       m_owner(owner), m_options_up(), m_bp_site_sp(), m_condition_mutex(),
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   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 
55 const BreakpointOptions *
GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind) const56 BreakpointLocation::GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind)
57 const {
58   if (m_options_up && m_options_up->IsOptionSet(kind))
59     return m_options_up.get();
60   else
61     return m_owner.GetOptions();
62 }
63 
GetAddress()64 Address &BreakpointLocation::GetAddress() { return m_address; }
65 
GetBreakpoint()66 Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }
67 
GetTarget()68 Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }
69 
IsEnabled() const70 bool BreakpointLocation::IsEnabled() const {
71   if (!m_owner.IsEnabled())
72     return false;
73   else if (m_options_up != nullptr)
74     return m_options_up->IsEnabled();
75   else
76     return true;
77 }
78 
SetEnabled(bool enabled)79 void BreakpointLocation::SetEnabled(bool enabled) {
80   GetLocationOptions()->SetEnabled(enabled);
81   if (enabled) {
82     ResolveBreakpointSite();
83   } else {
84     ClearBreakpointSite();
85   }
86   SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
87                                              : eBreakpointEventTypeDisabled);
88 }
89 
IsAutoContinue() const90 bool BreakpointLocation::IsAutoContinue() const {
91   if (m_options_up &&
92       m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue))
93     return m_options_up->IsAutoContinue();
94   else
95     return m_owner.IsAutoContinue();
96 }
97 
SetAutoContinue(bool auto_continue)98 void BreakpointLocation::SetAutoContinue(bool auto_continue) {
99   GetLocationOptions()->SetAutoContinue(auto_continue);
100   SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
101 }
102 
SetThreadID(lldb::tid_t thread_id)103 void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
104   if (thread_id != LLDB_INVALID_THREAD_ID)
105     GetLocationOptions()->SetThreadID(thread_id);
106   else {
107     // If we're resetting this to an invalid thread id, then don't make an
108     // options pointer just to do that.
109     if (m_options_up != nullptr)
110       m_options_up->SetThreadID(thread_id);
111   }
112   SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
113 }
114 
GetThreadID()115 lldb::tid_t BreakpointLocation::GetThreadID() {
116   const ThreadSpec *thread_spec =
117       GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
118           ->GetThreadSpecNoCreate();
119   if (thread_spec)
120     return thread_spec->GetTID();
121   else
122     return LLDB_INVALID_THREAD_ID;
123 }
124 
SetThreadIndex(uint32_t index)125 void BreakpointLocation::SetThreadIndex(uint32_t index) {
126   if (index != 0)
127     GetLocationOptions()->GetThreadSpec()->SetIndex(index);
128   else {
129     // If we're resetting this to an invalid thread id, then don't make an
130     // options pointer just to do that.
131     if (m_options_up != nullptr)
132       m_options_up->GetThreadSpec()->SetIndex(index);
133   }
134   SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
135 }
136 
GetThreadIndex() const137 uint32_t BreakpointLocation::GetThreadIndex() const {
138   const ThreadSpec *thread_spec =
139       GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
140           ->GetThreadSpecNoCreate();
141   if (thread_spec)
142     return thread_spec->GetIndex();
143   else
144     return 0;
145 }
146 
SetThreadName(const char * thread_name)147 void BreakpointLocation::SetThreadName(const char *thread_name) {
148   if (thread_name != nullptr)
149     GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
150   else {
151     // If we're resetting this to an invalid thread id, then don't make an
152     // options pointer just to do that.
153     if (m_options_up != nullptr)
154       m_options_up->GetThreadSpec()->SetName(thread_name);
155   }
156   SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
157 }
158 
GetThreadName() const159 const char *BreakpointLocation::GetThreadName() const {
160   const ThreadSpec *thread_spec =
161       GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
162           ->GetThreadSpecNoCreate();
163   if (thread_spec)
164     return thread_spec->GetName();
165   else
166     return nullptr;
167 }
168 
SetQueueName(const char * queue_name)169 void BreakpointLocation::SetQueueName(const char *queue_name) {
170   if (queue_name != nullptr)
171     GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
172   else {
173     // If we're resetting this to an invalid thread id, then don't make an
174     // options pointer just to do that.
175     if (m_options_up != nullptr)
176       m_options_up->GetThreadSpec()->SetQueueName(queue_name);
177   }
178   SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
179 }
180 
GetQueueName() const181 const char *BreakpointLocation::GetQueueName() const {
182   const ThreadSpec *thread_spec =
183       GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
184           ->GetThreadSpecNoCreate();
185   if (thread_spec)
186     return thread_spec->GetQueueName();
187   else
188     return nullptr;
189 }
190 
InvokeCallback(StoppointCallbackContext * context)191 bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
192   if (m_options_up != nullptr && m_options_up->HasCallback())
193     return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID());
194   else
195     return m_owner.InvokeCallback(context, GetID());
196 }
197 
SetCallback(BreakpointHitCallback callback,void * baton,bool is_synchronous)198 void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
199                                      void *baton, bool is_synchronous) {
200   // The default "Baton" class will keep a copy of "baton" and won't free or
201   // delete it when it goes goes out of scope.
202   GetLocationOptions()->SetCallback(
203       callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
204   SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
205 }
206 
SetCallback(BreakpointHitCallback callback,const BatonSP & baton_sp,bool is_synchronous)207 void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
208                                      const BatonSP &baton_sp,
209                                      bool is_synchronous) {
210   GetLocationOptions()->SetCallback(callback, baton_sp, is_synchronous);
211   SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
212 }
213 
ClearCallback()214 void BreakpointLocation::ClearCallback() {
215   GetLocationOptions()->ClearCallback();
216 }
217 
SetCondition(const char * condition)218 void BreakpointLocation::SetCondition(const char *condition) {
219   GetLocationOptions()->SetCondition(condition);
220   SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
221 }
222 
GetConditionText(size_t * hash) const223 const char *BreakpointLocation::GetConditionText(size_t *hash) const {
224   return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
225       ->GetConditionText(hash);
226 }
227 
ConditionSaysStop(ExecutionContext & exe_ctx,Status & error)228 bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
229                                            Status &error) {
230   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
231 
232   std::lock_guard<std::mutex> guard(m_condition_mutex);
233 
234   size_t condition_hash;
235   const char *condition_text = GetConditionText(&condition_hash);
236 
237   if (!condition_text) {
238     m_user_expression_sp.reset();
239     return false;
240   }
241 
242   error.Clear();
243 
244   DiagnosticManager diagnostics;
245 
246   if (condition_hash != m_condition_hash || !m_user_expression_sp ||
247       !m_user_expression_sp->MatchesContext(exe_ctx)) {
248     LanguageType language = eLanguageTypeUnknown;
249     // See if we can figure out the language from the frame, otherwise use the
250     // default language:
251     CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
252     if (comp_unit)
253       language = comp_unit->GetLanguage();
254 
255     m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
256         condition_text, llvm::StringRef(), language, Expression::eResultTypeAny,
257         EvaluateExpressionOptions(), nullptr, error));
258     if (error.Fail()) {
259       LLDB_LOGF(log, "Error getting condition expression: %s.",
260                 error.AsCString());
261       m_user_expression_sp.reset();
262       return true;
263     }
264 
265     if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
266                                      eExecutionPolicyOnlyWhenNeeded, true,
267                                      false)) {
268       error.SetErrorStringWithFormat(
269           "Couldn't parse conditional expression:\n%s",
270           diagnostics.GetString().c_str());
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.SetResultIsInternal(
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.SetErrorString("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.SetErrorString(
317               "Failed to get an integer result from the expression");
318           ret = false;
319         }
320       }
321     } else {
322       ret = false;
323       error.SetErrorString("Failed to get any result from the expression");
324     }
325   } else {
326     ret = false;
327     error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
328                                    diagnostics.GetString().c_str());
329   }
330 
331   return ret;
332 }
333 
GetIgnoreCount() const334 uint32_t BreakpointLocation::GetIgnoreCount() const {
335   return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
336       ->GetIgnoreCount();
337 }
338 
SetIgnoreCount(uint32_t n)339 void BreakpointLocation::SetIgnoreCount(uint32_t n) {
340   GetLocationOptions()->SetIgnoreCount(n);
341   SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
342 }
343 
DecrementIgnoreCount()344 void BreakpointLocation::DecrementIgnoreCount() {
345   if (m_options_up != nullptr) {
346     uint32_t loc_ignore = m_options_up->GetIgnoreCount();
347     if (loc_ignore != 0)
348       m_options_up->SetIgnoreCount(loc_ignore - 1);
349   }
350 }
351 
IgnoreCountShouldStop()352 bool BreakpointLocation::IgnoreCountShouldStop() {
353   if (m_options_up != nullptr) {
354     uint32_t loc_ignore = m_options_up->GetIgnoreCount();
355     if (loc_ignore != 0) {
356       m_owner.DecrementIgnoreCount();
357       DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
358                               // since it won't get a
359                               // chance to.
360       return false;
361     }
362   }
363   return true;
364 }
365 
GetLocationOptions()366 BreakpointOptions *BreakpointLocation::GetLocationOptions() {
367   // If we make the copy we don't copy the callbacks because that is
368   // potentially expensive and we don't want to do that for the simple case
369   // where someone is just disabling the location.
370   if (m_options_up == nullptr)
371     m_options_up = std::make_unique<BreakpointOptions>(false);
372 
373   return m_options_up.get();
374 }
375 
ValidForThisThread(Thread * thread)376 bool BreakpointLocation::ValidForThisThread(Thread *thread) {
377   return thread
378       ->MatchesSpec(GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
379       ->GetThreadSpecNoCreate());
380 }
381 
382 // RETURNS - true if we should stop at this breakpoint, false if we
383 // should continue.  Note, we don't check the thread spec for the breakpoint
384 // here, since if the breakpoint is not for this thread, then the event won't
385 // even get reported, so the check is redundant.
386 
ShouldStop(StoppointCallbackContext * context)387 bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
388   bool should_stop = true;
389   Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
390 
391   // Do this first, if a location is disabled, it shouldn't increment its hit
392   // count.
393   if (!IsEnabled())
394     return false;
395 
396   if (!IgnoreCountShouldStop())
397     return false;
398 
399   if (!m_owner.IgnoreCountShouldStop())
400     return false;
401 
402   // We only run synchronous callbacks in ShouldStop:
403   context->is_synchronous = true;
404   should_stop = InvokeCallback(context);
405 
406   if (log) {
407     StreamString s;
408     GetDescription(&s, lldb::eDescriptionLevelVerbose);
409     LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
410               should_stop ? "stopping" : "continuing");
411   }
412 
413   return should_stop;
414 }
415 
BumpHitCount()416 void BreakpointLocation::BumpHitCount() {
417   if (IsEnabled()) {
418     // Step our hit count, and also step the hit count of the owner.
419     m_hit_counter.Increment();
420     m_owner.m_hit_counter.Increment();
421   }
422 }
423 
UndoBumpHitCount()424 void BreakpointLocation::UndoBumpHitCount() {
425   if (IsEnabled()) {
426     // Step our hit count, and also step the hit count of the owner.
427     m_hit_counter.Decrement();
428     m_owner.m_hit_counter.Decrement();
429   }
430 }
431 
IsResolved() const432 bool BreakpointLocation::IsResolved() const {
433   return m_bp_site_sp.get() != nullptr;
434 }
435 
GetBreakpointSite() const436 lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
437   return m_bp_site_sp;
438 }
439 
ResolveBreakpointSite()440 bool BreakpointLocation::ResolveBreakpointSite() {
441   if (m_bp_site_sp)
442     return true;
443 
444   Process *process = m_owner.GetTarget().GetProcessSP().get();
445   if (process == nullptr)
446     return false;
447 
448   lldb::break_id_t new_id =
449       process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());
450 
451   if (new_id == LLDB_INVALID_BREAK_ID) {
452     Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
453     if (log)
454       log->Warning("Failed to add breakpoint site at 0x%" PRIx64,
455                    m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()));
456   }
457 
458   return IsResolved();
459 }
460 
SetBreakpointSite(BreakpointSiteSP & bp_site_sp)461 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
462   m_bp_site_sp = bp_site_sp;
463   SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
464   return true;
465 }
466 
ClearBreakpointSite()467 bool BreakpointLocation::ClearBreakpointSite() {
468   if (m_bp_site_sp.get()) {
469     ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
470     // If the process exists, get it to remove the owner, it will remove the
471     // physical implementation of the breakpoint as well if there are no more
472     // owners.  Otherwise just remove this owner.
473     if (process_sp)
474       process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(),
475                                                 GetID(), m_bp_site_sp);
476     else
477       m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID());
478 
479     m_bp_site_sp.reset();
480     return true;
481   }
482   return false;
483 }
484 
GetDescription(Stream * s,lldb::DescriptionLevel level)485 void BreakpointLocation::GetDescription(Stream *s,
486                                         lldb::DescriptionLevel level) {
487   SymbolContext sc;
488 
489   // If the description level is "initial" then the breakpoint is printing out
490   // our initial state, and we should let it decide how it wants to print our
491   // label.
492   if (level != eDescriptionLevelInitial) {
493     s->Indent();
494     BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
495   }
496 
497   if (level == lldb::eDescriptionLevelBrief)
498     return;
499 
500   if (level != eDescriptionLevelInitial)
501     s->PutCString(": ");
502 
503   if (level == lldb::eDescriptionLevelVerbose)
504     s->IndentMore();
505 
506   if (m_address.IsSectionOffset()) {
507     m_address.CalculateSymbolContext(&sc);
508 
509     if (level == lldb::eDescriptionLevelFull ||
510         level == eDescriptionLevelInitial) {
511       if (IsReExported())
512         s->PutCString("re-exported target = ");
513       else
514         s->PutCString("where = ");
515       sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
516                          false, true, false, true, true);
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         }
534 
535         if (sc.line_entry.line > 0) {
536           s->EOL();
537           s->Indent("location = ");
538           sc.line_entry.DumpStopContext(s, true);
539         }
540 
541       } else {
542         // If we don't have a comp unit, see if we have a symbol we can print.
543         if (sc.symbol) {
544           s->EOL();
545           if (IsReExported())
546             s->Indent("re-exported target = ");
547           else
548             s->Indent("symbol = ");
549           s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
550         }
551       }
552     }
553   }
554 
555   if (level == lldb::eDescriptionLevelVerbose) {
556     s->EOL();
557     s->Indent();
558   }
559 
560   if (m_address.IsSectionOffset() &&
561       (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
562     s->Printf(", ");
563   s->Printf("address = ");
564 
565   ExecutionContextScope *exe_scope = nullptr;
566   Target *target = &m_owner.GetTarget();
567   if (target)
568     exe_scope = target->GetProcessSP().get();
569   if (exe_scope == nullptr)
570     exe_scope = target;
571 
572   if (level == eDescriptionLevelInitial)
573     m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
574                    Address::DumpStyleFileAddress);
575   else
576     m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
577                    Address::DumpStyleModuleWithFileAddress);
578 
579   if (IsIndirect() && m_bp_site_sp) {
580     Address resolved_address;
581     resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
582     Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
583     if (resolved_symbol) {
584       if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
585         s->Printf(", ");
586       else if (level == lldb::eDescriptionLevelVerbose) {
587         s->EOL();
588         s->Indent();
589       }
590       s->Printf("indirect target = %s",
591                 resolved_symbol->GetName().GetCString());
592     }
593   }
594 
595   bool is_resolved = IsResolved();
596   bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
597 
598   if (level == lldb::eDescriptionLevelVerbose) {
599     s->EOL();
600     s->Indent();
601     s->Printf("resolved = %s\n", is_resolved ? "true" : "false");
602     s->Indent();
603     s->Printf("hardware = %s\n", is_hardware ? "true" : "false");
604     s->Indent();
605     s->Printf("hit count = %-4u\n", GetHitCount());
606 
607     if (m_options_up) {
608       s->Indent();
609       m_options_up->GetDescription(s, level);
610       s->EOL();
611     }
612     s->IndentLess();
613   } else if (level != eDescriptionLevelInitial) {
614     s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"),
615               (is_hardware ? "hardware, " : ""), GetHitCount());
616     if (m_options_up) {
617       m_options_up->GetDescription(s, level);
618     }
619   }
620 }
621 
Dump(Stream * s) const622 void BreakpointLocation::Dump(Stream *s) const {
623   if (s == nullptr)
624     return;
625 
626   bool is_resolved = IsResolved();
627   bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
628   auto hardware_index = is_resolved ?
629       m_bp_site_sp->GetHardwareIndex() : LLDB_INVALID_INDEX32;
630 
631   lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
632       ->GetThreadSpecNoCreate()->GetTID();
633   s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
634             "  load addr = 0x%8.8" PRIx64 "  state = %s  type = %s breakpoint  "
635             "hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
636             GetID(), tid,
637             (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
638             (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
639                 ? "enabled "
640                 : "disabled",
641             is_hardware ? "hardware" : "software", hardware_index, GetHitCount(),
642             GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
643                 ->GetIgnoreCount());
644 }
645 
SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind)646 void BreakpointLocation::SendBreakpointLocationChangedEvent(
647     lldb::BreakpointEventType eventKind) {
648   if (!m_being_created && !m_owner.IsInternal() &&
649       m_owner.GetTarget().EventTypeHasListeners(
650           Target::eBroadcastBitBreakpointChanged)) {
651     Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData(
652         eventKind, m_owner.shared_from_this());
653     data->GetBreakpointLocationCollection().Add(shared_from_this());
654     m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
655                                        data);
656   }
657 }
658 
SwapLocation(BreakpointLocationSP swap_from)659 void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
660   m_address = swap_from->m_address;
661   m_should_resolve_indirect_functions =
662       swap_from->m_should_resolve_indirect_functions;
663   m_is_reexported = swap_from->m_is_reexported;
664   m_is_indirect = swap_from->m_is_indirect;
665   m_user_expression_sp.reset();
666 }
667