180814287SRaphael Isemann //===-- BreakpointLocation.cpp --------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
1030fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointID.h"
1130fdc8d8SChris Lattner #include "lldb/Breakpoint/StoppointCallbackContext.h"
125b52f0c7SJim Ingham #include "lldb/Core/Debugger.h"
131f746071SGreg Clayton #include "lldb/Core/Module.h"
14a78bd7ffSZachary Turner #include "lldb/Core/ValueObject.h"
15579e70c9SSean Callanan #include "lldb/Expression/DiagnosticManager.h"
16937e3964SBruce Mitchener #include "lldb/Expression/ExpressionVariable.h"
17151c032cSJim Ingham #include "lldb/Expression/UserExpression.h"
181f746071SGreg Clayton #include "lldb/Symbol/CompileUnit.h"
191f746071SGreg Clayton #include "lldb/Symbol/Symbol.h"
20151c032cSJim Ingham #include "lldb/Symbol/TypeSystem.h"
211f746071SGreg Clayton #include "lldb/Target/Process.h"
22b9c1b51eSKate Stone #include "lldb/Target/Target.h"
2330fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
241b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
25c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
266f9e6901SZachary Turner #include "lldb/Utility/Log.h"
27bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
2830fdc8d8SChris Lattner 
2930fdc8d8SChris Lattner using namespace lldb;
3030fdc8d8SChris Lattner using namespace lldb_private;
3130fdc8d8SChris Lattner 
BreakpointLocation(break_id_t loc_id,Breakpoint & owner,const Address & addr,lldb::tid_t tid,bool hardware,bool check_for_resolver)32b9c1b51eSKate Stone BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner,
33b9c1b51eSKate Stone                                        const Address &addr, lldb::tid_t tid,
34bb19a13cSSaleem Abdulrasool                                        bool hardware, bool check_for_resolver)
35da0bba5cSTatyana Krasnukha     : m_being_created(true), m_should_resolve_indirect_functions(false),
36b9c1b51eSKate Stone       m_is_reexported(false), m_is_indirect(false), m_address(addr),
37*ee4b6cf5SKazu Hirata       m_owner(owner), m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() {
38b9c1b51eSKate Stone   if (check_for_resolver) {
391460e4bfSJim Ingham     Symbol *symbol = m_address.CalculateSymbolContextSymbol();
40b9c1b51eSKate Stone     if (symbol && symbol->IsIndirect()) {
411460e4bfSJim Ingham       SetShouldResolveIndirectFunctions(true);
421460e4bfSJim Ingham     }
431460e4bfSJim Ingham   }
441460e4bfSJim Ingham 
451b54c88cSJim Ingham   SetThreadID(tid);
46e6bc6cb9SJim Ingham   m_being_created = false;
4730fdc8d8SChris Lattner }
4830fdc8d8SChris Lattner 
~BreakpointLocation()49b9c1b51eSKate Stone BreakpointLocation::~BreakpointLocation() { ClearBreakpointSite(); }
5030fdc8d8SChris Lattner 
GetLoadAddress() const51b9c1b51eSKate Stone lldb::addr_t BreakpointLocation::GetLoadAddress() const {
52f3ef3d2aSGreg Clayton   return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
5330fdc8d8SChris Lattner }
5430fdc8d8SChris Lattner 
GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind) const55cfb96d84SJim Ingham const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind(
56cfb96d84SJim Ingham     BreakpointOptions::OptionKind kind) const {
57d5b44036SJonas Devlieghere   if (m_options_up && m_options_up->IsOptionSet(kind))
58cfb96d84SJim Ingham     return *m_options_up;
59af26b22cSJim Ingham   else
60af26b22cSJim Ingham     return m_owner.GetOptions();
61af26b22cSJim Ingham }
62af26b22cSJim Ingham 
GetAddress()63b9c1b51eSKate Stone Address &BreakpointLocation::GetAddress() { return m_address; }
6430fdc8d8SChris Lattner 
GetBreakpoint()65b9c1b51eSKate Stone Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }
6630fdc8d8SChris Lattner 
GetTarget()67b9c1b51eSKate Stone Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }
68151c032cSJim Ingham 
IsEnabled() const69b9c1b51eSKate Stone bool BreakpointLocation::IsEnabled() const {
7050df1f96SJohnny Chen   if (!m_owner.IsEnabled())
7150df1f96SJohnny Chen     return false;
72d5b44036SJonas Devlieghere   else if (m_options_up != nullptr)
73d5b44036SJonas Devlieghere     return m_options_up->IsEnabled();
7430fdc8d8SChris Lattner   else
7550df1f96SJohnny Chen     return true;
7630fdc8d8SChris Lattner }
7730fdc8d8SChris Lattner 
SetEnabled(bool enabled)78b9c1b51eSKate Stone void BreakpointLocation::SetEnabled(bool enabled) {
79cfb96d84SJim Ingham   GetLocationOptions().SetEnabled(enabled);
80b9c1b51eSKate Stone   if (enabled) {
8130fdc8d8SChris Lattner     ResolveBreakpointSite();
82b9c1b51eSKate Stone   } else {
8330fdc8d8SChris Lattner     ClearBreakpointSite();
8430fdc8d8SChris Lattner   }
85b9c1b51eSKate Stone   SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
86b9c1b51eSKate Stone                                              : eBreakpointEventTypeDisabled);
8730fdc8d8SChris Lattner }
8830fdc8d8SChris Lattner 
IsAutoContinue() const89f08f5c99SJim Ingham bool BreakpointLocation::IsAutoContinue() const {
90d5b44036SJonas Devlieghere   if (m_options_up &&
91d5b44036SJonas Devlieghere       m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue))
92d5b44036SJonas Devlieghere     return m_options_up->IsAutoContinue();
93f08f5c99SJim Ingham   else
94f08f5c99SJim Ingham     return m_owner.IsAutoContinue();
95f08f5c99SJim Ingham }
96f08f5c99SJim Ingham 
SetAutoContinue(bool auto_continue)97f08f5c99SJim Ingham void BreakpointLocation::SetAutoContinue(bool auto_continue) {
98cfb96d84SJim Ingham   GetLocationOptions().SetAutoContinue(auto_continue);
99f08f5c99SJim Ingham   SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
100f08f5c99SJim Ingham }
101f08f5c99SJim Ingham 
SetThreadID(lldb::tid_t thread_id)102b9c1b51eSKate Stone void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
1031b54c88cSJim Ingham   if (thread_id != LLDB_INVALID_THREAD_ID)
104cfb96d84SJim Ingham     GetLocationOptions().SetThreadID(thread_id);
105b9c1b51eSKate Stone   else {
10605097246SAdrian Prantl     // If we're resetting this to an invalid thread id, then don't make an
10705097246SAdrian Prantl     // options pointer just to do that.
108d5b44036SJonas Devlieghere     if (m_options_up != nullptr)
109d5b44036SJonas Devlieghere       m_options_up->SetThreadID(thread_id);
1101b54c88cSJim Ingham   }
111e6bc6cb9SJim Ingham   SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
112e6bc6cb9SJim Ingham }
113e6bc6cb9SJim Ingham 
GetThreadID()114b9c1b51eSKate Stone lldb::tid_t BreakpointLocation::GetThreadID() {
115af26b22cSJim Ingham   const ThreadSpec *thread_spec =
116af26b22cSJim Ingham       GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
117cfb96d84SJim Ingham           .GetThreadSpecNoCreate();
118af26b22cSJim Ingham   if (thread_spec)
119af26b22cSJim Ingham     return thread_spec->GetTID();
120e6bc6cb9SJim Ingham   else
121e6bc6cb9SJim Ingham     return LLDB_INVALID_THREAD_ID;
122e6bc6cb9SJim Ingham }
123e6bc6cb9SJim Ingham 
SetThreadIndex(uint32_t index)124b9c1b51eSKate Stone void BreakpointLocation::SetThreadIndex(uint32_t index) {
125e6bc6cb9SJim Ingham   if (index != 0)
126cfb96d84SJim Ingham     GetLocationOptions().GetThreadSpec()->SetIndex(index);
127b9c1b51eSKate Stone   else {
12805097246SAdrian Prantl     // If we're resetting this to an invalid thread id, then don't make an
12905097246SAdrian Prantl     // options pointer just to do that.
130d5b44036SJonas Devlieghere     if (m_options_up != nullptr)
131d5b44036SJonas Devlieghere       m_options_up->GetThreadSpec()->SetIndex(index);
132e6bc6cb9SJim Ingham   }
133e6bc6cb9SJim Ingham   SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
134e6bc6cb9SJim Ingham }
135e6bc6cb9SJim Ingham 
GetThreadIndex() const136b9c1b51eSKate Stone uint32_t BreakpointLocation::GetThreadIndex() const {
137af26b22cSJim Ingham   const ThreadSpec *thread_spec =
138af26b22cSJim Ingham       GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
139cfb96d84SJim Ingham           .GetThreadSpecNoCreate();
140af26b22cSJim Ingham   if (thread_spec)
141af26b22cSJim Ingham     return thread_spec->GetIndex();
142e6bc6cb9SJim Ingham   else
143e6bc6cb9SJim Ingham     return 0;
144e6bc6cb9SJim Ingham }
145e6bc6cb9SJim Ingham 
SetThreadName(const char * thread_name)146b9c1b51eSKate Stone void BreakpointLocation::SetThreadName(const char *thread_name) {
14716fd7511SEugene Zelenko   if (thread_name != nullptr)
148cfb96d84SJim Ingham     GetLocationOptions().GetThreadSpec()->SetName(thread_name);
149b9c1b51eSKate Stone   else {
15005097246SAdrian Prantl     // If we're resetting this to an invalid thread id, then don't make an
15105097246SAdrian Prantl     // options pointer just to do that.
152d5b44036SJonas Devlieghere     if (m_options_up != nullptr)
153d5b44036SJonas Devlieghere       m_options_up->GetThreadSpec()->SetName(thread_name);
154e6bc6cb9SJim Ingham   }
155e6bc6cb9SJim Ingham   SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
156e6bc6cb9SJim Ingham }
157e6bc6cb9SJim Ingham 
GetThreadName() const158b9c1b51eSKate Stone const char *BreakpointLocation::GetThreadName() const {
159af26b22cSJim Ingham   const ThreadSpec *thread_spec =
160af26b22cSJim Ingham       GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
161cfb96d84SJim Ingham           .GetThreadSpecNoCreate();
162af26b22cSJim Ingham   if (thread_spec)
163af26b22cSJim Ingham     return thread_spec->GetName();
164e6bc6cb9SJim Ingham   else
16516fd7511SEugene Zelenko     return nullptr;
166e6bc6cb9SJim Ingham }
167e6bc6cb9SJim Ingham 
SetQueueName(const char * queue_name)168b9c1b51eSKate Stone void BreakpointLocation::SetQueueName(const char *queue_name) {
16916fd7511SEugene Zelenko   if (queue_name != nullptr)
170cfb96d84SJim Ingham     GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name);
171b9c1b51eSKate Stone   else {
17205097246SAdrian Prantl     // If we're resetting this to an invalid thread id, then don't make an
17305097246SAdrian Prantl     // options pointer just to do that.
174d5b44036SJonas Devlieghere     if (m_options_up != nullptr)
175d5b44036SJonas Devlieghere       m_options_up->GetThreadSpec()->SetQueueName(queue_name);
176e6bc6cb9SJim Ingham   }
177e6bc6cb9SJim Ingham   SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
178e6bc6cb9SJim Ingham }
179e6bc6cb9SJim Ingham 
GetQueueName() const180b9c1b51eSKate Stone const char *BreakpointLocation::GetQueueName() const {
181af26b22cSJim Ingham   const ThreadSpec *thread_spec =
182af26b22cSJim Ingham       GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
183cfb96d84SJim Ingham           .GetThreadSpecNoCreate();
184af26b22cSJim Ingham   if (thread_spec)
185af26b22cSJim Ingham     return thread_spec->GetQueueName();
186e6bc6cb9SJim Ingham   else
18716fd7511SEugene Zelenko     return nullptr;
18830fdc8d8SChris Lattner }
18930fdc8d8SChris Lattner 
InvokeCallback(StoppointCallbackContext * context)190b9c1b51eSKate Stone bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
191d5b44036SJonas Devlieghere   if (m_options_up != nullptr && m_options_up->HasCallback())
192d5b44036SJonas Devlieghere     return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID());
19330fdc8d8SChris Lattner   else
1940136309fSJim Ingham     return m_owner.InvokeCallback(context, GetID());
19530fdc8d8SChris Lattner }
19630fdc8d8SChris Lattner 
IsCallbackSynchronous()197c8faa8c2SJim Ingham bool BreakpointLocation::IsCallbackSynchronous() {
198c8faa8c2SJim Ingham   if (m_options_up != nullptr && m_options_up->HasCallback())
199c8faa8c2SJim Ingham     return m_options_up->IsCallbackSynchronous();
200c8faa8c2SJim Ingham   else
201cfb96d84SJim Ingham     return m_owner.GetOptions().IsCallbackSynchronous();
202c8faa8c2SJim Ingham }
203c8faa8c2SJim Ingham 
SetCallback(BreakpointHitCallback callback,void * baton,bool is_synchronous)204b9c1b51eSKate Stone void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
205b9c1b51eSKate Stone                                      void *baton, bool is_synchronous) {
20605097246SAdrian Prantl   // The default "Baton" class will keep a copy of "baton" and won't free or
20705097246SAdrian Prantl   // delete it when it goes goes out of scope.
208cfb96d84SJim Ingham   GetLocationOptions().SetCallback(
2094e4fbe82SZachary Turner       callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
210e6bc6cb9SJim Ingham   SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
21130fdc8d8SChris Lattner }
21230fdc8d8SChris Lattner 
SetCallback(BreakpointHitCallback callback,const BatonSP & baton_sp,bool is_synchronous)213b9c1b51eSKate Stone void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
214b9c1b51eSKate Stone                                      const BatonSP &baton_sp,
215b9c1b51eSKate Stone                                      bool is_synchronous) {
216cfb96d84SJim Ingham   GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous);
217e6bc6cb9SJim Ingham   SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
21830fdc8d8SChris Lattner }
21930fdc8d8SChris Lattner 
ClearCallback()220b9c1b51eSKate Stone void BreakpointLocation::ClearCallback() {
221cfb96d84SJim Ingham   GetLocationOptions().ClearCallback();
22230fdc8d8SChris Lattner }
22330fdc8d8SChris Lattner 
SetCondition(const char * condition)224b9c1b51eSKate Stone void BreakpointLocation::SetCondition(const char *condition) {
225cfb96d84SJim Ingham   GetLocationOptions().SetCondition(condition);
226e6bc6cb9SJim Ingham   SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
22736f3b369SJim Ingham }
22836f3b369SJim Ingham 
GetConditionText(size_t * hash) const229b9c1b51eSKate Stone const char *BreakpointLocation::GetConditionText(size_t *hash) const {
230af26b22cSJim Ingham   return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
231cfb96d84SJim Ingham       .GetConditionText(hash);
2323dbf346eSSean Callanan }
2333dbf346eSSean Callanan 
ConditionSaysStop(ExecutionContext & exe_ctx,Status & error)234b9c1b51eSKate Stone bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
23597206d57SZachary Turner                                            Status &error) {
236a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::Breakpoints);
2373dbf346eSSean Callanan 
238bb19a13cSSaleem Abdulrasool   std::lock_guard<std::mutex> guard(m_condition_mutex);
239b4987e32SSean Callanan 
2403dbf346eSSean Callanan   size_t condition_hash;
2413dbf346eSSean Callanan   const char *condition_text = GetConditionText(&condition_hash);
2423dbf346eSSean Callanan 
243b9c1b51eSKate Stone   if (!condition_text) {
244ec537a24SSean Callanan     m_user_expression_sp.reset();
2453dbf346eSSean Callanan     return false;
246ec537a24SSean Callanan   }
2473dbf346eSSean Callanan 
248298de8f6SJim Ingham   error.Clear();
249298de8f6SJim Ingham 
250579e70c9SSean Callanan   DiagnosticManager diagnostics;
251579e70c9SSean Callanan 
252b9c1b51eSKate Stone   if (condition_hash != m_condition_hash || !m_user_expression_sp ||
253b9c1b51eSKate Stone       !m_user_expression_sp->MatchesContext(exe_ctx)) {
254151c032cSJim Ingham     LanguageType language = eLanguageTypeUnknown;
255b9c1b51eSKate Stone     // See if we can figure out the language from the frame, otherwise use the
256b9c1b51eSKate Stone     // default language:
257151c032cSJim Ingham     CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
258151c032cSJim Ingham     if (comp_unit)
259151c032cSJim Ingham       language = comp_unit->GetLanguage();
260151c032cSJim Ingham 
261b9c1b51eSKate Stone     m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
262c5d7df90SZachary Turner         condition_text, llvm::StringRef(), language, Expression::eResultTypeAny,
26340624a08SAleksandr Urakov         EvaluateExpressionOptions(), nullptr, error));
264b9c1b51eSKate Stone     if (error.Fail()) {
26563e5fb76SJonas Devlieghere       LLDB_LOGF(log, "Error getting condition expression: %s.",
266b9c1b51eSKate Stone                 error.AsCString());
267151c032cSJim Ingham       m_user_expression_sp.reset();
268151c032cSJim Ingham       return true;
269151c032cSJim Ingham     }
270151c032cSJim Ingham 
271b9c1b51eSKate Stone     if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
272b9c1b51eSKate Stone                                      eExecutionPolicyOnlyWhenNeeded, true,
273b9c1b51eSKate Stone                                      false)) {
274b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
275b9c1b51eSKate Stone           "Couldn't parse conditional expression:\n%s",
276579e70c9SSean Callanan           diagnostics.GetString().c_str());
2773dbf346eSSean Callanan       m_user_expression_sp.reset();
278298de8f6SJim Ingham       return true;
2793dbf346eSSean Callanan     }
2803dbf346eSSean Callanan 
2813dbf346eSSean Callanan     m_condition_hash = condition_hash;
2823dbf346eSSean Callanan   }
2833dbf346eSSean Callanan 
284b9c1b51eSKate Stone   // We need to make sure the user sees any parse errors in their condition, so
28505097246SAdrian Prantl   // we'll hook the constructor errors up to the debugger's Async I/O.
2863dbf346eSSean Callanan 
2873dbf346eSSean Callanan   ValueObjectSP result_value_sp;
28862afb9f6SGreg Clayton 
28962afb9f6SGreg Clayton   EvaluateExpressionOptions options;
29062afb9f6SGreg Clayton   options.SetUnwindOnError(true);
29162afb9f6SGreg Clayton   options.SetIgnoreBreakpoints(true);
2926fbc48bcSJim Ingham   options.SetTryAllThreads(true);
293b9c1b51eSKate Stone   options.SetResultIsInternal(
294b9c1b51eSKate Stone       true); // Don't generate a user variable for condition expressions.
2953dbf346eSSean Callanan 
29697206d57SZachary Turner   Status expr_error;
2973dbf346eSSean Callanan 
298579e70c9SSean Callanan   diagnostics.Clear();
2993dbf346eSSean Callanan 
300bc8ac34eSSean Callanan   ExpressionVariableSP result_variable_sp;
3013dbf346eSSean Callanan 
302b9c1b51eSKate Stone   ExpressionResults result_code = m_user_expression_sp->Execute(
303b9c1b51eSKate Stone       diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);
3043dbf346eSSean Callanan 
3053dbf346eSSean Callanan   bool ret;
3063dbf346eSSean Callanan 
307b9c1b51eSKate Stone   if (result_code == eExpressionCompleted) {
308b9c1b51eSKate Stone     if (!result_variable_sp) {
309467441d5SSean Callanan       error.SetErrorString("Expression did not return a result");
310879425faSSean Callanan       return false;
311467441d5SSean Callanan     }
312467441d5SSean Callanan 
3133dbf346eSSean Callanan     result_value_sp = result_variable_sp->GetValueObject();
3143dbf346eSSean Callanan 
315b9c1b51eSKate Stone     if (result_value_sp) {
31698e6daf1SJim Ingham       ret = result_value_sp->IsLogicalTrue(error);
317b9c1b51eSKate Stone       if (log) {
318b9c1b51eSKate Stone         if (error.Success()) {
31963e5fb76SJonas Devlieghere           LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n",
3203dbf346eSSean Callanan                     ret ? "true" : "false");
321b9c1b51eSKate Stone         } else {
322b9c1b51eSKate Stone           error.SetErrorString(
323b9c1b51eSKate Stone               "Failed to get an integer result from the expression");
32498e6daf1SJim Ingham           ret = false;
32598e6daf1SJim Ingham         }
3263dbf346eSSean Callanan       }
327b9c1b51eSKate Stone     } else {
3283dbf346eSSean Callanan       ret = false;
3293dbf346eSSean Callanan       error.SetErrorString("Failed to get any result from the expression");
3303dbf346eSSean Callanan     }
331b9c1b51eSKate Stone   } else {
3323dbf346eSSean Callanan     ret = false;
333b9c1b51eSKate Stone     error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
334b9c1b51eSKate Stone                                    diagnostics.GetString().c_str());
3353dbf346eSSean Callanan   }
3363dbf346eSSean Callanan 
3373dbf346eSSean Callanan   return ret;
33836f3b369SJim Ingham }
33936f3b369SJim Ingham 
GetIgnoreCount() const340da0bba5cSTatyana Krasnukha uint32_t BreakpointLocation::GetIgnoreCount() const {
341af26b22cSJim Ingham   return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
342cfb96d84SJim Ingham       .GetIgnoreCount();
34330fdc8d8SChris Lattner }
34430fdc8d8SChris Lattner 
SetIgnoreCount(uint32_t n)345b9c1b51eSKate Stone void BreakpointLocation::SetIgnoreCount(uint32_t n) {
346cfb96d84SJim Ingham   GetLocationOptions().SetIgnoreCount(n);
347e6bc6cb9SJim Ingham   SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
34830fdc8d8SChris Lattner }
34930fdc8d8SChris Lattner 
DecrementIgnoreCount()350b9c1b51eSKate Stone void BreakpointLocation::DecrementIgnoreCount() {
351d5b44036SJonas Devlieghere   if (m_options_up != nullptr) {
352d5b44036SJonas Devlieghere     uint32_t loc_ignore = m_options_up->GetIgnoreCount();
3530fd1b75fSJim Ingham     if (loc_ignore != 0)
354d5b44036SJonas Devlieghere       m_options_up->SetIgnoreCount(loc_ignore - 1);
3550fd1b75fSJim Ingham   }
3560fd1b75fSJim Ingham }
3570fd1b75fSJim Ingham 
IgnoreCountShouldStop()358b9c1b51eSKate Stone bool BreakpointLocation::IgnoreCountShouldStop() {
359658f6ed1SJim Ingham   uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
360658f6ed1SJim Ingham   uint32_t loc_ignore = 0;
361658f6ed1SJim Ingham   if (m_options_up != nullptr)
362658f6ed1SJim Ingham     loc_ignore = m_options_up->GetIgnoreCount();
363658f6ed1SJim Ingham 
364658f6ed1SJim Ingham   if (loc_ignore != 0 || owner_ignore != 0) {
3650fd1b75fSJim Ingham     m_owner.DecrementIgnoreCount();
366b9c1b51eSKate Stone     DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
367658f6ed1SJim Ingham                             // since it won't get a chance to.
3680fd1b75fSJim Ingham     return false;
3690fd1b75fSJim Ingham   }
3700fd1b75fSJim Ingham   return true;
3710fd1b75fSJim Ingham }
3720fd1b75fSJim Ingham 
GetLocationOptions()373cfb96d84SJim Ingham BreakpointOptions &BreakpointLocation::GetLocationOptions() {
37405097246SAdrian Prantl   // If we make the copy we don't copy the callbacks because that is
37505097246SAdrian Prantl   // potentially expensive and we don't want to do that for the simple case
37605097246SAdrian Prantl   // where someone is just disabling the location.
377d5b44036SJonas Devlieghere   if (m_options_up == nullptr)
37806412daeSJonas Devlieghere     m_options_up = std::make_unique<BreakpointOptions>(false);
37930fdc8d8SChris Lattner 
380cfb96d84SJim Ingham   return *m_options_up;
38130fdc8d8SChris Lattner }
38230fdc8d8SChris Lattner 
ValidForThisThread(Thread & thread)383cfb96d84SJim Ingham bool BreakpointLocation::ValidForThisThread(Thread &thread) {
384cfb96d84SJim Ingham   return thread.MatchesSpec(
385cfb96d84SJim Ingham       GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
386cfb96d84SJim Ingham           .GetThreadSpecNoCreate());
3871b54c88cSJim Ingham }
3881b54c88cSJim Ingham 
38930fdc8d8SChris Lattner // RETURNS - true if we should stop at this breakpoint, false if we
3901b54c88cSJim Ingham // should continue.  Note, we don't check the thread spec for the breakpoint
3911b54c88cSJim Ingham // here, since if the breakpoint is not for this thread, then the event won't
3921b54c88cSJim Ingham // even get reported, so the check is redundant.
39330fdc8d8SChris Lattner 
ShouldStop(StoppointCallbackContext * context)394b9c1b51eSKate Stone bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
39530fdc8d8SChris Lattner   bool should_stop = true;
396a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::Breakpoints);
39730fdc8d8SChris Lattner 
398b9c1b51eSKate Stone   // Do this first, if a location is disabled, it shouldn't increment its hit
399b9c1b51eSKate Stone   // count.
40030fdc8d8SChris Lattner   if (!IsEnabled())
40130fdc8d8SChris Lattner     return false;
40230fdc8d8SChris Lattner 
40336f3b369SJim Ingham   // We only run synchronous callbacks in ShouldStop:
40430fdc8d8SChris Lattner   context->is_synchronous = true;
40530fdc8d8SChris Lattner   should_stop = InvokeCallback(context);
40630fdc8d8SChris Lattner 
407b9c1b51eSKate Stone   if (log) {
40830fdc8d8SChris Lattner     StreamString s;
40930fdc8d8SChris Lattner     GetDescription(&s, lldb::eDescriptionLevelVerbose);
41063e5fb76SJonas Devlieghere     LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
411b9c1b51eSKate Stone               should_stop ? "stopping" : "continuing");
41230fdc8d8SChris Lattner   }
4135b52f0c7SJim Ingham 
41430fdc8d8SChris Lattner   return should_stop;
41530fdc8d8SChris Lattner }
41630fdc8d8SChris Lattner 
BumpHitCount()417b9c1b51eSKate Stone void BreakpointLocation::BumpHitCount() {
418b9c1b51eSKate Stone   if (IsEnabled()) {
419d762df8cSJim Ingham     // Step our hit count, and also step the hit count of the owner.
420da0bba5cSTatyana Krasnukha     m_hit_counter.Increment();
421da0bba5cSTatyana Krasnukha     m_owner.m_hit_counter.Increment();
422d762df8cSJim Ingham   }
423d762df8cSJim Ingham }
424d762df8cSJim Ingham 
UndoBumpHitCount()425b9c1b51eSKate Stone void BreakpointLocation::UndoBumpHitCount() {
426b9c1b51eSKate Stone   if (IsEnabled()) {
427d762df8cSJim Ingham     // Step our hit count, and also step the hit count of the owner.
428da0bba5cSTatyana Krasnukha     m_hit_counter.Decrement();
429da0bba5cSTatyana Krasnukha     m_owner.m_hit_counter.Decrement();
430d762df8cSJim Ingham   }
431a672ecefSJim Ingham }
432a672ecefSJim Ingham 
IsResolved() const433b9c1b51eSKate Stone bool BreakpointLocation::IsResolved() const {
43416fd7511SEugene Zelenko   return m_bp_site_sp.get() != nullptr;
43530fdc8d8SChris Lattner }
43630fdc8d8SChris Lattner 
GetBreakpointSite() const437b9c1b51eSKate Stone lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
43836f3b369SJim Ingham   return m_bp_site_sp;
43936f3b369SJim Ingham }
44036f3b369SJim Ingham 
ResolveBreakpointSite()441b9c1b51eSKate Stone bool BreakpointLocation::ResolveBreakpointSite() {
44230fdc8d8SChris Lattner   if (m_bp_site_sp)
44330fdc8d8SChris Lattner     return true;
44430fdc8d8SChris Lattner 
44530fdc8d8SChris Lattner   Process *process = m_owner.GetTarget().GetProcessSP().get();
44616fd7511SEugene Zelenko   if (process == nullptr)
44730fdc8d8SChris Lattner     return false;
44830fdc8d8SChris Lattner 
449b9c1b51eSKate Stone   lldb::break_id_t new_id =
450b9c1b51eSKate Stone       process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());
45130fdc8d8SChris Lattner 
452b9c1b51eSKate Stone   if (new_id == LLDB_INVALID_BREAK_ID) {
453a007a6d8SPavel Labath     Log *log = GetLog(LLDBLog::Breakpoints);
45430fdc8d8SChris Lattner     if (log)
455414f9b30STatyana Krasnukha       log->Warning("Failed to add breakpoint site at 0x%" PRIx64,
456f3ef3d2aSGreg Clayton                    m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()));
45730fdc8d8SChris Lattner   }
45830fdc8d8SChris Lattner 
459414f9b30STatyana Krasnukha   return IsResolved();
46030fdc8d8SChris Lattner }
46130fdc8d8SChris Lattner 
SetBreakpointSite(BreakpointSiteSP & bp_site_sp)462b9c1b51eSKate Stone bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
46330fdc8d8SChris Lattner   m_bp_site_sp = bp_site_sp;
4649b618d25SIlia K   SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
46530fdc8d8SChris Lattner   return true;
46630fdc8d8SChris Lattner }
46730fdc8d8SChris Lattner 
ClearBreakpointSite()468b9c1b51eSKate Stone bool BreakpointLocation::ClearBreakpointSite() {
469b9c1b51eSKate Stone   if (m_bp_site_sp.get()) {
47015783131SJim Ingham     ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
471b9c1b51eSKate Stone     // If the process exists, get it to remove the owner, it will remove the
47205097246SAdrian Prantl     // physical implementation of the breakpoint as well if there are no more
47305097246SAdrian Prantl     // owners.  Otherwise just remove this owner.
47415783131SJim Ingham     if (process_sp)
47515783131SJim Ingham       process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(),
4760136309fSJim Ingham                                                 GetID(), m_bp_site_sp);
47715783131SJim Ingham     else
47815783131SJim Ingham       m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID());
47915783131SJim Ingham 
48030fdc8d8SChris Lattner     m_bp_site_sp.reset();
48130fdc8d8SChris Lattner     return true;
48230fdc8d8SChris Lattner   }
48330fdc8d8SChris Lattner   return false;
48430fdc8d8SChris Lattner }
48530fdc8d8SChris Lattner 
GetDescription(Stream * s,lldb::DescriptionLevel level)486b9c1b51eSKate Stone void BreakpointLocation::GetDescription(Stream *s,
487b9c1b51eSKate Stone                                         lldb::DescriptionLevel level) {
48830fdc8d8SChris Lattner   SymbolContext sc;
4891391cc7dSJim Ingham 
490b9c1b51eSKate Stone   // If the description level is "initial" then the breakpoint is printing out
49105097246SAdrian Prantl   // our initial state, and we should let it decide how it wants to print our
49205097246SAdrian Prantl   // label.
493b9c1b51eSKate Stone   if (level != eDescriptionLevelInitial) {
49430fdc8d8SChris Lattner     s->Indent();
49530fdc8d8SChris Lattner     BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
4961391cc7dSJim Ingham   }
49730fdc8d8SChris Lattner 
49830fdc8d8SChris Lattner   if (level == lldb::eDescriptionLevelBrief)
49930fdc8d8SChris Lattner     return;
50030fdc8d8SChris Lattner 
5011391cc7dSJim Ingham   if (level != eDescriptionLevelInitial)
50230fdc8d8SChris Lattner     s->PutCString(": ");
50330fdc8d8SChris Lattner 
50430fdc8d8SChris Lattner   if (level == lldb::eDescriptionLevelVerbose)
50530fdc8d8SChris Lattner     s->IndentMore();
50630fdc8d8SChris Lattner 
507b9c1b51eSKate Stone   if (m_address.IsSectionOffset()) {
50830fdc8d8SChris Lattner     m_address.CalculateSymbolContext(&sc);
50930fdc8d8SChris Lattner 
510b9c1b51eSKate Stone     if (level == lldb::eDescriptionLevelFull ||
511b9c1b51eSKate Stone         level == eDescriptionLevelInitial) {
5121460e4bfSJim Ingham       if (IsReExported())
5131460e4bfSJim Ingham         s->PutCString("re-exported target = ");
5141460e4bfSJim Ingham       else
51530fdc8d8SChris Lattner         s->PutCString("where = ");
516b9c1b51eSKate Stone       sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
517b9c1b51eSKate Stone                          false, true, false, true, true);
518b9c1b51eSKate Stone     } else {
519b9c1b51eSKate Stone       if (sc.module_sp) {
52030fdc8d8SChris Lattner         s->EOL();
52130fdc8d8SChris Lattner         s->Indent("module = ");
5224dac97ebSRaphael Isemann         sc.module_sp->GetFileSpec().Dump(s->AsRawOstream());
52330fdc8d8SChris Lattner       }
52430fdc8d8SChris Lattner 
525b9c1b51eSKate Stone       if (sc.comp_unit != nullptr) {
52630fdc8d8SChris Lattner         s->EOL();
52730fdc8d8SChris Lattner         s->Indent("compile unit = ");
52838870af8SPavel Labath         sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s);
52930fdc8d8SChris Lattner 
530b9c1b51eSKate Stone         if (sc.function != nullptr) {
53130fdc8d8SChris Lattner           s->EOL();
53230fdc8d8SChris Lattner           s->Indent("function = ");
533ddaf6a72SGreg Clayton           s->PutCString(sc.function->GetName().AsCString("<unknown>"));
53430fdc8d8SChris Lattner         }
53530fdc8d8SChris Lattner 
536b9c1b51eSKate Stone         if (sc.line_entry.line > 0) {
53730fdc8d8SChris Lattner           s->EOL();
53830fdc8d8SChris Lattner           s->Indent("location = ");
5396dadd508SGreg Clayton           sc.line_entry.DumpStopContext(s, true);
54030fdc8d8SChris Lattner         }
54130fdc8d8SChris Lattner 
542b9c1b51eSKate Stone       } else {
54330fdc8d8SChris Lattner         // If we don't have a comp unit, see if we have a symbol we can print.
544b9c1b51eSKate Stone         if (sc.symbol) {
54530fdc8d8SChris Lattner           s->EOL();
5461460e4bfSJim Ingham           if (IsReExported())
5471460e4bfSJim Ingham             s->Indent("re-exported target = ");
5481460e4bfSJim Ingham           else
54930fdc8d8SChris Lattner             s->Indent("symbol = ");
550ddaf6a72SGreg Clayton           s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
55130fdc8d8SChris Lattner         }
55230fdc8d8SChris Lattner       }
55330fdc8d8SChris Lattner     }
55430fdc8d8SChris Lattner   }
55530fdc8d8SChris Lattner 
556b9c1b51eSKate Stone   if (level == lldb::eDescriptionLevelVerbose) {
55730fdc8d8SChris Lattner     s->EOL();
55830fdc8d8SChris Lattner     s->Indent();
55930fdc8d8SChris Lattner   }
5601391cc7dSJim Ingham 
561b9c1b51eSKate Stone   if (m_address.IsSectionOffset() &&
562b9c1b51eSKate Stone       (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
5631391cc7dSJim Ingham     s->Printf(", ");
5641391cc7dSJim Ingham   s->Printf("address = ");
5651391cc7dSJim Ingham 
56616fd7511SEugene Zelenko   ExecutionContextScope *exe_scope = nullptr;
56730fdc8d8SChris Lattner   Target *target = &m_owner.GetTarget();
56830fdc8d8SChris Lattner   if (target)
56930fdc8d8SChris Lattner     exe_scope = target->GetProcessSP().get();
57016fd7511SEugene Zelenko   if (exe_scope == nullptr)
57130fdc8d8SChris Lattner     exe_scope = target;
57230fdc8d8SChris Lattner 
5738f632665SJim Ingham   if (level == eDescriptionLevelInitial)
574b9c1b51eSKate Stone     m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
575b9c1b51eSKate Stone                    Address::DumpStyleFileAddress);
5761391cc7dSJim Ingham   else
577b9c1b51eSKate Stone     m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
578b9c1b51eSKate Stone                    Address::DumpStyleModuleWithFileAddress);
57930fdc8d8SChris Lattner 
580b9c1b51eSKate Stone   if (IsIndirect() && m_bp_site_sp) {
5811460e4bfSJim Ingham     Address resolved_address;
5821460e4bfSJim Ingham     resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
5831460e4bfSJim Ingham     Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
584b9c1b51eSKate Stone     if (resolved_symbol) {
5851460e4bfSJim Ingham       if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
5861460e4bfSJim Ingham         s->Printf(", ");
587b9c1b51eSKate Stone       else if (level == lldb::eDescriptionLevelVerbose) {
5881460e4bfSJim Ingham         s->EOL();
5891460e4bfSJim Ingham         s->Indent();
5901460e4bfSJim Ingham       }
591b9c1b51eSKate Stone       s->Printf("indirect target = %s",
592b9c1b51eSKate Stone                 resolved_symbol->GetName().GetCString());
5931460e4bfSJim Ingham     }
5941460e4bfSJim Ingham   }
5951460e4bfSJim Ingham 
596da0bba5cSTatyana Krasnukha   bool is_resolved = IsResolved();
597da0bba5cSTatyana Krasnukha   bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
598da0bba5cSTatyana Krasnukha 
599b9c1b51eSKate Stone   if (level == lldb::eDescriptionLevelVerbose) {
60030fdc8d8SChris Lattner     s->EOL();
60130fdc8d8SChris Lattner     s->Indent();
602da0bba5cSTatyana Krasnukha     s->Printf("resolved = %s\n", is_resolved ? "true" : "false");
603d8e0f4faSJonas Devlieghere     s->Indent();
604da0bba5cSTatyana Krasnukha     s->Printf("hardware = %s\n", is_hardware ? "true" : "false");
60530fdc8d8SChris Lattner     s->Indent();
60630fdc8d8SChris Lattner     s->Printf("hit count = %-4u\n", GetHitCount());
60730fdc8d8SChris Lattner 
608d5b44036SJonas Devlieghere     if (m_options_up) {
60930fdc8d8SChris Lattner       s->Indent();
610d5b44036SJonas Devlieghere       m_options_up->GetDescription(s, level);
61130fdc8d8SChris Lattner       s->EOL();
61230fdc8d8SChris Lattner     }
61330fdc8d8SChris Lattner     s->IndentLess();
614b9c1b51eSKate Stone   } else if (level != eDescriptionLevelInitial) {
615da0bba5cSTatyana Krasnukha     s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"),
616da0bba5cSTatyana Krasnukha               (is_hardware ? "hardware, " : ""), GetHitCount());
617d5b44036SJonas Devlieghere     if (m_options_up) {
618d5b44036SJonas Devlieghere       m_options_up->GetDescription(s, level);
6190136309fSJim Ingham     }
62030fdc8d8SChris Lattner   }
62130fdc8d8SChris Lattner }
62230fdc8d8SChris Lattner 
Dump(Stream * s) const623b9c1b51eSKate Stone void BreakpointLocation::Dump(Stream *s) const {
62416fd7511SEugene Zelenko   if (s == nullptr)
62530fdc8d8SChris Lattner     return;
62630fdc8d8SChris Lattner 
627da0bba5cSTatyana Krasnukha   bool is_resolved = IsResolved();
628da0bba5cSTatyana Krasnukha   bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
629da0bba5cSTatyana Krasnukha   auto hardware_index = is_resolved ?
630da0bba5cSTatyana Krasnukha       m_bp_site_sp->GetHardwareIndex() : LLDB_INVALID_INDEX32;
631da0bba5cSTatyana Krasnukha 
632af26b22cSJim Ingham   lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
633cfb96d84SJim Ingham                         .GetThreadSpecNoCreate()
634cfb96d84SJim Ingham                         ->GetTID();
63570355aceSJonas Devlieghere   s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
63670355aceSJonas Devlieghere             "  load addr = 0x%8.8" PRIx64 "  state = %s  type = %s breakpoint  "
6370136309fSJim Ingham             "hw_index = %i  hit_count = %-4u  ignore_count = %-4u",
638af26b22cSJim Ingham             GetID(), tid,
639f3ef3d2aSGreg Clayton             (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
640d5b44036SJonas Devlieghere             (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
641b9c1b51eSKate Stone                 ? "enabled "
642b9c1b51eSKate Stone                 : "disabled",
643cfb96d84SJim Ingham             is_hardware ? "hardware" : "software", hardware_index,
644cfb96d84SJim Ingham             GetHitCount(),
645af26b22cSJim Ingham             GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
646cfb96d84SJim Ingham                 .GetIgnoreCount());
64730fdc8d8SChris Lattner }
648e6bc6cb9SJim Ingham 
SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind)649b9c1b51eSKate Stone void BreakpointLocation::SendBreakpointLocationChangedEvent(
650b9c1b51eSKate Stone     lldb::BreakpointEventType eventKind) {
651b9c1b51eSKate Stone   if (!m_being_created && !m_owner.IsInternal() &&
652b9c1b51eSKate Stone       m_owner.GetTarget().EventTypeHasListeners(
653b9c1b51eSKate Stone           Target::eBroadcastBitBreakpointChanged)) {
654b9c1b51eSKate Stone     Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData(
655b9c1b51eSKate Stone         eventKind, m_owner.shared_from_this());
656e6bc6cb9SJim Ingham     data->GetBreakpointLocationCollection().Add(shared_from_this());
657b9c1b51eSKate Stone     m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
658b9c1b51eSKate Stone                                        data);
659e6bc6cb9SJim Ingham   }
660e6bc6cb9SJim Ingham }
661e6bc6cb9SJim Ingham 
SwapLocation(BreakpointLocationSP swap_from)662b9c1b51eSKate Stone void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
66377fd738fSJim Ingham   m_address = swap_from->m_address;
664b9c1b51eSKate Stone   m_should_resolve_indirect_functions =
665b9c1b51eSKate Stone       swap_from->m_should_resolve_indirect_functions;
66677fd738fSJim Ingham   m_is_reexported = swap_from->m_is_reexported;
66777fd738fSJim Ingham   m_is_indirect = swap_from->m_is_indirect;
66877fd738fSJim Ingham   m_user_expression_sp.reset();
66977fd738fSJim Ingham }
670