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 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->MatchesContext(exe_ctx)) {
254 LanguageType language = eLanguageTypeUnknown;
255 // See if we can figure out the language from the frame, otherwise use the
256 // default language:
257 CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
258 if (comp_unit)
259 language = comp_unit->GetLanguage();
260
261 m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
262 condition_text, llvm::StringRef(), language, Expression::eResultTypeAny,
263 EvaluateExpressionOptions(), nullptr, error));
264 if (error.Fail()) {
265 LLDB_LOGF(log, "Error getting condition expression: %s.",
266 error.AsCString());
267 m_user_expression_sp.reset();
268 return true;
269 }
270
271 if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
272 eExecutionPolicyOnlyWhenNeeded, true,
273 false)) {
274 error.SetErrorStringWithFormat(
275 "Couldn't parse conditional expression:\n%s",
276 diagnostics.GetString().c_str());
277 m_user_expression_sp.reset();
278 return true;
279 }
280
281 m_condition_hash = condition_hash;
282 }
283
284 // We need to make sure the user sees any parse errors in their condition, so
285 // we'll hook the constructor errors up to the debugger's Async I/O.
286
287 ValueObjectSP result_value_sp;
288
289 EvaluateExpressionOptions options;
290 options.SetUnwindOnError(true);
291 options.SetIgnoreBreakpoints(true);
292 options.SetTryAllThreads(true);
293 options.SetResultIsInternal(
294 true); // Don't generate a user variable for condition expressions.
295
296 Status expr_error;
297
298 diagnostics.Clear();
299
300 ExpressionVariableSP result_variable_sp;
301
302 ExpressionResults result_code = m_user_expression_sp->Execute(
303 diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);
304
305 bool ret;
306
307 if (result_code == eExpressionCompleted) {
308 if (!result_variable_sp) {
309 error.SetErrorString("Expression did not return a result");
310 return false;
311 }
312
313 result_value_sp = result_variable_sp->GetValueObject();
314
315 if (result_value_sp) {
316 ret = result_value_sp->IsLogicalTrue(error);
317 if (log) {
318 if (error.Success()) {
319 LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n",
320 ret ? "true" : "false");
321 } else {
322 error.SetErrorString(
323 "Failed to get an integer result from the expression");
324 ret = false;
325 }
326 }
327 } else {
328 ret = false;
329 error.SetErrorString("Failed to get any result from the expression");
330 }
331 } else {
332 ret = false;
333 error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
334 diagnostics.GetString().c_str());
335 }
336
337 return ret;
338 }
339
GetIgnoreCount() const340 uint32_t BreakpointLocation::GetIgnoreCount() const {
341 return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
342 .GetIgnoreCount();
343 }
344
SetIgnoreCount(uint32_t n)345 void BreakpointLocation::SetIgnoreCount(uint32_t n) {
346 GetLocationOptions().SetIgnoreCount(n);
347 SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
348 }
349
DecrementIgnoreCount()350 void BreakpointLocation::DecrementIgnoreCount() {
351 if (m_options_up != nullptr) {
352 uint32_t loc_ignore = m_options_up->GetIgnoreCount();
353 if (loc_ignore != 0)
354 m_options_up->SetIgnoreCount(loc_ignore - 1);
355 }
356 }
357
IgnoreCountShouldStop()358 bool BreakpointLocation::IgnoreCountShouldStop() {
359 uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
360 uint32_t loc_ignore = 0;
361 if (m_options_up != nullptr)
362 loc_ignore = m_options_up->GetIgnoreCount();
363
364 if (loc_ignore != 0 || owner_ignore != 0) {
365 m_owner.DecrementIgnoreCount();
366 DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
367 // since it won't get a chance to.
368 return false;
369 }
370 return true;
371 }
372
GetLocationOptions()373 BreakpointOptions &BreakpointLocation::GetLocationOptions() {
374 // If we make the copy we don't copy the callbacks because that is
375 // potentially expensive and we don't want to do that for the simple case
376 // where someone is just disabling the location.
377 if (m_options_up == nullptr)
378 m_options_up = std::make_unique<BreakpointOptions>(false);
379
380 return *m_options_up;
381 }
382
ValidForThisThread(Thread & thread)383 bool BreakpointLocation::ValidForThisThread(Thread &thread) {
384 return thread.MatchesSpec(
385 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
386 .GetThreadSpecNoCreate());
387 }
388
389 // RETURNS - true if we should stop at this breakpoint, false if we
390 // should continue. Note, we don't check the thread spec for the breakpoint
391 // here, since if the breakpoint is not for this thread, then the event won't
392 // even get reported, so the check is redundant.
393
ShouldStop(StoppointCallbackContext * context)394 bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
395 bool should_stop = true;
396 Log *log = GetLog(LLDBLog::Breakpoints);
397
398 // Do this first, if a location is disabled, it shouldn't increment its hit
399 // count.
400 if (!IsEnabled())
401 return false;
402
403 // We only run synchronous callbacks in ShouldStop:
404 context->is_synchronous = true;
405 should_stop = InvokeCallback(context);
406
407 if (log) {
408 StreamString s;
409 GetDescription(&s, lldb::eDescriptionLevelVerbose);
410 LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
411 should_stop ? "stopping" : "continuing");
412 }
413
414 return should_stop;
415 }
416
BumpHitCount()417 void BreakpointLocation::BumpHitCount() {
418 if (IsEnabled()) {
419 // Step our hit count, and also step the hit count of the owner.
420 m_hit_counter.Increment();
421 m_owner.m_hit_counter.Increment();
422 }
423 }
424
UndoBumpHitCount()425 void BreakpointLocation::UndoBumpHitCount() {
426 if (IsEnabled()) {
427 // Step our hit count, and also step the hit count of the owner.
428 m_hit_counter.Decrement();
429 m_owner.m_hit_counter.Decrement();
430 }
431 }
432
IsResolved() const433 bool BreakpointLocation::IsResolved() const {
434 return m_bp_site_sp.get() != nullptr;
435 }
436
GetBreakpointSite() const437 lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
438 return m_bp_site_sp;
439 }
440
ResolveBreakpointSite()441 bool BreakpointLocation::ResolveBreakpointSite() {
442 if (m_bp_site_sp)
443 return true;
444
445 Process *process = m_owner.GetTarget().GetProcessSP().get();
446 if (process == nullptr)
447 return false;
448
449 lldb::break_id_t new_id =
450 process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());
451
452 if (new_id == LLDB_INVALID_BREAK_ID) {
453 Log *log = GetLog(LLDBLog::Breakpoints);
454 if (log)
455 log->Warning("Failed to add breakpoint site at 0x%" PRIx64,
456 m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()));
457 }
458
459 return IsResolved();
460 }
461
SetBreakpointSite(BreakpointSiteSP & bp_site_sp)462 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
463 m_bp_site_sp = bp_site_sp;
464 SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
465 return true;
466 }
467
ClearBreakpointSite()468 bool BreakpointLocation::ClearBreakpointSite() {
469 if (m_bp_site_sp.get()) {
470 ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
471 // If the process exists, get it to remove the owner, it will remove the
472 // physical implementation of the breakpoint as well if there are no more
473 // owners. Otherwise just remove this owner.
474 if (process_sp)
475 process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(),
476 GetID(), m_bp_site_sp);
477 else
478 m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID());
479
480 m_bp_site_sp.reset();
481 return true;
482 }
483 return false;
484 }
485
GetDescription(Stream * s,lldb::DescriptionLevel level)486 void BreakpointLocation::GetDescription(Stream *s,
487 lldb::DescriptionLevel level) {
488 SymbolContext sc;
489
490 // If the description level is "initial" then the breakpoint is printing out
491 // our initial state, and we should let it decide how it wants to print our
492 // label.
493 if (level != eDescriptionLevelInitial) {
494 s->Indent();
495 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
496 }
497
498 if (level == lldb::eDescriptionLevelBrief)
499 return;
500
501 if (level != eDescriptionLevelInitial)
502 s->PutCString(": ");
503
504 if (level == lldb::eDescriptionLevelVerbose)
505 s->IndentMore();
506
507 if (m_address.IsSectionOffset()) {
508 m_address.CalculateSymbolContext(&sc);
509
510 if (level == lldb::eDescriptionLevelFull ||
511 level == eDescriptionLevelInitial) {
512 if (IsReExported())
513 s->PutCString("re-exported target = ");
514 else
515 s->PutCString("where = ");
516 sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
517 false, true, false, true, true);
518 } else {
519 if (sc.module_sp) {
520 s->EOL();
521 s->Indent("module = ");
522 sc.module_sp->GetFileSpec().Dump(s->AsRawOstream());
523 }
524
525 if (sc.comp_unit != nullptr) {
526 s->EOL();
527 s->Indent("compile unit = ");
528 sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s);
529
530 if (sc.function != nullptr) {
531 s->EOL();
532 s->Indent("function = ");
533 s->PutCString(sc.function->GetName().AsCString("<unknown>"));
534 }
535
536 if (sc.line_entry.line > 0) {
537 s->EOL();
538 s->Indent("location = ");
539 sc.line_entry.DumpStopContext(s, true);
540 }
541
542 } else {
543 // If we don't have a comp unit, see if we have a symbol we can print.
544 if (sc.symbol) {
545 s->EOL();
546 if (IsReExported())
547 s->Indent("re-exported target = ");
548 else
549 s->Indent("symbol = ");
550 s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
551 }
552 }
553 }
554 }
555
556 if (level == lldb::eDescriptionLevelVerbose) {
557 s->EOL();
558 s->Indent();
559 }
560
561 if (m_address.IsSectionOffset() &&
562 (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
563 s->Printf(", ");
564 s->Printf("address = ");
565
566 ExecutionContextScope *exe_scope = nullptr;
567 Target *target = &m_owner.GetTarget();
568 if (target)
569 exe_scope = target->GetProcessSP().get();
570 if (exe_scope == nullptr)
571 exe_scope = target;
572
573 if (level == eDescriptionLevelInitial)
574 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
575 Address::DumpStyleFileAddress);
576 else
577 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
578 Address::DumpStyleModuleWithFileAddress);
579
580 if (IsIndirect() && m_bp_site_sp) {
581 Address resolved_address;
582 resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
583 Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
584 if (resolved_symbol) {
585 if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
586 s->Printf(", ");
587 else if (level == lldb::eDescriptionLevelVerbose) {
588 s->EOL();
589 s->Indent();
590 }
591 s->Printf("indirect target = %s",
592 resolved_symbol->GetName().GetCString());
593 }
594 }
595
596 bool is_resolved = IsResolved();
597 bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
598
599 if (level == lldb::eDescriptionLevelVerbose) {
600 s->EOL();
601 s->Indent();
602 s->Printf("resolved = %s\n", is_resolved ? "true" : "false");
603 s->Indent();
604 s->Printf("hardware = %s\n", is_hardware ? "true" : "false");
605 s->Indent();
606 s->Printf("hit count = %-4u\n", GetHitCount());
607
608 if (m_options_up) {
609 s->Indent();
610 m_options_up->GetDescription(s, level);
611 s->EOL();
612 }
613 s->IndentLess();
614 } else if (level != eDescriptionLevelInitial) {
615 s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"),
616 (is_hardware ? "hardware, " : ""), GetHitCount());
617 if (m_options_up) {
618 m_options_up->GetDescription(s, level);
619 }
620 }
621 }
622
Dump(Stream * s) const623 void BreakpointLocation::Dump(Stream *s) const {
624 if (s == nullptr)
625 return;
626
627 bool is_resolved = IsResolved();
628 bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
629 auto hardware_index = is_resolved ?
630 m_bp_site_sp->GetHardwareIndex() : LLDB_INVALID_INDEX32;
631
632 lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
633 .GetThreadSpecNoCreate()
634 ->GetTID();
635 s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
636 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint "
637 "hw_index = %i hit_count = %-4u ignore_count = %-4u",
638 GetID(), tid,
639 (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
640 (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
641 ? "enabled "
642 : "disabled",
643 is_hardware ? "hardware" : "software", hardware_index,
644 GetHitCount(),
645 GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
646 .GetIgnoreCount());
647 }
648
SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind)649 void BreakpointLocation::SendBreakpointLocationChangedEvent(
650 lldb::BreakpointEventType eventKind) {
651 if (!m_being_created && !m_owner.IsInternal() &&
652 m_owner.GetTarget().EventTypeHasListeners(
653 Target::eBroadcastBitBreakpointChanged)) {
654 Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData(
655 eventKind, m_owner.shared_from_this());
656 data->GetBreakpointLocationCollection().Add(shared_from_this());
657 m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
658 data);
659 }
660 }
661
SwapLocation(BreakpointLocationSP swap_from)662 void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
663 m_address = swap_from->m_address;
664 m_should_resolve_indirect_functions =
665 swap_from->m_should_resolve_indirect_functions;
666 m_is_reexported = swap_from->m_is_reexported;
667 m_is_indirect = swap_from->m_is_indirect;
668 m_user_expression_sp.reset();
669 }
670