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/Expression/DiagnosticManager.h"
15 #include "lldb/Expression/ExpressionVariable.h"
16 #include "lldb/Expression/UserExpression.h"
17 #include "lldb/Symbol/CompileUnit.h"
18 #include "lldb/Symbol/Symbol.h"
19 #include "lldb/Symbol/TypeSystem.h"
20 #include "lldb/Target/Process.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Target/Thread.h"
23 #include "lldb/Target/ThreadSpec.h"
24 #include "lldb/Utility/LLDBLog.h"
25 #include "lldb/Utility/Log.h"
26 #include "lldb/Utility/StreamString.h"
27 #include "lldb/ValueObject/ValueObject.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 check_for_resolver)32 BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner,
33 const Address &addr, lldb::tid_t tid,
34 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() {
49 llvm::consumeError(ClearBreakpointSite());
50 }
51
GetLoadAddress() const52 lldb::addr_t BreakpointLocation::GetLoadAddress() const {
53 return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
54 }
55
GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind) const56 const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind(
57 BreakpointOptions::OptionKind kind) const {
58 if (m_options_up && m_options_up->IsOptionSet(kind))
59 return *m_options_up;
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 if (m_options_up != nullptr)
73 return m_options_up->IsEnabled();
74 return true;
75 }
76
SetEnabled(bool enabled)77 llvm::Error BreakpointLocation::SetEnabled(bool enabled) {
78 GetLocationOptions().SetEnabled(enabled);
79 llvm::Error error = enabled ? ResolveBreakpointSite() : ClearBreakpointSite();
80 SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
81 : eBreakpointEventTypeDisabled);
82 return error;
83 }
84
IsAutoContinue() const85 bool BreakpointLocation::IsAutoContinue() const {
86 if (m_options_up &&
87 m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue))
88 return m_options_up->IsAutoContinue();
89 return m_owner.IsAutoContinue();
90 }
91
SetAutoContinue(bool auto_continue)92 void BreakpointLocation::SetAutoContinue(bool auto_continue) {
93 GetLocationOptions().SetAutoContinue(auto_continue);
94 SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
95 }
96
SetThreadID(lldb::tid_t thread_id)97 void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
98 SetThreadIDInternal(thread_id);
99 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
100 }
101
GetThreadID()102 lldb::tid_t BreakpointLocation::GetThreadID() {
103 const ThreadSpec *thread_spec =
104 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
105 .GetThreadSpecNoCreate();
106 if (thread_spec)
107 return thread_spec->GetTID();
108 return LLDB_INVALID_THREAD_ID;
109 }
110
SetThreadIndex(uint32_t index)111 void BreakpointLocation::SetThreadIndex(uint32_t index) {
112 if (index != 0)
113 GetLocationOptions().GetThreadSpec()->SetIndex(index);
114 else {
115 // If we're resetting this to an invalid thread id, then don't make an
116 // options pointer just to do that.
117 if (m_options_up != nullptr)
118 m_options_up->GetThreadSpec()->SetIndex(index);
119 }
120 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
121 }
122
GetThreadIndex() const123 uint32_t BreakpointLocation::GetThreadIndex() const {
124 const ThreadSpec *thread_spec =
125 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
126 .GetThreadSpecNoCreate();
127 if (thread_spec)
128 return thread_spec->GetIndex();
129 return 0;
130 }
131
SetThreadName(const char * thread_name)132 void BreakpointLocation::SetThreadName(const char *thread_name) {
133 if (thread_name != nullptr)
134 GetLocationOptions().GetThreadSpec()->SetName(thread_name);
135 else {
136 // If we're resetting this to an invalid thread id, then don't make an
137 // options pointer just to do that.
138 if (m_options_up != nullptr)
139 m_options_up->GetThreadSpec()->SetName(thread_name);
140 }
141 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
142 }
143
GetThreadName() const144 const char *BreakpointLocation::GetThreadName() const {
145 const ThreadSpec *thread_spec =
146 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
147 .GetThreadSpecNoCreate();
148 if (thread_spec)
149 return thread_spec->GetName();
150 return nullptr;
151 }
152
SetQueueName(const char * queue_name)153 void BreakpointLocation::SetQueueName(const char *queue_name) {
154 if (queue_name != nullptr)
155 GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name);
156 else {
157 // If we're resetting this to an invalid thread id, then don't make an
158 // options pointer just to do that.
159 if (m_options_up != nullptr)
160 m_options_up->GetThreadSpec()->SetQueueName(queue_name);
161 }
162 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
163 }
164
GetQueueName() const165 const char *BreakpointLocation::GetQueueName() const {
166 const ThreadSpec *thread_spec =
167 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
168 .GetThreadSpecNoCreate();
169 if (thread_spec)
170 return thread_spec->GetQueueName();
171 return nullptr;
172 }
173
InvokeCallback(StoppointCallbackContext * context)174 bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
175 if (m_options_up != nullptr && m_options_up->HasCallback())
176 return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID());
177 return m_owner.InvokeCallback(context, GetID());
178 }
179
IsCallbackSynchronous()180 bool BreakpointLocation::IsCallbackSynchronous() {
181 if (m_options_up != nullptr && m_options_up->HasCallback())
182 return m_options_up->IsCallbackSynchronous();
183 return m_owner.GetOptions().IsCallbackSynchronous();
184 }
185
SetCallback(BreakpointHitCallback callback,void * baton,bool is_synchronous)186 void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
187 void *baton, bool is_synchronous) {
188 // The default "Baton" class will keep a copy of "baton" and won't free or
189 // delete it when it goes out of scope.
190 GetLocationOptions().SetCallback(
191 callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
192 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
193 }
194
SetCallback(BreakpointHitCallback callback,const BatonSP & baton_sp,bool is_synchronous)195 void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
196 const BatonSP &baton_sp,
197 bool is_synchronous) {
198 GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous);
199 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
200 }
201
ClearCallback()202 void BreakpointLocation::ClearCallback() {
203 GetLocationOptions().ClearCallback();
204 }
205
SetCondition(StopCondition condition)206 void BreakpointLocation::SetCondition(StopCondition condition) {
207 GetLocationOptions().SetCondition(std::move(condition));
208 SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
209 }
210
GetCondition() const211 const StopCondition &BreakpointLocation::GetCondition() const {
212 return GetOptionsSpecifyingKind(BreakpointOptions::eCondition).GetCondition();
213 }
214
ConditionSaysStop(ExecutionContext & exe_ctx,Status & error)215 bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
216 Status &error) {
217 Log *log = GetLog(LLDBLog::Breakpoints);
218
219 std::lock_guard<std::mutex> guard(m_condition_mutex);
220
221 StopCondition condition = GetCondition();
222
223 if (!condition) {
224 m_user_expression_sp.reset();
225 return false;
226 }
227
228 error.Clear();
229
230 DiagnosticManager diagnostics;
231
232 if (condition.GetHash() != m_condition_hash || !m_user_expression_sp ||
233 !m_user_expression_sp->IsParseCacheable() ||
234 !m_user_expression_sp->MatchesContext(exe_ctx)) {
235 LanguageType language = condition.GetLanguage();
236 if (language == lldb::eLanguageTypeUnknown) {
237 // See if we can figure out the language from the frame, otherwise use the
238 // default language:
239 if (CompileUnit *comp_unit =
240 m_address.CalculateSymbolContextCompileUnit())
241 language = comp_unit->GetLanguage();
242 }
243
244 m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
245 condition.GetText(), llvm::StringRef(), language,
246 Expression::eResultTypeAny, EvaluateExpressionOptions(), nullptr,
247 error));
248 if (error.Fail()) {
249 LLDB_LOGF(log, "Error getting condition expression: %s.",
250 error.AsCString());
251 m_user_expression_sp.reset();
252 return true;
253 }
254
255 if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
256 eExecutionPolicyOnlyWhenNeeded, true,
257 false)) {
258 error = Status::FromError(
259 diagnostics.GetAsError(lldb::eExpressionParseError,
260 "Couldn't parse conditional expression:"));
261
262 m_user_expression_sp.reset();
263 return true;
264 }
265
266 m_condition_hash = condition.GetHash();
267 }
268
269 // We need to make sure the user sees any parse errors in their condition, so
270 // we'll hook the constructor errors up to the debugger's Async I/O.
271
272 ValueObjectSP result_value_sp;
273
274 EvaluateExpressionOptions options;
275 options.SetUnwindOnError(true);
276 options.SetIgnoreBreakpoints(true);
277 options.SetTryAllThreads(true);
278 options.SetSuppressPersistentResult(
279 true); // Don't generate a user variable for condition expressions.
280
281 Status expr_error;
282
283 diagnostics.Clear();
284
285 ExpressionVariableSP result_variable_sp;
286
287 ExpressionResults result_code = m_user_expression_sp->Execute(
288 diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);
289
290 bool ret;
291
292 if (result_code == eExpressionCompleted) {
293 if (!result_variable_sp) {
294 error = Status::FromErrorString("Expression did not return a result");
295 return false;
296 }
297
298 result_value_sp = result_variable_sp->GetValueObject();
299
300 if (result_value_sp) {
301 ret = result_value_sp->IsLogicalTrue(error);
302 if (log) {
303 if (error.Success()) {
304 LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n",
305 ret ? "true" : "false");
306 } else {
307 error = Status::FromErrorString(
308 "Failed to get an integer result from the expression");
309 ret = false;
310 }
311 }
312 } else {
313 ret = false;
314 error = Status::FromErrorString(
315 "Failed to get any result from the expression");
316 }
317 } else {
318 ret = false;
319 error = Status::FromError(diagnostics.GetAsError(
320 lldb::eExpressionParseError, "Couldn't execute expression:"));
321 }
322
323 return ret;
324 }
325
GetIgnoreCount() const326 uint32_t BreakpointLocation::GetIgnoreCount() const {
327 return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
328 .GetIgnoreCount();
329 }
330
SetIgnoreCount(uint32_t n)331 void BreakpointLocation::SetIgnoreCount(uint32_t n) {
332 GetLocationOptions().SetIgnoreCount(n);
333 SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
334 }
335
DecrementIgnoreCount()336 void BreakpointLocation::DecrementIgnoreCount() {
337 if (m_options_up != nullptr) {
338 uint32_t loc_ignore = m_options_up->GetIgnoreCount();
339 if (loc_ignore != 0)
340 m_options_up->SetIgnoreCount(loc_ignore - 1);
341 }
342 }
343
IgnoreCountShouldStop()344 bool BreakpointLocation::IgnoreCountShouldStop() {
345 uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
346 uint32_t loc_ignore = 0;
347 if (m_options_up != nullptr)
348 loc_ignore = m_options_up->GetIgnoreCount();
349
350 if (loc_ignore != 0 || owner_ignore != 0) {
351 m_owner.DecrementIgnoreCount();
352 DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
353 // since it won't get a chance to.
354 return false;
355 }
356 return true;
357 }
358
GetLocationOptions()359 BreakpointOptions &BreakpointLocation::GetLocationOptions() {
360 // If we make the copy we don't copy the callbacks because that is
361 // potentially expensive and we don't want to do that for the simple case
362 // where someone is just disabling the location.
363 if (m_options_up == nullptr)
364 m_options_up = std::make_unique<BreakpointOptions>(false);
365
366 return *m_options_up;
367 }
368
ValidForThisThread(Thread & thread)369 bool BreakpointLocation::ValidForThisThread(Thread &thread) {
370 return thread.MatchesSpec(
371 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
372 .GetThreadSpecNoCreate());
373 }
374
375 // RETURNS - true if we should stop at this breakpoint, false if we
376 // should continue. Note, we don't check the thread spec for the breakpoint
377 // here, since if the breakpoint is not for this thread, then the event won't
378 // even get reported, so the check is redundant.
379
ShouldStop(StoppointCallbackContext * context)380 bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
381 bool should_stop = true;
382 Log *log = GetLog(LLDBLog::Breakpoints);
383
384 // Do this first, if a location is disabled, it shouldn't increment its hit
385 // count.
386 if (!IsEnabled())
387 return false;
388
389 // We only run synchronous callbacks in ShouldStop:
390 context->is_synchronous = true;
391 should_stop = InvokeCallback(context);
392
393 if (log) {
394 StreamString s;
395 GetDescription(&s, lldb::eDescriptionLevelVerbose);
396 LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
397 should_stop ? "stopping" : "continuing");
398 }
399
400 return should_stop;
401 }
402
BumpHitCount()403 void BreakpointLocation::BumpHitCount() {
404 if (IsEnabled()) {
405 // Step our hit count, and also step the hit count of the owner.
406 m_hit_counter.Increment();
407 m_owner.m_hit_counter.Increment();
408 }
409 }
410
UndoBumpHitCount()411 void BreakpointLocation::UndoBumpHitCount() {
412 if (IsEnabled()) {
413 // Step our hit count, and also step the hit count of the owner.
414 m_hit_counter.Decrement();
415 m_owner.m_hit_counter.Decrement();
416 }
417 }
418
IsResolved() const419 bool BreakpointLocation::IsResolved() const {
420 return m_bp_site_sp.get() != nullptr;
421 }
422
GetBreakpointSite() const423 lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
424 return m_bp_site_sp;
425 }
426
ResolveBreakpointSite()427 llvm::Error BreakpointLocation::ResolveBreakpointSite() {
428 if (m_bp_site_sp)
429 return llvm::Error::success();
430
431 Process *process = m_owner.GetTarget().GetProcessSP().get();
432 if (process == nullptr)
433 return llvm::createStringError("no process");
434
435 lldb::break_id_t new_id =
436 process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());
437
438 if (new_id == LLDB_INVALID_BREAK_ID)
439 return llvm::createStringError(
440 llvm::formatv("Failed to add breakpoint site at {0:x}",
441 m_address.GetOpcodeLoadAddress(&m_owner.GetTarget())));
442
443 if (!IsResolved())
444 return llvm::createStringError(
445 "breakpoint site created but location is still unresolved");
446
447 return llvm::Error::success();
448 }
449
SetBreakpointSite(BreakpointSiteSP & bp_site_sp)450 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
451 m_bp_site_sp = bp_site_sp;
452 SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
453 return true;
454 }
455
ClearBreakpointSite()456 llvm::Error BreakpointLocation::ClearBreakpointSite() {
457 if (!m_bp_site_sp)
458 return llvm::createStringError("no breakpoint site to clear");
459
460 // If the process exists, get it to remove the owner, it will remove the
461 // physical implementation of the breakpoint as well if there are no more
462 // owners. Otherwise just remove this owner.
463 if (ProcessSP process_sp = m_owner.GetTarget().GetProcessSP())
464 process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(),
465 GetID(), m_bp_site_sp);
466 else
467 m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID());
468
469 m_bp_site_sp.reset();
470 return llvm::Error::success();
471 }
472
GetDescription(Stream * s,lldb::DescriptionLevel level)473 void BreakpointLocation::GetDescription(Stream *s,
474 lldb::DescriptionLevel level) {
475 SymbolContext sc;
476
477 // If the description level is "initial" then the breakpoint is printing out
478 // our initial state, and we should let it decide how it wants to print our
479 // label.
480 if (level != eDescriptionLevelInitial) {
481 s->Indent();
482 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
483 }
484
485 if (level == lldb::eDescriptionLevelBrief)
486 return;
487
488 if (level != eDescriptionLevelInitial)
489 s->PutCString(": ");
490
491 if (level == lldb::eDescriptionLevelVerbose)
492 s->IndentMore();
493
494 if (m_address.IsSectionOffset()) {
495 m_address.CalculateSymbolContext(&sc);
496
497 if (level == lldb::eDescriptionLevelFull ||
498 level == eDescriptionLevelInitial) {
499 if (IsReExported())
500 s->PutCString("re-exported target = ");
501 else
502 s->PutCString("where = ");
503
504 // If there's a preferred line entry for printing, use that.
505 bool show_function_info = true;
506 if (auto preferred = GetPreferredLineEntry()) {
507 sc.line_entry = *preferred;
508 // FIXME: We're going to get the function name wrong when the preferred
509 // line entry is not the lowest one. For now, just leave the function
510 // out in this case, but we really should also figure out how to easily
511 // fake the function name here.
512 show_function_info = false;
513 }
514 sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
515 false, true, false, show_function_info,
516 show_function_info, show_function_info);
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 if (ConstString mangled_name =
534 sc.function->GetMangled().GetMangledName()) {
535 s->EOL();
536 s->Indent("mangled function = ");
537 s->PutCString(mangled_name.AsCString());
538 }
539 }
540
541 if (sc.line_entry.line > 0) {
542 s->EOL();
543 s->Indent("location = ");
544 if (auto preferred = GetPreferredLineEntry())
545 preferred->DumpStopContext(s, true);
546 else
547 sc.line_entry.DumpStopContext(s, true);
548 }
549
550 } else {
551 // If we don't have a comp unit, see if we have a symbol we can print.
552 if (sc.symbol) {
553 s->EOL();
554 if (IsReExported())
555 s->Indent("re-exported target = ");
556 else
557 s->Indent("symbol = ");
558 s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
559 }
560 }
561 }
562 }
563
564 if (level == lldb::eDescriptionLevelVerbose) {
565 s->EOL();
566 s->Indent();
567 }
568
569 if (m_address.IsSectionOffset() &&
570 (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
571 s->Printf(", ");
572 s->Printf("address = ");
573
574 ExecutionContextScope *exe_scope = nullptr;
575 Target *target = &m_owner.GetTarget();
576 if (target)
577 exe_scope = target->GetProcessSP().get();
578 if (exe_scope == nullptr)
579 exe_scope = target;
580
581 if (level == eDescriptionLevelInitial)
582 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
583 Address::DumpStyleFileAddress);
584 else
585 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
586 Address::DumpStyleModuleWithFileAddress);
587
588 if (IsIndirect() && m_bp_site_sp) {
589 Address resolved_address;
590 resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
591 Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
592 if (resolved_symbol) {
593 if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
594 s->Printf(", ");
595 else if (level == lldb::eDescriptionLevelVerbose) {
596 s->EOL();
597 s->Indent();
598 }
599 s->Printf("indirect target = %s",
600 resolved_symbol->GetName().GetCString());
601 }
602 }
603
604 bool is_resolved = IsResolved();
605 bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
606
607 if (level == lldb::eDescriptionLevelVerbose) {
608 s->EOL();
609 s->Indent();
610 s->Printf("resolved = %s\n", is_resolved ? "true" : "false");
611 s->Indent();
612 s->Printf("hardware = %s\n", is_hardware ? "true" : "false");
613 s->Indent();
614 s->Printf("hit count = %-4u\n", GetHitCount());
615
616 if (m_options_up) {
617 s->Indent();
618 m_options_up->GetDescription(s, level);
619 s->EOL();
620 }
621 s->IndentLess();
622 } else if (level != eDescriptionLevelInitial) {
623 s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"),
624 (is_hardware ? "hardware, " : ""), GetHitCount());
625 if (m_options_up) {
626 m_options_up->GetDescription(s, level);
627 }
628 }
629 }
630
Dump(Stream * s) const631 void BreakpointLocation::Dump(Stream *s) const {
632 if (s == nullptr)
633 return;
634
635 bool is_resolved = IsResolved();
636 bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
637
638 lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
639 .GetThreadSpecNoCreate()
640 ->GetTID();
641 s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
642 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint "
643 "hit_count = %-4u ignore_count = %-4u",
644 GetID(), tid,
645 (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
646 (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
647 ? "enabled "
648 : "disabled",
649 is_hardware ? "hardware" : "software", GetHitCount(),
650 GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
651 .GetIgnoreCount());
652 }
653
SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind)654 void BreakpointLocation::SendBreakpointLocationChangedEvent(
655 lldb::BreakpointEventType eventKind) {
656 if (!m_owner.IsInternal() && m_owner.GetTarget().EventTypeHasListeners(
657 Target::eBroadcastBitBreakpointChanged)) {
658 auto data_sp = std::make_shared<Breakpoint::BreakpointEventData>(
659 eventKind, m_owner.shared_from_this());
660 data_sp->GetBreakpointLocationCollection().Add(shared_from_this());
661 m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
662 data_sp);
663 }
664 }
665
GetSuggestedStackFrameIndex()666 std::optional<uint32_t> BreakpointLocation::GetSuggestedStackFrameIndex() {
667 auto preferred_opt = GetPreferredLineEntry();
668 if (!preferred_opt)
669 return {};
670 LineEntry preferred = *preferred_opt;
671 SymbolContext sc;
672 if (!m_address.CalculateSymbolContext(&sc))
673 return {};
674 // Don't return anything special if frame 0 is the preferred line entry.
675 // We not really telling the stack frame list to do anything special in that
676 // case.
677 if (!LineEntry::Compare(sc.line_entry, preferred))
678 return {};
679
680 if (!sc.block)
681 return {};
682
683 // Blocks have their line info in Declaration form, so make one here:
684 Declaration preferred_decl(preferred.GetFile(), preferred.line,
685 preferred.column);
686
687 uint32_t depth = 0;
688 Block *inlined_block = sc.block->GetContainingInlinedBlock();
689 while (inlined_block) {
690 // If we've moved to a block that this isn't the start of, that's not
691 // our inlining info or call site, so we can stop here.
692 Address start_address;
693 if (!inlined_block->GetStartAddress(start_address) ||
694 start_address != m_address)
695 return {};
696
697 const InlineFunctionInfo *info = inlined_block->GetInlinedFunctionInfo();
698 if (info) {
699 if (preferred_decl == info->GetDeclaration())
700 return depth;
701 if (preferred_decl == info->GetCallSite())
702 return depth + 1;
703 }
704 inlined_block = inlined_block->GetInlinedParent();
705 depth++;
706 }
707 return {};
708 }
709
SwapLocation(BreakpointLocationSP swap_from)710 void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
711 m_address = swap_from->m_address;
712 m_should_resolve_indirect_functions =
713 swap_from->m_should_resolve_indirect_functions;
714 m_is_reexported = swap_from->m_is_reexported;
715 m_is_indirect = swap_from->m_is_indirect;
716 m_user_expression_sp.reset();
717 }
718
SetThreadIDInternal(lldb::tid_t thread_id)719 void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) {
720 if (thread_id != LLDB_INVALID_THREAD_ID)
721 GetLocationOptions().SetThreadID(thread_id);
722 else {
723 // If we're resetting this to an invalid thread id, then don't make an
724 // options pointer just to do that.
725 if (m_options_up != nullptr)
726 m_options_up->SetThreadID(thread_id);
727 }
728 }
729