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