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