1 //===-- BreakpointLocation.cpp ----------------------------------*- C++ -*-===//
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/Log.h"
26 #include "lldb/Utility/StreamString.h"
29 using namespace lldb_private;
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 : StoppointLocation(loc_id, addr.GetOpcodeLoadAddress(&owner.GetTarget()),
36 m_being_created(true), m_should_resolve_indirect_functions(false),
37 m_is_reexported(false), m_is_indirect(false), m_address(addr),
38 m_owner(owner), m_options_up(), m_bp_site_sp(), m_condition_mutex() {
39 if (check_for_resolver) {
40 Symbol *symbol = m_address.CalculateSymbolContextSymbol();
41 if (symbol && symbol->IsIndirect()) {
42 SetShouldResolveIndirectFunctions(true);
47 m_being_created = false;
50 BreakpointLocation::~BreakpointLocation() { ClearBreakpointSite(); }
52 lldb::addr_t BreakpointLocation::GetLoadAddress() const {
53 return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
56 const BreakpointOptions *
57 BreakpointLocation::GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind)
59 if (m_options_up && m_options_up->IsOptionSet(kind))
60 return m_options_up.get();
62 return m_owner.GetOptions();
65 Address &BreakpointLocation::GetAddress() { return m_address; }
67 Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }
69 Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }
71 bool BreakpointLocation::IsEnabled() const {
72 if (!m_owner.IsEnabled())
74 else if (m_options_up != nullptr)
75 return m_options_up->IsEnabled();
80 void BreakpointLocation::SetEnabled(bool enabled) {
81 GetLocationOptions()->SetEnabled(enabled);
83 ResolveBreakpointSite();
85 ClearBreakpointSite();
87 SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
88 : eBreakpointEventTypeDisabled);
91 bool BreakpointLocation::IsAutoContinue() const {
93 m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue))
94 return m_options_up->IsAutoContinue();
96 return m_owner.IsAutoContinue();
99 void BreakpointLocation::SetAutoContinue(bool auto_continue) {
100 GetLocationOptions()->SetAutoContinue(auto_continue);
101 SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
104 void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
105 if (thread_id != LLDB_INVALID_THREAD_ID)
106 GetLocationOptions()->SetThreadID(thread_id);
108 // If we're resetting this to an invalid thread id, then don't make an
109 // options pointer just to do that.
110 if (m_options_up != nullptr)
111 m_options_up->SetThreadID(thread_id);
113 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
116 lldb::tid_t BreakpointLocation::GetThreadID() {
117 const ThreadSpec *thread_spec =
118 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
119 ->GetThreadSpecNoCreate();
121 return thread_spec->GetTID();
123 return LLDB_INVALID_THREAD_ID;
126 void BreakpointLocation::SetThreadIndex(uint32_t index) {
128 GetLocationOptions()->GetThreadSpec()->SetIndex(index);
130 // If we're resetting this to an invalid thread id, then don't make an
131 // options pointer just to do that.
132 if (m_options_up != nullptr)
133 m_options_up->GetThreadSpec()->SetIndex(index);
135 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
138 uint32_t BreakpointLocation::GetThreadIndex() const {
139 const ThreadSpec *thread_spec =
140 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
141 ->GetThreadSpecNoCreate();
143 return thread_spec->GetIndex();
148 void BreakpointLocation::SetThreadName(const char *thread_name) {
149 if (thread_name != nullptr)
150 GetLocationOptions()->GetThreadSpec()->SetName(thread_name);
152 // If we're resetting this to an invalid thread id, then don't make an
153 // options pointer just to do that.
154 if (m_options_up != nullptr)
155 m_options_up->GetThreadSpec()->SetName(thread_name);
157 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
160 const char *BreakpointLocation::GetThreadName() const {
161 const ThreadSpec *thread_spec =
162 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
163 ->GetThreadSpecNoCreate();
165 return thread_spec->GetName();
170 void BreakpointLocation::SetQueueName(const char *queue_name) {
171 if (queue_name != nullptr)
172 GetLocationOptions()->GetThreadSpec()->SetQueueName(queue_name);
174 // If we're resetting this to an invalid thread id, then don't make an
175 // options pointer just to do that.
176 if (m_options_up != nullptr)
177 m_options_up->GetThreadSpec()->SetQueueName(queue_name);
179 SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
182 const char *BreakpointLocation::GetQueueName() const {
183 const ThreadSpec *thread_spec =
184 GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
185 ->GetThreadSpecNoCreate();
187 return thread_spec->GetQueueName();
192 bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
193 if (m_options_up != nullptr && m_options_up->HasCallback())
194 return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID());
196 return m_owner.InvokeCallback(context, GetID());
199 void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
200 void *baton, bool is_synchronous) {
201 // The default "Baton" class will keep a copy of "baton" and won't free or
202 // delete it when it goes goes out of scope.
203 GetLocationOptions()->SetCallback(
204 callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
205 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
208 void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
209 const BatonSP &baton_sp,
210 bool is_synchronous) {
211 GetLocationOptions()->SetCallback(callback, baton_sp, is_synchronous);
212 SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
215 void BreakpointLocation::ClearCallback() {
216 GetLocationOptions()->ClearCallback();
219 void BreakpointLocation::SetCondition(const char *condition) {
220 GetLocationOptions()->SetCondition(condition);
221 SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
224 const char *BreakpointLocation::GetConditionText(size_t *hash) const {
225 return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
226 ->GetConditionText(hash);
229 bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
231 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
233 std::lock_guard<std::mutex> guard(m_condition_mutex);
235 size_t condition_hash;
236 const char *condition_text = GetConditionText(&condition_hash);
238 if (!condition_text) {
239 m_user_expression_sp.reset();
245 DiagnosticManager diagnostics;
247 if (condition_hash != m_condition_hash || !m_user_expression_sp ||
248 !m_user_expression_sp->MatchesContext(exe_ctx)) {
249 LanguageType language = eLanguageTypeUnknown;
250 // See if we can figure out the language from the frame, otherwise use the
252 CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
254 language = comp_unit->GetLanguage();
256 m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
257 condition_text, llvm::StringRef(), language, Expression::eResultTypeAny,
258 EvaluateExpressionOptions(), nullptr, error));
261 log->Printf("Error getting condition expression: %s.",
263 m_user_expression_sp.reset();
267 if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
268 eExecutionPolicyOnlyWhenNeeded, true,
270 error.SetErrorStringWithFormat(
271 "Couldn't parse conditional expression:\n%s",
272 diagnostics.GetString().c_str());
273 m_user_expression_sp.reset();
277 m_condition_hash = condition_hash;
280 // We need to make sure the user sees any parse errors in their condition, so
281 // we'll hook the constructor errors up to the debugger's Async I/O.
283 ValueObjectSP result_value_sp;
285 EvaluateExpressionOptions options;
286 options.SetUnwindOnError(true);
287 options.SetIgnoreBreakpoints(true);
288 options.SetTryAllThreads(true);
289 options.SetResultIsInternal(
290 true); // Don't generate a user variable for condition expressions.
296 ExpressionVariableSP result_variable_sp;
298 ExpressionResults result_code = m_user_expression_sp->Execute(
299 diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);
303 if (result_code == eExpressionCompleted) {
304 if (!result_variable_sp) {
305 error.SetErrorString("Expression did not return a result");
309 result_value_sp = result_variable_sp->GetValueObject();
311 if (result_value_sp) {
312 ret = result_value_sp->IsLogicalTrue(error);
314 if (error.Success()) {
315 log->Printf("Condition successfully evaluated, result is %s.\n",
316 ret ? "true" : "false");
318 error.SetErrorString(
319 "Failed to get an integer result from the expression");
325 error.SetErrorString("Failed to get any result from the expression");
329 error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
330 diagnostics.GetString().c_str());
336 uint32_t BreakpointLocation::GetIgnoreCount() {
337 return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
341 void BreakpointLocation::SetIgnoreCount(uint32_t n) {
342 GetLocationOptions()->SetIgnoreCount(n);
343 SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
346 void BreakpointLocation::DecrementIgnoreCount() {
347 if (m_options_up != nullptr) {
348 uint32_t loc_ignore = m_options_up->GetIgnoreCount();
350 m_options_up->SetIgnoreCount(loc_ignore - 1);
354 bool BreakpointLocation::IgnoreCountShouldStop() {
355 if (m_options_up != nullptr) {
356 uint32_t loc_ignore = m_options_up->GetIgnoreCount();
357 if (loc_ignore != 0) {
358 m_owner.DecrementIgnoreCount();
359 DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
360 // since it won't get a
368 BreakpointOptions *BreakpointLocation::GetLocationOptions() {
369 // If we make the copy we don't copy the callbacks because that is
370 // potentially expensive and we don't want to do that for the simple case
371 // where someone is just disabling the location.
372 if (m_options_up == nullptr)
373 m_options_up.reset(new BreakpointOptions(false));
375 return m_options_up.get();
378 bool BreakpointLocation::ValidForThisThread(Thread *thread) {
380 ->MatchesSpec(GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
381 ->GetThreadSpecNoCreate());
384 // RETURNS - true if we should stop at this breakpoint, false if we
385 // should continue. Note, we don't check the thread spec for the breakpoint
386 // here, since if the breakpoint is not for this thread, then the event won't
387 // even get reported, so the check is redundant.
389 bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
390 bool should_stop = true;
391 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
393 // Do this first, if a location is disabled, it shouldn't increment its hit
398 if (!IgnoreCountShouldStop())
401 if (!m_owner.IgnoreCountShouldStop())
404 // We only run synchronous callbacks in ShouldStop:
405 context->is_synchronous = true;
406 should_stop = InvokeCallback(context);
410 GetDescription(&s, lldb::eDescriptionLevelVerbose);
411 log->Printf("Hit breakpoint location: %s, %s.\n", s.GetData(),
412 should_stop ? "stopping" : "continuing");
418 void BreakpointLocation::BumpHitCount() {
420 // Step our hit count, and also step the hit count of the owner.
422 m_owner.IncrementHitCount();
426 void BreakpointLocation::UndoBumpHitCount() {
428 // Step our hit count, and also step the hit count of the owner.
430 m_owner.DecrementHitCount();
434 bool BreakpointLocation::IsResolved() const {
435 return m_bp_site_sp.get() != nullptr;
438 lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
442 bool BreakpointLocation::ResolveBreakpointSite() {
446 Process *process = m_owner.GetTarget().GetProcessSP().get();
447 if (process == nullptr)
450 lldb::break_id_t new_id =
451 process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());
453 if (new_id == LLDB_INVALID_BREAK_ID) {
454 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
456 log->Warning("Failed to add breakpoint site at 0x%" PRIx64,
457 m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()));
463 bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
464 m_bp_site_sp = bp_site_sp;
465 SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
469 bool BreakpointLocation::ClearBreakpointSite() {
470 if (m_bp_site_sp.get()) {
471 ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
472 // If the process exists, get it to remove the owner, it will remove the
473 // physical implementation of the breakpoint as well if there are no more
474 // owners. Otherwise just remove this owner.
476 process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(),
477 GetID(), m_bp_site_sp);
479 m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID());
481 m_bp_site_sp.reset();
487 void BreakpointLocation::GetDescription(Stream *s,
488 lldb::DescriptionLevel level) {
491 // If the description level is "initial" then the breakpoint is printing out
492 // our initial state, and we should let it decide how it wants to print our
494 if (level != eDescriptionLevelInitial) {
496 BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
499 if (level == lldb::eDescriptionLevelBrief)
502 if (level != eDescriptionLevelInitial)
505 if (level == lldb::eDescriptionLevelVerbose)
508 if (m_address.IsSectionOffset()) {
509 m_address.CalculateSymbolContext(&sc);
511 if (level == lldb::eDescriptionLevelFull ||
512 level == eDescriptionLevelInitial) {
514 s->PutCString("re-exported target = ");
516 s->PutCString("where = ");
517 sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
518 false, true, false, true, true);
522 s->Indent("module = ");
523 sc.module_sp->GetFileSpec().Dump(s);
526 if (sc.comp_unit != nullptr) {
528 s->Indent("compile unit = ");
529 static_cast<FileSpec *>(sc.comp_unit)->GetFilename().Dump(s);
531 if (sc.function != nullptr) {
533 s->Indent("function = ");
534 s->PutCString(sc.function->GetName().AsCString("<unknown>"));
537 if (sc.line_entry.line > 0) {
539 s->Indent("location = ");
540 sc.line_entry.DumpStopContext(s, true);
544 // If we don't have a comp unit, see if we have a symbol we can print.
548 s->Indent("re-exported target = ");
550 s->Indent("symbol = ");
551 s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
557 if (level == lldb::eDescriptionLevelVerbose) {
562 if (m_address.IsSectionOffset() &&
563 (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
565 s->Printf("address = ");
567 ExecutionContextScope *exe_scope = nullptr;
568 Target *target = &m_owner.GetTarget();
570 exe_scope = target->GetProcessSP().get();
571 if (exe_scope == nullptr)
574 if (level == eDescriptionLevelInitial)
575 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
576 Address::DumpStyleFileAddress);
578 m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
579 Address::DumpStyleModuleWithFileAddress);
581 if (IsIndirect() && m_bp_site_sp) {
582 Address resolved_address;
583 resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
584 Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
585 if (resolved_symbol) {
586 if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
588 else if (level == lldb::eDescriptionLevelVerbose) {
592 s->Printf("indirect target = %s",
593 resolved_symbol->GetName().GetCString());
597 if (level == lldb::eDescriptionLevelVerbose) {
600 s->Printf("resolved = %s\n", IsResolved() ? "true" : "false");
603 s->Printf("hit count = %-4u\n", GetHitCount());
607 m_options_up->GetDescription(s, level);
611 } else if (level != eDescriptionLevelInitial) {
612 s->Printf(", %sresolved, hit count = %u ", (IsResolved() ? "" : "un"),
615 m_options_up->GetDescription(s, level);
620 void BreakpointLocation::Dump(Stream *s) const {
624 lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
625 ->GetThreadSpecNoCreate()->GetTID();
626 s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
627 " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint "
628 "hw_index = %i hit_count = %-4u ignore_count = %-4u",
630 (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
631 (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
634 IsHardware() ? "hardware" : "software", GetHardwareIndex(),
636 GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
640 void BreakpointLocation::SendBreakpointLocationChangedEvent(
641 lldb::BreakpointEventType eventKind) {
642 if (!m_being_created && !m_owner.IsInternal() &&
643 m_owner.GetTarget().EventTypeHasListeners(
644 Target::eBroadcastBitBreakpointChanged)) {
645 Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData(
646 eventKind, m_owner.shared_from_this());
647 data->GetBreakpointLocationCollection().Add(shared_from_this());
648 m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
653 void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
654 m_address = swap_from->m_address;
655 m_should_resolve_indirect_functions =
656 swap_from->m_should_resolve_indirect_functions;
657 m_is_reexported = swap_from->m_is_reexported;
658 m_is_indirect = swap_from->m_is_indirect;
659 m_user_expression_sp.reset();