15ffd83dbSDimitry Andric //===-- BreakpointLocation.cpp --------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h" 100b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointID.h" 110b57cec5SDimitry Andric #include "lldb/Breakpoint/StoppointCallbackContext.h" 120b57cec5SDimitry Andric #include "lldb/Core/Debugger.h" 130b57cec5SDimitry Andric #include "lldb/Core/Module.h" 140b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 150b57cec5SDimitry Andric #include "lldb/Expression/DiagnosticManager.h" 160b57cec5SDimitry Andric #include "lldb/Expression/ExpressionVariable.h" 170b57cec5SDimitry Andric #include "lldb/Expression/UserExpression.h" 180b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h" 190b57cec5SDimitry Andric #include "lldb/Symbol/Symbol.h" 200b57cec5SDimitry Andric #include "lldb/Symbol/TypeSystem.h" 210b57cec5SDimitry Andric #include "lldb/Target/Process.h" 220b57cec5SDimitry Andric #include "lldb/Target/Target.h" 230b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 240b57cec5SDimitry Andric #include "lldb/Target/ThreadSpec.h" 2581ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 260b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 270b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric using namespace lldb; 300b57cec5SDimitry Andric using namespace lldb_private; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner, 330b57cec5SDimitry Andric const Address &addr, lldb::tid_t tid, 340b57cec5SDimitry Andric bool hardware, bool check_for_resolver) 35*0fca6ea1SDimitry Andric : m_should_resolve_indirect_functions(false), m_is_reexported(false), 36*0fca6ea1SDimitry Andric m_is_indirect(false), m_address(addr), m_owner(owner), 37*0fca6ea1SDimitry Andric m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() { 380b57cec5SDimitry Andric if (check_for_resolver) { 390b57cec5SDimitry Andric Symbol *symbol = m_address.CalculateSymbolContextSymbol(); 400b57cec5SDimitry Andric if (symbol && symbol->IsIndirect()) { 410b57cec5SDimitry Andric SetShouldResolveIndirectFunctions(true); 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 45*0fca6ea1SDimitry Andric SetThreadIDInternal(tid); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric BreakpointLocation::~BreakpointLocation() { ClearBreakpointSite(); } 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric lldb::addr_t BreakpointLocation::GetLoadAddress() const { 510b57cec5SDimitry Andric return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 54fe6060f1SDimitry Andric const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind( 55fe6060f1SDimitry Andric BreakpointOptions::OptionKind kind) const { 560b57cec5SDimitry Andric if (m_options_up && m_options_up->IsOptionSet(kind)) 57fe6060f1SDimitry Andric return *m_options_up; 580b57cec5SDimitry Andric else 590b57cec5SDimitry Andric return m_owner.GetOptions(); 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric Address &BreakpointLocation::GetAddress() { return m_address; } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric bool BreakpointLocation::IsEnabled() const { 690b57cec5SDimitry Andric if (!m_owner.IsEnabled()) 700b57cec5SDimitry Andric return false; 710b57cec5SDimitry Andric else if (m_options_up != nullptr) 720b57cec5SDimitry Andric return m_options_up->IsEnabled(); 730b57cec5SDimitry Andric else 740b57cec5SDimitry Andric return true; 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric void BreakpointLocation::SetEnabled(bool enabled) { 78fe6060f1SDimitry Andric GetLocationOptions().SetEnabled(enabled); 790b57cec5SDimitry Andric if (enabled) { 800b57cec5SDimitry Andric ResolveBreakpointSite(); 810b57cec5SDimitry Andric } else { 820b57cec5SDimitry Andric ClearBreakpointSite(); 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled 850b57cec5SDimitry Andric : eBreakpointEventTypeDisabled); 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric bool BreakpointLocation::IsAutoContinue() const { 890b57cec5SDimitry Andric if (m_options_up && 900b57cec5SDimitry Andric m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue)) 910b57cec5SDimitry Andric return m_options_up->IsAutoContinue(); 920b57cec5SDimitry Andric else 930b57cec5SDimitry Andric return m_owner.IsAutoContinue(); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric void BreakpointLocation::SetAutoContinue(bool auto_continue) { 97fe6060f1SDimitry Andric GetLocationOptions().SetAutoContinue(auto_continue); 980b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) { 102*0fca6ea1SDimitry Andric SetThreadIDInternal(thread_id); 1030b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric lldb::tid_t BreakpointLocation::GetThreadID() { 1070b57cec5SDimitry Andric const ThreadSpec *thread_spec = 1080b57cec5SDimitry Andric GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 109fe6060f1SDimitry Andric .GetThreadSpecNoCreate(); 1100b57cec5SDimitry Andric if (thread_spec) 1110b57cec5SDimitry Andric return thread_spec->GetTID(); 1120b57cec5SDimitry Andric else 1130b57cec5SDimitry Andric return LLDB_INVALID_THREAD_ID; 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric void BreakpointLocation::SetThreadIndex(uint32_t index) { 1170b57cec5SDimitry Andric if (index != 0) 118fe6060f1SDimitry Andric GetLocationOptions().GetThreadSpec()->SetIndex(index); 1190b57cec5SDimitry Andric else { 1200b57cec5SDimitry Andric // If we're resetting this to an invalid thread id, then don't make an 1210b57cec5SDimitry Andric // options pointer just to do that. 1220b57cec5SDimitry Andric if (m_options_up != nullptr) 1230b57cec5SDimitry Andric m_options_up->GetThreadSpec()->SetIndex(index); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric uint32_t BreakpointLocation::GetThreadIndex() const { 1290b57cec5SDimitry Andric const ThreadSpec *thread_spec = 1300b57cec5SDimitry Andric GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 131fe6060f1SDimitry Andric .GetThreadSpecNoCreate(); 1320b57cec5SDimitry Andric if (thread_spec) 1330b57cec5SDimitry Andric return thread_spec->GetIndex(); 1340b57cec5SDimitry Andric else 1350b57cec5SDimitry Andric return 0; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric void BreakpointLocation::SetThreadName(const char *thread_name) { 1390b57cec5SDimitry Andric if (thread_name != nullptr) 140fe6060f1SDimitry Andric GetLocationOptions().GetThreadSpec()->SetName(thread_name); 1410b57cec5SDimitry Andric else { 1420b57cec5SDimitry Andric // If we're resetting this to an invalid thread id, then don't make an 1430b57cec5SDimitry Andric // options pointer just to do that. 1440b57cec5SDimitry Andric if (m_options_up != nullptr) 1450b57cec5SDimitry Andric m_options_up->GetThreadSpec()->SetName(thread_name); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric const char *BreakpointLocation::GetThreadName() const { 1510b57cec5SDimitry Andric const ThreadSpec *thread_spec = 1520b57cec5SDimitry Andric GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 153fe6060f1SDimitry Andric .GetThreadSpecNoCreate(); 1540b57cec5SDimitry Andric if (thread_spec) 1550b57cec5SDimitry Andric return thread_spec->GetName(); 1560b57cec5SDimitry Andric else 1570b57cec5SDimitry Andric return nullptr; 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric void BreakpointLocation::SetQueueName(const char *queue_name) { 1610b57cec5SDimitry Andric if (queue_name != nullptr) 162fe6060f1SDimitry Andric GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name); 1630b57cec5SDimitry Andric else { 1640b57cec5SDimitry Andric // If we're resetting this to an invalid thread id, then don't make an 1650b57cec5SDimitry Andric // options pointer just to do that. 1660b57cec5SDimitry Andric if (m_options_up != nullptr) 1670b57cec5SDimitry Andric m_options_up->GetThreadSpec()->SetQueueName(queue_name); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged); 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric const char *BreakpointLocation::GetQueueName() const { 1730b57cec5SDimitry Andric const ThreadSpec *thread_spec = 1740b57cec5SDimitry Andric GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 175fe6060f1SDimitry Andric .GetThreadSpecNoCreate(); 1760b57cec5SDimitry Andric if (thread_spec) 1770b57cec5SDimitry Andric return thread_spec->GetQueueName(); 1780b57cec5SDimitry Andric else 1790b57cec5SDimitry Andric return nullptr; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) { 1830b57cec5SDimitry Andric if (m_options_up != nullptr && m_options_up->HasCallback()) 1840b57cec5SDimitry Andric return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID()); 1850b57cec5SDimitry Andric else 1860b57cec5SDimitry Andric return m_owner.InvokeCallback(context, GetID()); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 189fe6060f1SDimitry Andric bool BreakpointLocation::IsCallbackSynchronous() { 190fe6060f1SDimitry Andric if (m_options_up != nullptr && m_options_up->HasCallback()) 191fe6060f1SDimitry Andric return m_options_up->IsCallbackSynchronous(); 192fe6060f1SDimitry Andric else 193fe6060f1SDimitry Andric return m_owner.GetOptions().IsCallbackSynchronous(); 194fe6060f1SDimitry Andric } 195fe6060f1SDimitry Andric 1960b57cec5SDimitry Andric void BreakpointLocation::SetCallback(BreakpointHitCallback callback, 1970b57cec5SDimitry Andric void *baton, bool is_synchronous) { 1980b57cec5SDimitry Andric // The default "Baton" class will keep a copy of "baton" and won't free or 1995f757f3fSDimitry Andric // delete it when it goes out of scope. 200fe6060f1SDimitry Andric GetLocationOptions().SetCallback( 2010b57cec5SDimitry Andric callback, std::make_shared<UntypedBaton>(baton), is_synchronous); 2020b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric void BreakpointLocation::SetCallback(BreakpointHitCallback callback, 2060b57cec5SDimitry Andric const BatonSP &baton_sp, 2070b57cec5SDimitry Andric bool is_synchronous) { 208fe6060f1SDimitry Andric GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous); 2090b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged); 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric void BreakpointLocation::ClearCallback() { 213fe6060f1SDimitry Andric GetLocationOptions().ClearCallback(); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric void BreakpointLocation::SetCondition(const char *condition) { 217fe6060f1SDimitry Andric GetLocationOptions().SetCondition(condition); 2180b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric const char *BreakpointLocation::GetConditionText(size_t *hash) const { 2220b57cec5SDimitry Andric return GetOptionsSpecifyingKind(BreakpointOptions::eCondition) 223fe6060f1SDimitry Andric .GetConditionText(hash); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, 2270b57cec5SDimitry Andric Status &error) { 22881ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Breakpoints); 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric std::lock_guard<std::mutex> guard(m_condition_mutex); 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric size_t condition_hash; 2330b57cec5SDimitry Andric const char *condition_text = GetConditionText(&condition_hash); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric if (!condition_text) { 2360b57cec5SDimitry Andric m_user_expression_sp.reset(); 2370b57cec5SDimitry Andric return false; 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric error.Clear(); 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric DiagnosticManager diagnostics; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric if (condition_hash != m_condition_hash || !m_user_expression_sp || 2455f757f3fSDimitry Andric !m_user_expression_sp->IsParseCacheable() || 2460b57cec5SDimitry Andric !m_user_expression_sp->MatchesContext(exe_ctx)) { 2470b57cec5SDimitry Andric LanguageType language = eLanguageTypeUnknown; 2480b57cec5SDimitry Andric // See if we can figure out the language from the frame, otherwise use the 2490b57cec5SDimitry Andric // default language: 2500b57cec5SDimitry Andric CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit(); 2510b57cec5SDimitry Andric if (comp_unit) 2520b57cec5SDimitry Andric language = comp_unit->GetLanguage(); 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage( 2550b57cec5SDimitry Andric condition_text, llvm::StringRef(), language, Expression::eResultTypeAny, 2560b57cec5SDimitry Andric EvaluateExpressionOptions(), nullptr, error)); 2570b57cec5SDimitry Andric if (error.Fail()) { 2589dba64beSDimitry Andric LLDB_LOGF(log, "Error getting condition expression: %s.", 2590b57cec5SDimitry Andric error.AsCString()); 2600b57cec5SDimitry Andric m_user_expression_sp.reset(); 2610b57cec5SDimitry Andric return true; 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric if (!m_user_expression_sp->Parse(diagnostics, exe_ctx, 2650b57cec5SDimitry Andric eExecutionPolicyOnlyWhenNeeded, true, 2660b57cec5SDimitry Andric false)) { 2670b57cec5SDimitry Andric error.SetErrorStringWithFormat( 2680b57cec5SDimitry Andric "Couldn't parse conditional expression:\n%s", 2690b57cec5SDimitry Andric diagnostics.GetString().c_str()); 2700b57cec5SDimitry Andric m_user_expression_sp.reset(); 2710b57cec5SDimitry Andric return true; 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric m_condition_hash = condition_hash; 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // We need to make sure the user sees any parse errors in their condition, so 2780b57cec5SDimitry Andric // we'll hook the constructor errors up to the debugger's Async I/O. 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric ValueObjectSP result_value_sp; 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric EvaluateExpressionOptions options; 2830b57cec5SDimitry Andric options.SetUnwindOnError(true); 2840b57cec5SDimitry Andric options.SetIgnoreBreakpoints(true); 2850b57cec5SDimitry Andric options.SetTryAllThreads(true); 28606c3fb27SDimitry Andric options.SetSuppressPersistentResult( 2870b57cec5SDimitry Andric true); // Don't generate a user variable for condition expressions. 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric Status expr_error; 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric diagnostics.Clear(); 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric ExpressionVariableSP result_variable_sp; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric ExpressionResults result_code = m_user_expression_sp->Execute( 2960b57cec5SDimitry Andric diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp); 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric bool ret; 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric if (result_code == eExpressionCompleted) { 3010b57cec5SDimitry Andric if (!result_variable_sp) { 3020b57cec5SDimitry Andric error.SetErrorString("Expression did not return a result"); 3030b57cec5SDimitry Andric return false; 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric result_value_sp = result_variable_sp->GetValueObject(); 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric if (result_value_sp) { 3090b57cec5SDimitry Andric ret = result_value_sp->IsLogicalTrue(error); 3100b57cec5SDimitry Andric if (log) { 3110b57cec5SDimitry Andric if (error.Success()) { 3129dba64beSDimitry Andric LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n", 3130b57cec5SDimitry Andric ret ? "true" : "false"); 3140b57cec5SDimitry Andric } else { 3150b57cec5SDimitry Andric error.SetErrorString( 3160b57cec5SDimitry Andric "Failed to get an integer result from the expression"); 3170b57cec5SDimitry Andric ret = false; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric } else { 3210b57cec5SDimitry Andric ret = false; 3220b57cec5SDimitry Andric error.SetErrorString("Failed to get any result from the expression"); 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric } else { 3250b57cec5SDimitry Andric ret = false; 3260b57cec5SDimitry Andric error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", 3270b57cec5SDimitry Andric diagnostics.GetString().c_str()); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric return ret; 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric 333e8d8bef9SDimitry Andric uint32_t BreakpointLocation::GetIgnoreCount() const { 3340b57cec5SDimitry Andric return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount) 335fe6060f1SDimitry Andric .GetIgnoreCount(); 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric void BreakpointLocation::SetIgnoreCount(uint32_t n) { 339fe6060f1SDimitry Andric GetLocationOptions().SetIgnoreCount(n); 3400b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric void BreakpointLocation::DecrementIgnoreCount() { 3440b57cec5SDimitry Andric if (m_options_up != nullptr) { 3450b57cec5SDimitry Andric uint32_t loc_ignore = m_options_up->GetIgnoreCount(); 3460b57cec5SDimitry Andric if (loc_ignore != 0) 3470b57cec5SDimitry Andric m_options_up->SetIgnoreCount(loc_ignore - 1); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric bool BreakpointLocation::IgnoreCountShouldStop() { 352fe6060f1SDimitry Andric uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount(); 353fe6060f1SDimitry Andric uint32_t loc_ignore = 0; 354fe6060f1SDimitry Andric if (m_options_up != nullptr) 355fe6060f1SDimitry Andric loc_ignore = m_options_up->GetIgnoreCount(); 356fe6060f1SDimitry Andric 357fe6060f1SDimitry Andric if (loc_ignore != 0 || owner_ignore != 0) { 3580b57cec5SDimitry Andric m_owner.DecrementIgnoreCount(); 3590b57cec5SDimitry Andric DecrementIgnoreCount(); // Have to decrement our owners' ignore count, 360fe6060f1SDimitry Andric // since it won't get a chance to. 3610b57cec5SDimitry Andric return false; 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric return true; 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 366fe6060f1SDimitry Andric BreakpointOptions &BreakpointLocation::GetLocationOptions() { 3670b57cec5SDimitry Andric // If we make the copy we don't copy the callbacks because that is 3680b57cec5SDimitry Andric // potentially expensive and we don't want to do that for the simple case 3690b57cec5SDimitry Andric // where someone is just disabling the location. 3700b57cec5SDimitry Andric if (m_options_up == nullptr) 3715ffd83dbSDimitry Andric m_options_up = std::make_unique<BreakpointOptions>(false); 3720b57cec5SDimitry Andric 373fe6060f1SDimitry Andric return *m_options_up; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric 376fe6060f1SDimitry Andric bool BreakpointLocation::ValidForThisThread(Thread &thread) { 377fe6060f1SDimitry Andric return thread.MatchesSpec( 378fe6060f1SDimitry Andric GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 379fe6060f1SDimitry Andric .GetThreadSpecNoCreate()); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric // RETURNS - true if we should stop at this breakpoint, false if we 3830b57cec5SDimitry Andric // should continue. Note, we don't check the thread spec for the breakpoint 3840b57cec5SDimitry Andric // here, since if the breakpoint is not for this thread, then the event won't 3850b57cec5SDimitry Andric // even get reported, so the check is redundant. 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) { 3880b57cec5SDimitry Andric bool should_stop = true; 38981ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Breakpoints); 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric // Do this first, if a location is disabled, it shouldn't increment its hit 3920b57cec5SDimitry Andric // count. 3930b57cec5SDimitry Andric if (!IsEnabled()) 3940b57cec5SDimitry Andric return false; 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric // We only run synchronous callbacks in ShouldStop: 3970b57cec5SDimitry Andric context->is_synchronous = true; 3980b57cec5SDimitry Andric should_stop = InvokeCallback(context); 3990b57cec5SDimitry Andric 4000b57cec5SDimitry Andric if (log) { 4010b57cec5SDimitry Andric StreamString s; 4020b57cec5SDimitry Andric GetDescription(&s, lldb::eDescriptionLevelVerbose); 4039dba64beSDimitry Andric LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(), 4040b57cec5SDimitry Andric should_stop ? "stopping" : "continuing"); 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric return should_stop; 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric void BreakpointLocation::BumpHitCount() { 4110b57cec5SDimitry Andric if (IsEnabled()) { 4120b57cec5SDimitry Andric // Step our hit count, and also step the hit count of the owner. 413e8d8bef9SDimitry Andric m_hit_counter.Increment(); 414e8d8bef9SDimitry Andric m_owner.m_hit_counter.Increment(); 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric void BreakpointLocation::UndoBumpHitCount() { 4190b57cec5SDimitry Andric if (IsEnabled()) { 4200b57cec5SDimitry Andric // Step our hit count, and also step the hit count of the owner. 421e8d8bef9SDimitry Andric m_hit_counter.Decrement(); 422e8d8bef9SDimitry Andric m_owner.m_hit_counter.Decrement(); 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric bool BreakpointLocation::IsResolved() const { 4270b57cec5SDimitry Andric return m_bp_site_sp.get() != nullptr; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const { 4310b57cec5SDimitry Andric return m_bp_site_sp; 4320b57cec5SDimitry Andric } 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric bool BreakpointLocation::ResolveBreakpointSite() { 4350b57cec5SDimitry Andric if (m_bp_site_sp) 4360b57cec5SDimitry Andric return true; 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric Process *process = m_owner.GetTarget().GetProcessSP().get(); 4390b57cec5SDimitry Andric if (process == nullptr) 4400b57cec5SDimitry Andric return false; 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric lldb::break_id_t new_id = 4430b57cec5SDimitry Andric process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware()); 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric if (new_id == LLDB_INVALID_BREAK_ID) { 44681ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Breakpoints); 4470b57cec5SDimitry Andric if (log) 4480b57cec5SDimitry Andric log->Warning("Failed to add breakpoint site at 0x%" PRIx64, 4490b57cec5SDimitry Andric m_address.GetOpcodeLoadAddress(&m_owner.GetTarget())); 4500b57cec5SDimitry Andric } 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric return IsResolved(); 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) { 4560b57cec5SDimitry Andric m_bp_site_sp = bp_site_sp; 4570b57cec5SDimitry Andric SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved); 4580b57cec5SDimitry Andric return true; 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric bool BreakpointLocation::ClearBreakpointSite() { 4620b57cec5SDimitry Andric if (m_bp_site_sp.get()) { 4630b57cec5SDimitry Andric ProcessSP process_sp(m_owner.GetTarget().GetProcessSP()); 4640b57cec5SDimitry Andric // If the process exists, get it to remove the owner, it will remove the 4650b57cec5SDimitry Andric // physical implementation of the breakpoint as well if there are no more 4660b57cec5SDimitry Andric // owners. Otherwise just remove this owner. 4670b57cec5SDimitry Andric if (process_sp) 4685f757f3fSDimitry Andric process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(), 4690b57cec5SDimitry Andric GetID(), m_bp_site_sp); 4700b57cec5SDimitry Andric else 4715f757f3fSDimitry Andric m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID()); 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric m_bp_site_sp.reset(); 4740b57cec5SDimitry Andric return true; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric return false; 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric void BreakpointLocation::GetDescription(Stream *s, 4800b57cec5SDimitry Andric lldb::DescriptionLevel level) { 4810b57cec5SDimitry Andric SymbolContext sc; 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric // If the description level is "initial" then the breakpoint is printing out 4840b57cec5SDimitry Andric // our initial state, and we should let it decide how it wants to print our 4850b57cec5SDimitry Andric // label. 4860b57cec5SDimitry Andric if (level != eDescriptionLevelInitial) { 4870b57cec5SDimitry Andric s->Indent(); 4880b57cec5SDimitry Andric BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID()); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric if (level == lldb::eDescriptionLevelBrief) 4920b57cec5SDimitry Andric return; 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric if (level != eDescriptionLevelInitial) 4950b57cec5SDimitry Andric s->PutCString(": "); 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric if (level == lldb::eDescriptionLevelVerbose) 4980b57cec5SDimitry Andric s->IndentMore(); 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric if (m_address.IsSectionOffset()) { 5010b57cec5SDimitry Andric m_address.CalculateSymbolContext(&sc); 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric if (level == lldb::eDescriptionLevelFull || 5040b57cec5SDimitry Andric level == eDescriptionLevelInitial) { 5050b57cec5SDimitry Andric if (IsReExported()) 5060b57cec5SDimitry Andric s->PutCString("re-exported target = "); 5070b57cec5SDimitry Andric else 5080b57cec5SDimitry Andric s->PutCString("where = "); 5090b57cec5SDimitry Andric sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address, 510*0fca6ea1SDimitry Andric false, true, false, true, true, true); 5110b57cec5SDimitry Andric } else { 5120b57cec5SDimitry Andric if (sc.module_sp) { 5130b57cec5SDimitry Andric s->EOL(); 5140b57cec5SDimitry Andric s->Indent("module = "); 515480093f4SDimitry Andric sc.module_sp->GetFileSpec().Dump(s->AsRawOstream()); 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric if (sc.comp_unit != nullptr) { 5190b57cec5SDimitry Andric s->EOL(); 5200b57cec5SDimitry Andric s->Indent("compile unit = "); 521480093f4SDimitry Andric sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s); 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric if (sc.function != nullptr) { 5240b57cec5SDimitry Andric s->EOL(); 5250b57cec5SDimitry Andric s->Indent("function = "); 5260b57cec5SDimitry Andric s->PutCString(sc.function->GetName().AsCString("<unknown>")); 527*0fca6ea1SDimitry Andric if (ConstString mangled_name = 528*0fca6ea1SDimitry Andric sc.function->GetMangled().GetMangledName()) { 529*0fca6ea1SDimitry Andric s->EOL(); 530*0fca6ea1SDimitry Andric s->Indent("mangled function = "); 531*0fca6ea1SDimitry Andric s->PutCString(mangled_name.AsCString()); 532*0fca6ea1SDimitry Andric } 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric if (sc.line_entry.line > 0) { 5360b57cec5SDimitry Andric s->EOL(); 5370b57cec5SDimitry Andric s->Indent("location = "); 5380b57cec5SDimitry Andric sc.line_entry.DumpStopContext(s, true); 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric } else { 5420b57cec5SDimitry Andric // If we don't have a comp unit, see if we have a symbol we can print. 5430b57cec5SDimitry Andric if (sc.symbol) { 5440b57cec5SDimitry Andric s->EOL(); 5450b57cec5SDimitry Andric if (IsReExported()) 5460b57cec5SDimitry Andric s->Indent("re-exported target = "); 5470b57cec5SDimitry Andric else 5480b57cec5SDimitry Andric s->Indent("symbol = "); 5490b57cec5SDimitry Andric s->PutCString(sc.symbol->GetName().AsCString("<unknown>")); 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric if (level == lldb::eDescriptionLevelVerbose) { 5560b57cec5SDimitry Andric s->EOL(); 5570b57cec5SDimitry Andric s->Indent(); 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric if (m_address.IsSectionOffset() && 5610b57cec5SDimitry Andric (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)) 5620b57cec5SDimitry Andric s->Printf(", "); 5630b57cec5SDimitry Andric s->Printf("address = "); 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric ExecutionContextScope *exe_scope = nullptr; 5660b57cec5SDimitry Andric Target *target = &m_owner.GetTarget(); 5670b57cec5SDimitry Andric if (target) 5680b57cec5SDimitry Andric exe_scope = target->GetProcessSP().get(); 5690b57cec5SDimitry Andric if (exe_scope == nullptr) 5700b57cec5SDimitry Andric exe_scope = target; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric if (level == eDescriptionLevelInitial) 5730b57cec5SDimitry Andric m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, 5740b57cec5SDimitry Andric Address::DumpStyleFileAddress); 5750b57cec5SDimitry Andric else 5760b57cec5SDimitry Andric m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress, 5770b57cec5SDimitry Andric Address::DumpStyleModuleWithFileAddress); 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric if (IsIndirect() && m_bp_site_sp) { 5800b57cec5SDimitry Andric Address resolved_address; 5810b57cec5SDimitry Andric resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target); 5820b57cec5SDimitry Andric Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol(); 5830b57cec5SDimitry Andric if (resolved_symbol) { 5840b57cec5SDimitry Andric if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial) 5850b57cec5SDimitry Andric s->Printf(", "); 5860b57cec5SDimitry Andric else if (level == lldb::eDescriptionLevelVerbose) { 5870b57cec5SDimitry Andric s->EOL(); 5880b57cec5SDimitry Andric s->Indent(); 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric s->Printf("indirect target = %s", 5910b57cec5SDimitry Andric resolved_symbol->GetName().GetCString()); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 595e8d8bef9SDimitry Andric bool is_resolved = IsResolved(); 596e8d8bef9SDimitry Andric bool is_hardware = is_resolved && m_bp_site_sp->IsHardware(); 597e8d8bef9SDimitry Andric 5980b57cec5SDimitry Andric if (level == lldb::eDescriptionLevelVerbose) { 5990b57cec5SDimitry Andric s->EOL(); 6000b57cec5SDimitry Andric s->Indent(); 601e8d8bef9SDimitry Andric s->Printf("resolved = %s\n", is_resolved ? "true" : "false"); 6025ffd83dbSDimitry Andric s->Indent(); 603e8d8bef9SDimitry Andric s->Printf("hardware = %s\n", is_hardware ? "true" : "false"); 6040b57cec5SDimitry Andric s->Indent(); 6050b57cec5SDimitry Andric s->Printf("hit count = %-4u\n", GetHitCount()); 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric if (m_options_up) { 6080b57cec5SDimitry Andric s->Indent(); 6090b57cec5SDimitry Andric m_options_up->GetDescription(s, level); 6100b57cec5SDimitry Andric s->EOL(); 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric s->IndentLess(); 6130b57cec5SDimitry Andric } else if (level != eDescriptionLevelInitial) { 614e8d8bef9SDimitry Andric s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"), 615e8d8bef9SDimitry Andric (is_hardware ? "hardware, " : ""), GetHitCount()); 6160b57cec5SDimitry Andric if (m_options_up) { 6170b57cec5SDimitry Andric m_options_up->GetDescription(s, level); 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric void BreakpointLocation::Dump(Stream *s) const { 6230b57cec5SDimitry Andric if (s == nullptr) 6240b57cec5SDimitry Andric return; 6250b57cec5SDimitry Andric 626e8d8bef9SDimitry Andric bool is_resolved = IsResolved(); 627e8d8bef9SDimitry Andric bool is_hardware = is_resolved && m_bp_site_sp->IsHardware(); 628e8d8bef9SDimitry Andric 6290b57cec5SDimitry Andric lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec) 630fe6060f1SDimitry Andric .GetThreadSpecNoCreate() 631fe6060f1SDimitry Andric ->GetTID(); 6320b57cec5SDimitry Andric s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64 6330b57cec5SDimitry Andric " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint " 6345f757f3fSDimitry Andric "hit_count = %-4u ignore_count = %-4u", 6350b57cec5SDimitry Andric GetID(), tid, 6360b57cec5SDimitry Andric (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()), 6370b57cec5SDimitry Andric (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled()) 6380b57cec5SDimitry Andric ? "enabled " 6390b57cec5SDimitry Andric : "disabled", 6405f757f3fSDimitry Andric is_hardware ? "hardware" : "software", GetHitCount(), 6410b57cec5SDimitry Andric GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount) 642fe6060f1SDimitry Andric .GetIgnoreCount()); 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric void BreakpointLocation::SendBreakpointLocationChangedEvent( 6460b57cec5SDimitry Andric lldb::BreakpointEventType eventKind) { 647*0fca6ea1SDimitry Andric if (!m_owner.IsInternal() && m_owner.GetTarget().EventTypeHasListeners( 6480b57cec5SDimitry Andric Target::eBroadcastBitBreakpointChanged)) { 6497a6dacacSDimitry Andric auto data_sp = std::make_shared<Breakpoint::BreakpointEventData>( 6500b57cec5SDimitry Andric eventKind, m_owner.shared_from_this()); 6517a6dacacSDimitry Andric data_sp->GetBreakpointLocationCollection().Add(shared_from_this()); 6520b57cec5SDimitry Andric m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, 6537a6dacacSDimitry Andric data_sp); 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) { 6580b57cec5SDimitry Andric m_address = swap_from->m_address; 6590b57cec5SDimitry Andric m_should_resolve_indirect_functions = 6600b57cec5SDimitry Andric swap_from->m_should_resolve_indirect_functions; 6610b57cec5SDimitry Andric m_is_reexported = swap_from->m_is_reexported; 6620b57cec5SDimitry Andric m_is_indirect = swap_from->m_is_indirect; 6630b57cec5SDimitry Andric m_user_expression_sp.reset(); 6640b57cec5SDimitry Andric } 665*0fca6ea1SDimitry Andric 666*0fca6ea1SDimitry Andric void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) { 667*0fca6ea1SDimitry Andric if (thread_id != LLDB_INVALID_THREAD_ID) 668*0fca6ea1SDimitry Andric GetLocationOptions().SetThreadID(thread_id); 669*0fca6ea1SDimitry Andric else { 670*0fca6ea1SDimitry Andric // If we're resetting this to an invalid thread id, then don't make an 671*0fca6ea1SDimitry Andric // options pointer just to do that. 672*0fca6ea1SDimitry Andric if (m_options_up != nullptr) 673*0fca6ea1SDimitry Andric m_options_up->SetThreadID(thread_id); 674*0fca6ea1SDimitry Andric } 675*0fca6ea1SDimitry Andric } 676