xref: /freebsd/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocation.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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_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() { ClearBreakpointSite(); }
49 
GetLoadAddress() const50 lldb::addr_t BreakpointLocation::GetLoadAddress() const {
51   return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
52 }
53 
GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind) const54 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 
GetAddress()62 Address &BreakpointLocation::GetAddress() { return m_address; }
63 
GetBreakpoint()64 Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }
65 
GetTarget()66 Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }
67 
IsEnabled() const68 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 
SetEnabled(bool enabled)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 
IsAutoContinue() const88 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 
SetAutoContinue(bool auto_continue)96 void BreakpointLocation::SetAutoContinue(bool auto_continue) {
97   GetLocationOptions().SetAutoContinue(auto_continue);
98   SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
99 }
100 
SetThreadID(lldb::tid_t thread_id)101 void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
102   SetThreadIDInternal(thread_id);
103   SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
104 }
105 
GetThreadID()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 
SetThreadIndex(uint32_t index)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 
GetThreadIndex() const128 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 
SetThreadName(const char * thread_name)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 
GetThreadName() const150 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 
SetQueueName(const char * queue_name)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 
GetQueueName() const172 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 
InvokeCallback(StoppointCallbackContext * context)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 
IsCallbackSynchronous()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 
SetCallback(BreakpointHitCallback callback,void * baton,bool is_synchronous)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 
SetCallback(BreakpointHitCallback callback,const BatonSP & baton_sp,bool is_synchronous)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 
ClearCallback()212 void BreakpointLocation::ClearCallback() {
213   GetLocationOptions().ClearCallback();
214 }
215 
SetCondition(const char * condition)216 void BreakpointLocation::SetCondition(const char *condition) {
217   GetLocationOptions().SetCondition(condition);
218   SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
219 }
220 
GetConditionText(size_t * hash) const221 const char *BreakpointLocation::GetConditionText(size_t *hash) const {
222   return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
223       .GetConditionText(hash);
224 }
225 
ConditionSaysStop(ExecutionContext & exe_ctx,Status & error)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.SetErrorStringWithFormat(
268           "Couldn't parse conditional expression:\n%s",
269           diagnostics.GetString().c_str());
270       m_user_expression_sp.reset();
271       return true;
272     }
273 
274     m_condition_hash = condition_hash;
275   }
276 
277   // We need to make sure the user sees any parse errors in their condition, so
278   // we'll hook the constructor errors up to the debugger's Async I/O.
279 
280   ValueObjectSP result_value_sp;
281 
282   EvaluateExpressionOptions options;
283   options.SetUnwindOnError(true);
284   options.SetIgnoreBreakpoints(true);
285   options.SetTryAllThreads(true);
286   options.SetSuppressPersistentResult(
287       true); // Don't generate a user variable for condition expressions.
288 
289   Status expr_error;
290 
291   diagnostics.Clear();
292 
293   ExpressionVariableSP result_variable_sp;
294 
295   ExpressionResults result_code = m_user_expression_sp->Execute(
296       diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);
297 
298   bool ret;
299 
300   if (result_code == eExpressionCompleted) {
301     if (!result_variable_sp) {
302       error.SetErrorString("Expression did not return a result");
303       return false;
304     }
305 
306     result_value_sp = result_variable_sp->GetValueObject();
307 
308     if (result_value_sp) {
309       ret = result_value_sp->IsLogicalTrue(error);
310       if (log) {
311         if (error.Success()) {
312           LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n",
313                     ret ? "true" : "false");
314         } else {
315           error.SetErrorString(
316               "Failed to get an integer result from the expression");
317           ret = false;
318         }
319       }
320     } else {
321       ret = false;
322       error.SetErrorString("Failed to get any result from the expression");
323     }
324   } else {
325     ret = false;
326     error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
327                                    diagnostics.GetString().c_str());
328   }
329 
330   return ret;
331 }
332 
GetIgnoreCount() const333 uint32_t BreakpointLocation::GetIgnoreCount() const {
334   return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
335       .GetIgnoreCount();
336 }
337 
SetIgnoreCount(uint32_t n)338 void BreakpointLocation::SetIgnoreCount(uint32_t n) {
339   GetLocationOptions().SetIgnoreCount(n);
340   SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
341 }
342 
DecrementIgnoreCount()343 void BreakpointLocation::DecrementIgnoreCount() {
344   if (m_options_up != nullptr) {
345     uint32_t loc_ignore = m_options_up->GetIgnoreCount();
346     if (loc_ignore != 0)
347       m_options_up->SetIgnoreCount(loc_ignore - 1);
348   }
349 }
350 
IgnoreCountShouldStop()351 bool BreakpointLocation::IgnoreCountShouldStop() {
352   uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
353   uint32_t loc_ignore = 0;
354   if (m_options_up != nullptr)
355     loc_ignore = m_options_up->GetIgnoreCount();
356 
357   if (loc_ignore != 0 || owner_ignore != 0) {
358     m_owner.DecrementIgnoreCount();
359     DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
360                             // since it won't get a chance to.
361     return false;
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;
374 }
375 
ValidForThisThread(Thread & thread)376 bool BreakpointLocation::ValidForThisThread(Thread &thread) {
377   return thread.MatchesSpec(
378       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 = GetLog(LLDBLog::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   // We only run synchronous callbacks in ShouldStop:
397   context->is_synchronous = true;
398   should_stop = InvokeCallback(context);
399 
400   if (log) {
401     StreamString s;
402     GetDescription(&s, lldb::eDescriptionLevelVerbose);
403     LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
404               should_stop ? "stopping" : "continuing");
405   }
406 
407   return should_stop;
408 }
409 
BumpHitCount()410 void BreakpointLocation::BumpHitCount() {
411   if (IsEnabled()) {
412     // Step our hit count, and also step the hit count of the owner.
413     m_hit_counter.Increment();
414     m_owner.m_hit_counter.Increment();
415   }
416 }
417 
UndoBumpHitCount()418 void BreakpointLocation::UndoBumpHitCount() {
419   if (IsEnabled()) {
420     // Step our hit count, and also step the hit count of the owner.
421     m_hit_counter.Decrement();
422     m_owner.m_hit_counter.Decrement();
423   }
424 }
425 
IsResolved() const426 bool BreakpointLocation::IsResolved() const {
427   return m_bp_site_sp.get() != nullptr;
428 }
429 
GetBreakpointSite() const430 lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
431   return m_bp_site_sp;
432 }
433 
ResolveBreakpointSite()434 bool BreakpointLocation::ResolveBreakpointSite() {
435   if (m_bp_site_sp)
436     return true;
437 
438   Process *process = m_owner.GetTarget().GetProcessSP().get();
439   if (process == nullptr)
440     return false;
441 
442   lldb::break_id_t new_id =
443       process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());
444 
445   if (new_id == LLDB_INVALID_BREAK_ID) {
446     Log *log = GetLog(LLDBLog::Breakpoints);
447     if (log)
448       log->Warning("Failed to add breakpoint site at 0x%" PRIx64,
449                    m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()));
450   }
451 
452   return IsResolved();
453 }
454 
SetBreakpointSite(BreakpointSiteSP & bp_site_sp)455 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
456   m_bp_site_sp = bp_site_sp;
457   SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
458   return true;
459 }
460 
ClearBreakpointSite()461 bool BreakpointLocation::ClearBreakpointSite() {
462   if (m_bp_site_sp.get()) {
463     ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
464     // If the process exists, get it to remove the owner, it will remove the
465     // physical implementation of the breakpoint as well if there are no more
466     // owners.  Otherwise just remove this owner.
467     if (process_sp)
468       process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(),
469                                                       GetID(), m_bp_site_sp);
470     else
471       m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID());
472 
473     m_bp_site_sp.reset();
474     return true;
475   }
476   return false;
477 }
478 
GetDescription(Stream * s,lldb::DescriptionLevel level)479 void BreakpointLocation::GetDescription(Stream *s,
480                                         lldb::DescriptionLevel level) {
481   SymbolContext sc;
482 
483   // If the description level is "initial" then the breakpoint is printing out
484   // our initial state, and we should let it decide how it wants to print our
485   // label.
486   if (level != eDescriptionLevelInitial) {
487     s->Indent();
488     BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
489   }
490 
491   if (level == lldb::eDescriptionLevelBrief)
492     return;
493 
494   if (level != eDescriptionLevelInitial)
495     s->PutCString(": ");
496 
497   if (level == lldb::eDescriptionLevelVerbose)
498     s->IndentMore();
499 
500   if (m_address.IsSectionOffset()) {
501     m_address.CalculateSymbolContext(&sc);
502 
503     if (level == lldb::eDescriptionLevelFull ||
504         level == eDescriptionLevelInitial) {
505       if (IsReExported())
506         s->PutCString("re-exported target = ");
507       else
508         s->PutCString("where = ");
509       sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
510                          false, true, false, true, true, true);
511     } else {
512       if (sc.module_sp) {
513         s->EOL();
514         s->Indent("module = ");
515         sc.module_sp->GetFileSpec().Dump(s->AsRawOstream());
516       }
517 
518       if (sc.comp_unit != nullptr) {
519         s->EOL();
520         s->Indent("compile unit = ");
521         sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s);
522 
523         if (sc.function != nullptr) {
524           s->EOL();
525           s->Indent("function = ");
526           s->PutCString(sc.function->GetName().AsCString("<unknown>"));
527           if (ConstString mangled_name =
528                   sc.function->GetMangled().GetMangledName()) {
529             s->EOL();
530             s->Indent("mangled function = ");
531             s->PutCString(mangled_name.AsCString());
532           }
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 
629   lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
630                         .GetThreadSpecNoCreate()
631                         ->GetTID();
632   s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
633             "  load addr = 0x%8.8" PRIx64 "  state = %s  type = %s breakpoint  "
634             "hit_count = %-4u  ignore_count = %-4u",
635             GetID(), tid,
636             (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
637             (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
638                 ? "enabled "
639                 : "disabled",
640             is_hardware ? "hardware" : "software", GetHitCount(),
641             GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
642                 .GetIgnoreCount());
643 }
644 
SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind)645 void BreakpointLocation::SendBreakpointLocationChangedEvent(
646     lldb::BreakpointEventType eventKind) {
647   if (!m_owner.IsInternal() && m_owner.GetTarget().EventTypeHasListeners(
648                                    Target::eBroadcastBitBreakpointChanged)) {
649     auto data_sp = std::make_shared<Breakpoint::BreakpointEventData>(
650         eventKind, m_owner.shared_from_this());
651     data_sp->GetBreakpointLocationCollection().Add(shared_from_this());
652     m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
653                                        data_sp);
654   }
655 }
656 
SwapLocation(BreakpointLocationSP swap_from)657 void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
658   m_address = swap_from->m_address;
659   m_should_resolve_indirect_functions =
660       swap_from->m_should_resolve_indirect_functions;
661   m_is_reexported = swap_from->m_is_reexported;
662   m_is_indirect = swap_from->m_is_indirect;
663   m_user_expression_sp.reset();
664 }
665 
SetThreadIDInternal(lldb::tid_t thread_id)666 void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) {
667   if (thread_id != LLDB_INVALID_THREAD_ID)
668     GetLocationOptions().SetThreadID(thread_id);
669   else {
670     // If we're resetting this to an invalid thread id, then don't make an
671     // options pointer just to do that.
672     if (m_options_up != nullptr)
673       m_options_up->SetThreadID(thread_id);
674   }
675 }
676