1 //===-- BreakpointLocation.cpp --------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
30 using namespace lldb_private
;
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);
46 m_being_created
= false;
49 BreakpointLocation::~BreakpointLocation() { ClearBreakpointSite(); }
51 lldb::addr_t
BreakpointLocation::GetLoadAddress() const {
52 return m_address
.GetOpcodeLoadAddress(&m_owner
.GetTarget());
55 const BreakpointOptions
&BreakpointLocation::GetOptionsSpecifyingKind(
56 BreakpointOptions::OptionKind kind
) const {
57 if (m_options_up
&& m_options_up
->IsOptionSet(kind
))
60 return m_owner
.GetOptions();
63 Address
&BreakpointLocation::GetAddress() { return m_address
; }
65 Breakpoint
&BreakpointLocation::GetBreakpoint() { return m_owner
; }
67 Target
&BreakpointLocation::GetTarget() { return m_owner
.GetTarget(); }
69 bool BreakpointLocation::IsEnabled() const {
70 if (!m_owner
.IsEnabled())
72 else if (m_options_up
!= nullptr)
73 return m_options_up
->IsEnabled();
78 void BreakpointLocation::SetEnabled(bool enabled
) {
79 GetLocationOptions().SetEnabled(enabled
);
81 ResolveBreakpointSite();
83 ClearBreakpointSite();
85 SendBreakpointLocationChangedEvent(enabled
? eBreakpointEventTypeEnabled
86 : eBreakpointEventTypeDisabled
);
89 bool BreakpointLocation::IsAutoContinue() const {
91 m_options_up
->IsOptionSet(BreakpointOptions::eAutoContinue
))
92 return m_options_up
->IsAutoContinue();
94 return m_owner
.IsAutoContinue();
97 void BreakpointLocation::SetAutoContinue(bool auto_continue
) {
98 GetLocationOptions().SetAutoContinue(auto_continue
);
99 SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged
);
102 void BreakpointLocation::SetThreadID(lldb::tid_t thread_id
) {
103 if (thread_id
!= LLDB_INVALID_THREAD_ID
)
104 GetLocationOptions().SetThreadID(thread_id
);
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
);
111 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged
);
114 lldb::tid_t
BreakpointLocation::GetThreadID() {
115 const ThreadSpec
*thread_spec
=
116 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
117 .GetThreadSpecNoCreate();
119 return thread_spec
->GetTID();
121 return LLDB_INVALID_THREAD_ID
;
124 void BreakpointLocation::SetThreadIndex(uint32_t index
) {
126 GetLocationOptions().GetThreadSpec()->SetIndex(index
);
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
);
133 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged
);
136 uint32_t BreakpointLocation::GetThreadIndex() const {
137 const ThreadSpec
*thread_spec
=
138 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
139 .GetThreadSpecNoCreate();
141 return thread_spec
->GetIndex();
146 void BreakpointLocation::SetThreadName(const char *thread_name
) {
147 if (thread_name
!= nullptr)
148 GetLocationOptions().GetThreadSpec()->SetName(thread_name
);
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
);
155 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged
);
158 const char *BreakpointLocation::GetThreadName() const {
159 const ThreadSpec
*thread_spec
=
160 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
161 .GetThreadSpecNoCreate();
163 return thread_spec
->GetName();
168 void BreakpointLocation::SetQueueName(const char *queue_name
) {
169 if (queue_name
!= nullptr)
170 GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name
);
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
);
177 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged
);
180 const char *BreakpointLocation::GetQueueName() const {
181 const ThreadSpec
*thread_spec
=
182 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
183 .GetThreadSpecNoCreate();
185 return thread_spec
->GetQueueName();
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());
194 return m_owner
.InvokeCallback(context
, GetID());
197 bool BreakpointLocation::IsCallbackSynchronous() {
198 if (m_options_up
!= nullptr && m_options_up
->HasCallback())
199 return m_options_up
->IsCallbackSynchronous();
201 return m_owner
.GetOptions().IsCallbackSynchronous();
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 out of scope.
208 GetLocationOptions().SetCallback(
209 callback
, std::make_shared
<UntypedBaton
>(baton
), is_synchronous
);
210 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged
);
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
);
220 void BreakpointLocation::ClearCallback() {
221 GetLocationOptions().ClearCallback();
224 void BreakpointLocation::SetCondition(const char *condition
) {
225 GetLocationOptions().SetCondition(condition
);
226 SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged
);
229 const char *BreakpointLocation::GetConditionText(size_t *hash
) const {
230 return GetOptionsSpecifyingKind(BreakpointOptions::eCondition
)
231 .GetConditionText(hash
);
234 bool BreakpointLocation::ConditionSaysStop(ExecutionContext
&exe_ctx
,
236 Log
*log
= GetLog(LLDBLog::Breakpoints
);
238 std::lock_guard
<std::mutex
> guard(m_condition_mutex
);
240 size_t condition_hash
;
241 const char *condition_text
= GetConditionText(&condition_hash
);
243 if (!condition_text
) {
244 m_user_expression_sp
.reset();
250 DiagnosticManager diagnostics
;
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
257 CompileUnit
*comp_unit
= m_address
.CalculateSymbolContextCompileUnit();
259 language
= comp_unit
->GetLanguage();
261 m_user_expression_sp
.reset(GetTarget().GetUserExpressionForLanguage(
262 condition_text
, llvm::StringRef(), language
, Expression::eResultTypeAny
,
263 EvaluateExpressionOptions(), nullptr, error
));
265 LLDB_LOGF(log
, "Error getting condition expression: %s.",
267 m_user_expression_sp
.reset();
271 if (!m_user_expression_sp
->Parse(diagnostics
, exe_ctx
,
272 eExecutionPolicyOnlyWhenNeeded
, true,
274 error
.SetErrorStringWithFormat(
275 "Couldn't parse conditional expression:\n%s",
276 diagnostics
.GetString().c_str());
277 m_user_expression_sp
.reset();
281 m_condition_hash
= condition_hash
;
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.
287 ValueObjectSP result_value_sp
;
289 EvaluateExpressionOptions options
;
290 options
.SetUnwindOnError(true);
291 options
.SetIgnoreBreakpoints(true);
292 options
.SetTryAllThreads(true);
293 options
.SetSuppressPersistentResult(
294 true); // Don't generate a user variable for condition expressions.
300 ExpressionVariableSP result_variable_sp
;
302 ExpressionResults result_code
= m_user_expression_sp
->Execute(
303 diagnostics
, exe_ctx
, options
, m_user_expression_sp
, result_variable_sp
);
307 if (result_code
== eExpressionCompleted
) {
308 if (!result_variable_sp
) {
309 error
.SetErrorString("Expression did not return a result");
313 result_value_sp
= result_variable_sp
->GetValueObject();
315 if (result_value_sp
) {
316 ret
= result_value_sp
->IsLogicalTrue(error
);
318 if (error
.Success()) {
319 LLDB_LOGF(log
, "Condition successfully evaluated, result is %s.\n",
320 ret
? "true" : "false");
322 error
.SetErrorString(
323 "Failed to get an integer result from the expression");
329 error
.SetErrorString("Failed to get any result from the expression");
333 error
.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
334 diagnostics
.GetString().c_str());
340 uint32_t BreakpointLocation::GetIgnoreCount() const {
341 return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount
)
345 void BreakpointLocation::SetIgnoreCount(uint32_t n
) {
346 GetLocationOptions().SetIgnoreCount(n
);
347 SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged
);
350 void BreakpointLocation::DecrementIgnoreCount() {
351 if (m_options_up
!= nullptr) {
352 uint32_t loc_ignore
= m_options_up
->GetIgnoreCount();
354 m_options_up
->SetIgnoreCount(loc_ignore
- 1);
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();
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.
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);
380 return *m_options_up
;
383 bool BreakpointLocation::ValidForThisThread(Thread
&thread
) {
384 return thread
.MatchesSpec(
385 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
386 .GetThreadSpecNoCreate());
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.
394 bool BreakpointLocation::ShouldStop(StoppointCallbackContext
*context
) {
395 bool should_stop
= true;
396 Log
*log
= GetLog(LLDBLog::Breakpoints
);
398 // Do this first, if a location is disabled, it shouldn't increment its hit
403 // We only run synchronous callbacks in ShouldStop:
404 context
->is_synchronous
= true;
405 should_stop
= InvokeCallback(context
);
409 GetDescription(&s
, lldb::eDescriptionLevelVerbose
);
410 LLDB_LOGF(log
, "Hit breakpoint location: %s, %s.\n", s
.GetData(),
411 should_stop
? "stopping" : "continuing");
417 void BreakpointLocation::BumpHitCount() {
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();
425 void BreakpointLocation::UndoBumpHitCount() {
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();
433 bool BreakpointLocation::IsResolved() const {
434 return m_bp_site_sp
.get() != nullptr;
437 lldb::BreakpointSiteSP
BreakpointLocation::GetBreakpointSite() const {
441 bool BreakpointLocation::ResolveBreakpointSite() {
445 Process
*process
= m_owner
.GetTarget().GetProcessSP().get();
446 if (process
== nullptr)
449 lldb::break_id_t new_id
=
450 process
->CreateBreakpointSite(shared_from_this(), m_owner
.IsHardware());
452 if (new_id
== LLDB_INVALID_BREAK_ID
) {
453 Log
*log
= GetLog(LLDBLog::Breakpoints
);
455 log
->Warning("Failed to add breakpoint site at 0x%" PRIx64
,
456 m_address
.GetOpcodeLoadAddress(&m_owner
.GetTarget()));
462 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP
&bp_site_sp
) {
463 m_bp_site_sp
= bp_site_sp
;
464 SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved
);
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.
475 process_sp
->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(),
476 GetID(), m_bp_site_sp
);
478 m_bp_site_sp
->RemoveOwner(GetBreakpoint().GetID(), GetID());
480 m_bp_site_sp
.reset();
486 void BreakpointLocation::GetDescription(Stream
*s
,
487 lldb::DescriptionLevel level
) {
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
493 if (level
!= eDescriptionLevelInitial
) {
495 BreakpointID::GetCanonicalReference(s
, m_owner
.GetID(), GetID());
498 if (level
== lldb::eDescriptionLevelBrief
)
501 if (level
!= eDescriptionLevelInitial
)
504 if (level
== lldb::eDescriptionLevelVerbose
)
507 if (m_address
.IsSectionOffset()) {
508 m_address
.CalculateSymbolContext(&sc
);
510 if (level
== lldb::eDescriptionLevelFull
||
511 level
== eDescriptionLevelInitial
) {
513 s
->PutCString("re-exported target = ");
515 s
->PutCString("where = ");
516 sc
.DumpStopContext(s
, m_owner
.GetTarget().GetProcessSP().get(), m_address
,
517 false, true, false, true, true);
521 s
->Indent("module = ");
522 sc
.module_sp
->GetFileSpec().Dump(s
->AsRawOstream());
525 if (sc
.comp_unit
!= nullptr) {
527 s
->Indent("compile unit = ");
528 sc
.comp_unit
->GetPrimaryFile().GetFilename().Dump(s
);
530 if (sc
.function
!= nullptr) {
532 s
->Indent("function = ");
533 s
->PutCString(sc
.function
->GetName().AsCString("<unknown>"));
536 if (sc
.line_entry
.line
> 0) {
538 s
->Indent("location = ");
539 sc
.line_entry
.DumpStopContext(s
, true);
543 // If we don't have a comp unit, see if we have a symbol we can print.
547 s
->Indent("re-exported target = ");
549 s
->Indent("symbol = ");
550 s
->PutCString(sc
.symbol
->GetName().AsCString("<unknown>"));
556 if (level
== lldb::eDescriptionLevelVerbose
) {
561 if (m_address
.IsSectionOffset() &&
562 (level
== eDescriptionLevelFull
|| level
== eDescriptionLevelInitial
))
564 s
->Printf("address = ");
566 ExecutionContextScope
*exe_scope
= nullptr;
567 Target
*target
= &m_owner
.GetTarget();
569 exe_scope
= target
->GetProcessSP().get();
570 if (exe_scope
== nullptr)
573 if (level
== eDescriptionLevelInitial
)
574 m_address
.Dump(s
, exe_scope
, Address::DumpStyleLoadAddress
,
575 Address::DumpStyleFileAddress
);
577 m_address
.Dump(s
, exe_scope
, Address::DumpStyleLoadAddress
,
578 Address::DumpStyleModuleWithFileAddress
);
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
)
587 else if (level
== lldb::eDescriptionLevelVerbose
) {
591 s
->Printf("indirect target = %s",
592 resolved_symbol
->GetName().GetCString());
596 bool is_resolved
= IsResolved();
597 bool is_hardware
= is_resolved
&& m_bp_site_sp
->IsHardware();
599 if (level
== lldb::eDescriptionLevelVerbose
) {
602 s
->Printf("resolved = %s\n", is_resolved
? "true" : "false");
604 s
->Printf("hardware = %s\n", is_hardware
? "true" : "false");
606 s
->Printf("hit count = %-4u\n", GetHitCount());
610 m_options_up
->GetDescription(s
, level
);
614 } else if (level
!= eDescriptionLevelInitial
) {
615 s
->Printf(", %sresolved, %shit count = %u ", (is_resolved
? "" : "un"),
616 (is_hardware
? "hardware, " : ""), GetHitCount());
618 m_options_up
->GetDescription(s
, level
);
623 void BreakpointLocation::Dump(Stream
*s
) const {
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
;
632 lldb::tid_t tid
= GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec
)
633 .GetThreadSpecNoCreate()
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",
639 (uint64_t)m_address
.GetOpcodeLoadAddress(&m_owner
.GetTarget()),
640 (m_options_up
? m_options_up
->IsEnabled() : m_owner
.IsEnabled())
643 is_hardware
? "hardware" : "software", hardware_index
,
645 GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount
)
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
,
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();