1 //===-- BreakpointLocation.cpp ----------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Breakpoint/BreakpointLocation.h"
11 #include "lldb/Breakpoint/BreakpointID.h"
12 #include "lldb/Breakpoint/StoppointCallbackContext.h"
13 #include "lldb/Core/Debugger.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/ValueObject.h"
16 #include "lldb/Expression/DiagnosticManager.h"
17 #include "lldb/Expression/ExpressionVariable.h"
18 #include "lldb/Expression/UserExpression.h"
19 #include "lldb/Symbol/CompileUnit.h"
20 #include "lldb/Symbol/Symbol.h"
21 #include "lldb/Symbol/TypeSystem.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
25 #include "lldb/Target/ThreadSpec.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 : StoppointLocation(loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()),
36 hardware),
37 m_being_created(true), m_should_resolve_indirect_functions(false),
38 m_is_reexported(false), m_is_indirect(false), m_address(addr),
39 m_owner(owner), m_options_ap(), m_bp_site_sp(), m_condition_mutex() {
40 if (check_for_resolver) {
41 Symbol *symbol = m_address.CalculateSymbolContextSymbol();
42 if (symbol && symbol->IsIndirect()) {
43 SetShouldResolveIndirectFunctions(true);
44 }
45 }
46
47 SetThreadID(tid);
48 m_being_created = false;
49 }
50
~BreakpointLocation()51 BreakpointLocation::~BreakpointLocation() { ClearBreakpointSite(); }
52
GetLoadAddress() const53 lldb::addr_t BreakpointLocation::GetLoadAddress() const {
54 return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
55 }
56
57 const BreakpointOptions *
GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind) const58 BreakpointLocation::GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind)
59 const {
60 if (m_options_ap && m_options_ap->IsOptionSet(kind))
61 return m_options_ap.get();
62 else
63 return m_owner.GetOptions();
64 }
65
GetAddress()66 Address &BreakpointLocation::GetAddress() { return m_address; }
67
GetBreakpoint()68 Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }
69
GetTarget()70 Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }
71
IsEnabled() const72 bool BreakpointLocation::IsEnabled() const {
73 if (!m_owner.IsEnabled())
74 return false;
75 else if (m_options_ap.get() != nullptr)
76 return m_options_ap->IsEnabled();
77 else
78 return true;
79 }
80
SetEnabled(bool enabled)81 void BreakpointLocation::SetEnabled(bool enabled) {
82 GetLocationOptions()->SetEnabled(enabled);
83 if (enabled) {
84 ResolveBreakpointSite();
85 } else {
86 ClearBreakpointSite();
87 }
88 SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
89 : eBreakpointEventTypeDisabled);
90 }
91
IsAutoContinue() const92 bool BreakpointLocation::IsAutoContinue() const {
93 if (m_options_ap
94 && m_options_ap->IsOptionSet(BreakpointOptions::eAutoContinue))
95 return m_options_ap->IsAutoContinue();
96 else
97 return m_owner.IsAutoContinue();
98 }
99
SetAutoContinue(bool auto_continue)100 void BreakpointLocation::SetAutoContinue(bool auto_continue) {
101 GetLocationOptions()->SetAutoContinue(auto_continue);
102 SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
103 }
104
SetThreadID(lldb::tid_t thread_id)105 void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
106 if (thread_id != LLDB_INVALID_THREAD_ID)
107 GetLocationOptions()->SetThreadID(thread_id);
108 else {
109 // If we're resetting this to an invalid thread id, then don't make an
110 // options pointer just to do that.
111 if (m_options_ap.get() != nullptr)
112 m_options_ap->SetThreadID(thread_id);
113 }
114 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
115 }
116
GetThreadID()117 lldb::tid_t BreakpointLocation::GetThreadID() {
118 const ThreadSpec *thread_spec =
119 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
120 ->GetThreadSpecNoCreate();
121 if (thread_spec)
122 return thread_spec->GetTID();
123 else
124 return LLDB_INVALID_THREAD_ID;
125 }
126
SetThreadIndex(uint32_t index)127 void BreakpointLocation::SetThreadIndex(uint32_t index) {
128 if (index != 0)
129 GetLocationOptions()->GetThreadSpec()->SetIndex(index);
130 else {
131 // If we're resetting this to an invalid thread id, then don't make an
132 // options pointer just to do that.
133 if (m_options_ap.get() != nullptr)
134 m_options_ap->GetThreadSpec()->SetIndex(index);
135 }
136 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
137 }
138
GetThreadIndex() const139 uint32_t BreakpointLocation::GetThreadIndex() const {
140 const ThreadSpec *thread_spec =
141 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
142 ->GetThreadSpecNoCreate();
143 if (thread_spec)
144 return thread_spec->GetIndex();
145 else
146 return 0;
147 }
148
SetThreadName(const char * thread_name)149 void BreakpointLocation::SetThreadName(const char *thread_name) {
150 if (thread_name != nullptr)
151 GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
152 else {
153 // If we're resetting this to an invalid thread id, then don't make an
154 // options pointer just to do that.
155 if (m_options_ap.get() != nullptr)
156 m_options_ap->GetThreadSpec()->SetName(thread_name);
157 }
158 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
159 }
160
GetThreadName() const161 const char *BreakpointLocation::GetThreadName() const {
162 const ThreadSpec *thread_spec =
163 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
164 ->GetThreadSpecNoCreate();
165 if (thread_spec)
166 return thread_spec->GetName();
167 else
168 return nullptr;
169 }
170
SetQueueName(const char * queue_name)171 void BreakpointLocation::SetQueueName(const char *queue_name) {
172 if (queue_name != nullptr)
173 GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
174 else {
175 // If we're resetting this to an invalid thread id, then don't make an
176 // options pointer just to do that.
177 if (m_options_ap.get() != nullptr)
178 m_options_ap->GetThreadSpec()->SetQueueName(queue_name);
179 }
180 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
181 }
182
GetQueueName() const183 const char *BreakpointLocation::GetQueueName() const {
184 const ThreadSpec *thread_spec =
185 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
186 ->GetThreadSpecNoCreate();
187 if (thread_spec)
188 return thread_spec->GetQueueName();
189 else
190 return nullptr;
191 }
192
InvokeCallback(StoppointCallbackContext * context)193 bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
194 if (m_options_ap.get() != nullptr && m_options_ap->HasCallback())
195 return m_options_ap->InvokeCallback(context, m_owner.GetID(), GetID());
196 else
197 return m_owner.InvokeCallback(context, GetID());
198 }
199
SetCallback(BreakpointHitCallback callback,void * baton,bool is_synchronous)200 void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
201 void *baton, bool is_synchronous) {
202 // The default "Baton" class will keep a copy of "baton" and won't free or
203 // delete it when it goes goes out of scope.
204 GetLocationOptions()->SetCallback(
205 callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
206 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
207 }
208
SetCallback(BreakpointHitCallback callback,const BatonSP & baton_sp,bool is_synchronous)209 void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
210 const BatonSP &baton_sp,
211 bool is_synchronous) {
212 GetLocationOptions()->SetCallback(callback, baton_sp, is_synchronous);
213 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
214 }
215
ClearCallback()216 void BreakpointLocation::ClearCallback() {
217 GetLocationOptions()->ClearCallback();
218 }
219
SetCondition(const char * condition)220 void BreakpointLocation::SetCondition(const char *condition) {
221 GetLocationOptions()->SetCondition(condition);
222 SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
223 }
224
GetConditionText(size_t * hash) const225 const char *BreakpointLocation::GetConditionText(size_t *hash) const {
226 return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
227 ->GetConditionText(hash);
228 }
229
ConditionSaysStop(ExecutionContext & exe_ctx,Status & error)230 bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
231 Status &error) {
232 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
233
234 std::lock_guard<std::mutex> guard(m_condition_mutex);
235
236 size_t condition_hash;
237 const char *condition_text = GetConditionText(&condition_hash);
238
239 if (!condition_text) {
240 m_user_expression_sp.reset();
241 return false;
242 }
243
244 error.Clear();
245
246 DiagnosticManager diagnostics;
247
248 if (condition_hash != m_condition_hash || !m_user_expression_sp ||
249 !m_user_expression_sp->MatchesContext(exe_ctx)) {
250 LanguageType language = eLanguageTypeUnknown;
251 // See if we can figure out the language from the frame, otherwise use the
252 // default language:
253 CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
254 if (comp_unit)
255 language = comp_unit->GetLanguage();
256
257 m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
258 condition_text, llvm::StringRef(), language, Expression::eResultTypeAny,
259 EvaluateExpressionOptions(), error));
260 if (error.Fail()) {
261 if (log)
262 log->Printf("Error getting condition expression: %s.",
263 error.AsCString());
264 m_user_expression_sp.reset();
265 return true;
266 }
267
268 if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
269 eExecutionPolicyOnlyWhenNeeded, true,
270 false)) {
271 error.SetErrorStringWithFormat(
272 "Couldn't parse conditional expression:\n%s",
273 diagnostics.GetString().c_str());
274 m_user_expression_sp.reset();
275 return true;
276 }
277
278 m_condition_hash = condition_hash;
279 }
280
281 // We need to make sure the user sees any parse errors in their condition, so
282 // we'll hook the constructor errors up to the debugger's Async I/O.
283
284 ValueObjectSP result_value_sp;
285
286 EvaluateExpressionOptions options;
287 options.SetUnwindOnError(true);
288 options.SetIgnoreBreakpoints(true);
289 options.SetTryAllThreads(true);
290 options.SetResultIsInternal(
291 true); // Don't generate a user variable for condition expressions.
292
293 Status expr_error;
294
295 diagnostics.Clear();
296
297 ExpressionVariableSP result_variable_sp;
298
299 ExpressionResults result_code = m_user_expression_sp->Execute(
300 diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);
301
302 bool ret;
303
304 if (result_code == eExpressionCompleted) {
305 if (!result_variable_sp) {
306 error.SetErrorString("Expression did not return a result");
307 return false;
308 }
309
310 result_value_sp = result_variable_sp->GetValueObject();
311
312 if (result_value_sp) {
313 ret = result_value_sp->IsLogicalTrue(error);
314 if (log) {
315 if (error.Success()) {
316 log->Printf("Condition successfully evaluated, result is %s.\n",
317 ret ? "true" : "false");
318 } else {
319 error.SetErrorString(
320 "Failed to get an integer result from the expression");
321 ret = false;
322 }
323 }
324 } else {
325 ret = false;
326 error.SetErrorString("Failed to get any result from the expression");
327 }
328 } else {
329 ret = false;
330 error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
331 diagnostics.GetString().c_str());
332 }
333
334 return ret;
335 }
336
GetIgnoreCount()337 uint32_t BreakpointLocation::GetIgnoreCount() {
338 return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
339 ->GetIgnoreCount();
340 }
341
SetIgnoreCount(uint32_t n)342 void BreakpointLocation::SetIgnoreCount(uint32_t n) {
343 GetLocationOptions()->SetIgnoreCount(n);
344 SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
345 }
346
DecrementIgnoreCount()347 void BreakpointLocation::DecrementIgnoreCount() {
348 if (m_options_ap.get() != nullptr) {
349 uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
350 if (loc_ignore != 0)
351 m_options_ap->SetIgnoreCount(loc_ignore - 1);
352 }
353 }
354
IgnoreCountShouldStop()355 bool BreakpointLocation::IgnoreCountShouldStop() {
356 if (m_options_ap.get() != nullptr) {
357 uint32_t loc_ignore = m_options_ap->GetIgnoreCount();
358 if (loc_ignore != 0) {
359 m_owner.DecrementIgnoreCount();
360 DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
361 // since it won't get a
362 // chance to.
363 return false;
364 }
365 }
366 return true;
367 }
368
GetLocationOptions()369 BreakpointOptions *BreakpointLocation::GetLocationOptions() {
370 // If we make the copy we don't copy the callbacks because that is
371 // potentially expensive and we don't want to do that for the simple case
372 // where someone is just disabling the location.
373 if (m_options_ap.get() == nullptr)
374 m_options_ap.reset(
375 new BreakpointOptions(false));
376
377 return m_options_ap.get();
378 }
379
ValidForThisThread(Thread * thread)380 bool BreakpointLocation::ValidForThisThread(Thread *thread) {
381 return thread
382 ->MatchesSpec(GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
383 ->GetThreadSpecNoCreate());
384 }
385
386 // RETURNS - true if we should stop at this breakpoint, false if we
387 // should continue. Note, we don't check the thread spec for the breakpoint
388 // here, since if the breakpoint is not for this thread, then the event won't
389 // even get reported, so the check is redundant.
390
ShouldStop(StoppointCallbackContext * context)391 bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
392 bool should_stop = true;
393 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
394
395 // Do this first, if a location is disabled, it shouldn't increment its hit
396 // count.
397 if (!IsEnabled())
398 return false;
399
400 if (!IgnoreCountShouldStop())
401 return false;
402
403 if (!m_owner.IgnoreCountShouldStop())
404 return false;
405
406 // We only run synchronous callbacks in ShouldStop:
407 context->is_synchronous = true;
408 should_stop = InvokeCallback(context);
409
410 if (log) {
411 StreamString s;
412 GetDescription(&s, lldb::eDescriptionLevelVerbose);
413 log->Printf("Hit breakpoint location: %s, %s.\n", s.GetData(),
414 should_stop ? "stopping" : "continuing");
415 }
416
417 return should_stop;
418 }
419
BumpHitCount()420 void BreakpointLocation::BumpHitCount() {
421 if (IsEnabled()) {
422 // Step our hit count, and also step the hit count of the owner.
423 IncrementHitCount();
424 m_owner.IncrementHitCount();
425 }
426 }
427
UndoBumpHitCount()428 void BreakpointLocation::UndoBumpHitCount() {
429 if (IsEnabled()) {
430 // Step our hit count, and also step the hit count of the owner.
431 DecrementHitCount();
432 m_owner.DecrementHitCount();
433 }
434 }
435
IsResolved() const436 bool BreakpointLocation::IsResolved() const {
437 return m_bp_site_sp.get() != nullptr;
438 }
439
GetBreakpointSite() const440 lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
441 return m_bp_site_sp;
442 }
443
ResolveBreakpointSite()444 bool BreakpointLocation::ResolveBreakpointSite() {
445 if (m_bp_site_sp)
446 return true;
447
448 Process *process = m_owner.GetTarget().GetProcessSP().get();
449 if (process == nullptr)
450 return false;
451
452 lldb::break_id_t new_id =
453 process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());
454
455 if (new_id == LLDB_INVALID_BREAK_ID) {
456 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
457 if (log)
458 log->Warning("Tried to add breakpoint site at 0x%" PRIx64
459 " but it was already present.\n",
460 m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()));
461 return false;
462 }
463
464 return true;
465 }
466
SetBreakpointSite(BreakpointSiteSP & bp_site_sp)467 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
468 m_bp_site_sp = bp_site_sp;
469 SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
470 return true;
471 }
472
ClearBreakpointSite()473 bool BreakpointLocation::ClearBreakpointSite() {
474 if (m_bp_site_sp.get()) {
475 ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
476 // If the process exists, get it to remove the owner, it will remove the
477 // physical implementation of the breakpoint as well if there are no more
478 // owners. Otherwise just remove this owner.
479 if (process_sp)
480 process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(),
481 GetID(), m_bp_site_sp);
482 else
483 m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID());
484
485 m_bp_site_sp.reset();
486 return true;
487 }
488 return false;
489 }
490
GetDescription(Stream * s,lldb::DescriptionLevel level)491 void BreakpointLocation::GetDescription(Stream *s,
492 lldb::DescriptionLevel level) {
493 SymbolContext sc;
494
495 // If the description level is "initial" then the breakpoint is printing out
496 // our initial state, and we should let it decide how it wants to print our
497 // label.
498 if (level != eDescriptionLevelInitial) {
499 s->Indent();
500 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
501 }
502
503 if (level == lldb::eDescriptionLevelBrief)
504 return;
505
506 if (level != eDescriptionLevelInitial)
507 s->PutCString(": ");
508
509 if (level == lldb::eDescriptionLevelVerbose)
510 s->IndentMore();
511
512 if (m_address.IsSectionOffset()) {
513 m_address.CalculateSymbolContext(&sc);
514
515 if (level == lldb::eDescriptionLevelFull ||
516 level == eDescriptionLevelInitial) {
517 if (IsReExported())
518 s->PutCString("re-exported target = ");
519 else
520 s->PutCString("where = ");
521 sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
522 false, true, false, true, true);
523 } else {
524 if (sc.module_sp) {
525 s->EOL();
526 s->Indent("module = ");
527 sc.module_sp->GetFileSpec().Dump(s);
528 }
529
530 if (sc.comp_unit != nullptr) {
531 s->EOL();
532 s->Indent("compile unit = ");
533 static_cast<FileSpec *>(sc.comp_unit)->GetFilename().Dump(s);
534
535 if (sc.function != nullptr) {
536 s->EOL();
537 s->Indent("function = ");
538 s->PutCString(sc.function->GetName().AsCString("<unknown>"));
539 }
540
541 if (sc.line_entry.line > 0) {
542 s->EOL();
543 s->Indent("location = ");
544 sc.line_entry.DumpStopContext(s, true);
545 }
546
547 } else {
548 // If we don't have a comp unit, see if we have a symbol we can print.
549 if (sc.symbol) {
550 s->EOL();
551 if (IsReExported())
552 s->Indent("re-exported target = ");
553 else
554 s->Indent("symbol = ");
555 s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
556 }
557 }
558 }
559 }
560
561 if (level == lldb::eDescriptionLevelVerbose) {
562 s->EOL();
563 s->Indent();
564 }
565
566 if (m_address.IsSectionOffset() &&
567 (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
568 s->Printf(", ");
569 s->Printf("address = ");
570
571 ExecutionContextScope *exe_scope = nullptr;
572 Target *target = &m_owner.GetTarget();
573 if (target)
574 exe_scope = target->GetProcessSP().get();
575 if (exe_scope == nullptr)
576 exe_scope = target;
577
578 if (level == eDescriptionLevelInitial)
579 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
580 Address::DumpStyleFileAddress);
581 else
582 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
583 Address::DumpStyleModuleWithFileAddress);
584
585 if (IsIndirect() && m_bp_site_sp) {
586 Address resolved_address;
587 resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
588 Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
589 if (resolved_symbol) {
590 if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
591 s->Printf(", ");
592 else if (level == lldb::eDescriptionLevelVerbose) {
593 s->EOL();
594 s->Indent();
595 }
596 s->Printf("indirect target = %s",
597 resolved_symbol->GetName().GetCString());
598 }
599 }
600
601 if (level == lldb::eDescriptionLevelVerbose) {
602 s->EOL();
603 s->Indent();
604 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
605
606 s->Indent();
607 s->Printf("hit count = %-4u\n", GetHitCount());
608
609 if (m_options_ap.get()) {
610 s->Indent();
611 m_options_ap->GetDescription(s, level);
612 s->EOL();
613 }
614 s->IndentLess();
615 } else if (level != eDescriptionLevelInitial) {
616 s->Printf(", %sresolved, hit count = %u ", (IsResolved() ? "" : "un"),
617 GetHitCount());
618 if (m_options_ap.get()) {
619 m_options_ap->GetDescription(s, level);
620 }
621 }
622 }
623
Dump(Stream * s) const624 void BreakpointLocation::Dump(Stream *s) const {
625 if (s == nullptr)
626 return;
627
628 lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
629 ->GetThreadSpecNoCreate()->GetTID();
630 s->Printf(
631 "BreakpointLocation %u: tid = %4.4" PRIx64 " load addr = 0x%8.8" PRIx64
632 " state = %s type = %s breakpoint "
633 "hw_index = %i hit_count = %-4u ignore_count = %-4u",
634 GetID(), tid,
635 (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
636 (m_options_ap.get() ? m_options_ap->IsEnabled() : m_owner.IsEnabled())
637 ? "enabled "
638 : "disabled",
639 IsHardware() ? "hardware" : "software", GetHardwareIndex(), GetHitCount(),
640 GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
641 ->GetIgnoreCount());
642 }
643
SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind)644 void BreakpointLocation::SendBreakpointLocationChangedEvent(
645 lldb::BreakpointEventType eventKind) {
646 if (!m_being_created && !m_owner.IsInternal() &&
647 m_owner.GetTarget().EventTypeHasListeners(
648 Target::eBroadcastBitBreakpointChanged)) {
649 Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData(
650 eventKind, m_owner.shared_from_this());
651 data->GetBreakpointLocationCollection().Add(shared_from_this());
652 m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
653 data);
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