1dda28197Spatrick //===-- BreakpointLocation.cpp --------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
10061da546Spatrick #include "lldb/Breakpoint/BreakpointID.h"
11061da546Spatrick #include "lldb/Breakpoint/StoppointCallbackContext.h"
12061da546Spatrick #include "lldb/Core/Debugger.h"
13061da546Spatrick #include "lldb/Core/Module.h"
14061da546Spatrick #include "lldb/Core/ValueObject.h"
15061da546Spatrick #include "lldb/Expression/DiagnosticManager.h"
16061da546Spatrick #include "lldb/Expression/ExpressionVariable.h"
17061da546Spatrick #include "lldb/Expression/UserExpression.h"
18061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
19061da546Spatrick #include "lldb/Symbol/Symbol.h"
20061da546Spatrick #include "lldb/Symbol/TypeSystem.h"
21061da546Spatrick #include "lldb/Target/Process.h"
22061da546Spatrick #include "lldb/Target/Target.h"
23061da546Spatrick #include "lldb/Target/Thread.h"
24061da546Spatrick #include "lldb/Target/ThreadSpec.h"
25*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
26061da546Spatrick #include "lldb/Utility/Log.h"
27061da546Spatrick #include "lldb/Utility/StreamString.h"
28061da546Spatrick
29061da546Spatrick using namespace lldb;
30061da546Spatrick using namespace lldb_private;
31061da546Spatrick
BreakpointLocation(break_id_t loc_id,Breakpoint & owner,const Address & addr,lldb::tid_t tid,bool hardware,bool check_for_resolver)32061da546Spatrick BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner,
33061da546Spatrick const Address &addr, lldb::tid_t tid,
34061da546Spatrick bool hardware, bool check_for_resolver)
35be691f3bSpatrick : m_being_created(true), m_should_resolve_indirect_functions(false),
36061da546Spatrick m_is_reexported(false), m_is_indirect(false), m_address(addr),
37*f6aab3d8Srobert m_owner(owner), m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() {
38061da546Spatrick if (check_for_resolver) {
39061da546Spatrick Symbol *symbol = m_address.CalculateSymbolContextSymbol();
40061da546Spatrick if (symbol && symbol->IsIndirect()) {
41061da546Spatrick SetShouldResolveIndirectFunctions(true);
42061da546Spatrick }
43061da546Spatrick }
44061da546Spatrick
45061da546Spatrick SetThreadID(tid);
46061da546Spatrick m_being_created = false;
47061da546Spatrick }
48061da546Spatrick
~BreakpointLocation()49061da546Spatrick BreakpointLocation::~BreakpointLocation() { ClearBreakpointSite(); }
50061da546Spatrick
GetLoadAddress() const51061da546Spatrick lldb::addr_t BreakpointLocation::GetLoadAddress() const {
52061da546Spatrick return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
53061da546Spatrick }
54061da546Spatrick
GetOptionsSpecifyingKind(BreakpointOptions::OptionKind kind) const55be691f3bSpatrick const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind(
56be691f3bSpatrick BreakpointOptions::OptionKind kind) const {
57061da546Spatrick if (m_options_up && m_options_up->IsOptionSet(kind))
58be691f3bSpatrick return *m_options_up;
59061da546Spatrick else
60061da546Spatrick return m_owner.GetOptions();
61061da546Spatrick }
62061da546Spatrick
GetAddress()63061da546Spatrick Address &BreakpointLocation::GetAddress() { return m_address; }
64061da546Spatrick
GetBreakpoint()65061da546Spatrick Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }
66061da546Spatrick
GetTarget()67061da546Spatrick Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }
68061da546Spatrick
IsEnabled() const69061da546Spatrick bool BreakpointLocation::IsEnabled() const {
70061da546Spatrick if (!m_owner.IsEnabled())
71061da546Spatrick return false;
72061da546Spatrick else if (m_options_up != nullptr)
73061da546Spatrick return m_options_up->IsEnabled();
74061da546Spatrick else
75061da546Spatrick return true;
76061da546Spatrick }
77061da546Spatrick
SetEnabled(bool enabled)78061da546Spatrick void BreakpointLocation::SetEnabled(bool enabled) {
79be691f3bSpatrick GetLocationOptions().SetEnabled(enabled);
80061da546Spatrick if (enabled) {
81061da546Spatrick ResolveBreakpointSite();
82061da546Spatrick } else {
83061da546Spatrick ClearBreakpointSite();
84061da546Spatrick }
85061da546Spatrick SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
86061da546Spatrick : eBreakpointEventTypeDisabled);
87061da546Spatrick }
88061da546Spatrick
IsAutoContinue() const89061da546Spatrick bool BreakpointLocation::IsAutoContinue() const {
90061da546Spatrick if (m_options_up &&
91061da546Spatrick m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue))
92061da546Spatrick return m_options_up->IsAutoContinue();
93061da546Spatrick else
94061da546Spatrick return m_owner.IsAutoContinue();
95061da546Spatrick }
96061da546Spatrick
SetAutoContinue(bool auto_continue)97061da546Spatrick void BreakpointLocation::SetAutoContinue(bool auto_continue) {
98be691f3bSpatrick GetLocationOptions().SetAutoContinue(auto_continue);
99061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
100061da546Spatrick }
101061da546Spatrick
SetThreadID(lldb::tid_t thread_id)102061da546Spatrick void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
103061da546Spatrick if (thread_id != LLDB_INVALID_THREAD_ID)
104be691f3bSpatrick GetLocationOptions().SetThreadID(thread_id);
105061da546Spatrick else {
106061da546Spatrick // If we're resetting this to an invalid thread id, then don't make an
107061da546Spatrick // options pointer just to do that.
108061da546Spatrick if (m_options_up != nullptr)
109061da546Spatrick m_options_up->SetThreadID(thread_id);
110061da546Spatrick }
111061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
112061da546Spatrick }
113061da546Spatrick
GetThreadID()114061da546Spatrick lldb::tid_t BreakpointLocation::GetThreadID() {
115061da546Spatrick const ThreadSpec *thread_spec =
116061da546Spatrick GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
117be691f3bSpatrick .GetThreadSpecNoCreate();
118061da546Spatrick if (thread_spec)
119061da546Spatrick return thread_spec->GetTID();
120061da546Spatrick else
121061da546Spatrick return LLDB_INVALID_THREAD_ID;
122061da546Spatrick }
123061da546Spatrick
SetThreadIndex(uint32_t index)124061da546Spatrick void BreakpointLocation::SetThreadIndex(uint32_t index) {
125061da546Spatrick if (index != 0)
126be691f3bSpatrick GetLocationOptions().GetThreadSpec()->SetIndex(index);
127061da546Spatrick else {
128061da546Spatrick // If we're resetting this to an invalid thread id, then don't make an
129061da546Spatrick // options pointer just to do that.
130061da546Spatrick if (m_options_up != nullptr)
131061da546Spatrick m_options_up->GetThreadSpec()->SetIndex(index);
132061da546Spatrick }
133061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
134061da546Spatrick }
135061da546Spatrick
GetThreadIndex() const136061da546Spatrick uint32_t BreakpointLocation::GetThreadIndex() const {
137061da546Spatrick const ThreadSpec *thread_spec =
138061da546Spatrick GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
139be691f3bSpatrick .GetThreadSpecNoCreate();
140061da546Spatrick if (thread_spec)
141061da546Spatrick return thread_spec->GetIndex();
142061da546Spatrick else
143061da546Spatrick return 0;
144061da546Spatrick }
145061da546Spatrick
SetThreadName(const char * thread_name)146061da546Spatrick void BreakpointLocation::SetThreadName(const char *thread_name) {
147061da546Spatrick if (thread_name != nullptr)
148be691f3bSpatrick GetLocationOptions().GetThreadSpec()->SetName(thread_name);
149061da546Spatrick else {
150061da546Spatrick // If we're resetting this to an invalid thread id, then don't make an
151061da546Spatrick // options pointer just to do that.
152061da546Spatrick if (m_options_up != nullptr)
153061da546Spatrick m_options_up->GetThreadSpec()->SetName(thread_name);
154061da546Spatrick }
155061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
156061da546Spatrick }
157061da546Spatrick
GetThreadName() const158061da546Spatrick const char *BreakpointLocation::GetThreadName() const {
159061da546Spatrick const ThreadSpec *thread_spec =
160061da546Spatrick GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
161be691f3bSpatrick .GetThreadSpecNoCreate();
162061da546Spatrick if (thread_spec)
163061da546Spatrick return thread_spec->GetName();
164061da546Spatrick else
165061da546Spatrick return nullptr;
166061da546Spatrick }
167061da546Spatrick
SetQueueName(const char * queue_name)168061da546Spatrick void BreakpointLocation::SetQueueName(const char *queue_name) {
169061da546Spatrick if (queue_name != nullptr)
170be691f3bSpatrick GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name);
171061da546Spatrick else {
172061da546Spatrick // If we're resetting this to an invalid thread id, then don't make an
173061da546Spatrick // options pointer just to do that.
174061da546Spatrick if (m_options_up != nullptr)
175061da546Spatrick m_options_up->GetThreadSpec()->SetQueueName(queue_name);
176061da546Spatrick }
177061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
178061da546Spatrick }
179061da546Spatrick
GetQueueName() const180061da546Spatrick const char *BreakpointLocation::GetQueueName() const {
181061da546Spatrick const ThreadSpec *thread_spec =
182061da546Spatrick GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
183be691f3bSpatrick .GetThreadSpecNoCreate();
184061da546Spatrick if (thread_spec)
185061da546Spatrick return thread_spec->GetQueueName();
186061da546Spatrick else
187061da546Spatrick return nullptr;
188061da546Spatrick }
189061da546Spatrick
InvokeCallback(StoppointCallbackContext * context)190061da546Spatrick bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
191061da546Spatrick if (m_options_up != nullptr && m_options_up->HasCallback())
192061da546Spatrick return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID());
193061da546Spatrick else
194061da546Spatrick return m_owner.InvokeCallback(context, GetID());
195061da546Spatrick }
196061da546Spatrick
IsCallbackSynchronous()197be691f3bSpatrick bool BreakpointLocation::IsCallbackSynchronous() {
198be691f3bSpatrick if (m_options_up != nullptr && m_options_up->HasCallback())
199be691f3bSpatrick return m_options_up->IsCallbackSynchronous();
200be691f3bSpatrick else
201be691f3bSpatrick return m_owner.GetOptions().IsCallbackSynchronous();
202be691f3bSpatrick }
203be691f3bSpatrick
SetCallback(BreakpointHitCallback callback,void * baton,bool is_synchronous)204061da546Spatrick void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
205061da546Spatrick void *baton, bool is_synchronous) {
206061da546Spatrick // The default "Baton" class will keep a copy of "baton" and won't free or
207061da546Spatrick // delete it when it goes goes out of scope.
208be691f3bSpatrick GetLocationOptions().SetCallback(
209061da546Spatrick callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
210061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
211061da546Spatrick }
212061da546Spatrick
SetCallback(BreakpointHitCallback callback,const BatonSP & baton_sp,bool is_synchronous)213061da546Spatrick void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
214061da546Spatrick const BatonSP &baton_sp,
215061da546Spatrick bool is_synchronous) {
216be691f3bSpatrick GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous);
217061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
218061da546Spatrick }
219061da546Spatrick
ClearCallback()220061da546Spatrick void BreakpointLocation::ClearCallback() {
221be691f3bSpatrick GetLocationOptions().ClearCallback();
222061da546Spatrick }
223061da546Spatrick
SetCondition(const char * condition)224061da546Spatrick void BreakpointLocation::SetCondition(const char *condition) {
225be691f3bSpatrick GetLocationOptions().SetCondition(condition);
226061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
227061da546Spatrick }
228061da546Spatrick
GetConditionText(size_t * hash) const229061da546Spatrick const char *BreakpointLocation::GetConditionText(size_t *hash) const {
230061da546Spatrick return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
231be691f3bSpatrick .GetConditionText(hash);
232061da546Spatrick }
233061da546Spatrick
ConditionSaysStop(ExecutionContext & exe_ctx,Status & error)234061da546Spatrick bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
235061da546Spatrick Status &error) {
236*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Breakpoints);
237061da546Spatrick
238061da546Spatrick std::lock_guard<std::mutex> guard(m_condition_mutex);
239061da546Spatrick
240061da546Spatrick size_t condition_hash;
241061da546Spatrick const char *condition_text = GetConditionText(&condition_hash);
242061da546Spatrick
243061da546Spatrick if (!condition_text) {
244061da546Spatrick m_user_expression_sp.reset();
245061da546Spatrick return false;
246061da546Spatrick }
247061da546Spatrick
248061da546Spatrick error.Clear();
249061da546Spatrick
250061da546Spatrick DiagnosticManager diagnostics;
251061da546Spatrick
252061da546Spatrick if (condition_hash != m_condition_hash || !m_user_expression_sp ||
253061da546Spatrick !m_user_expression_sp->MatchesContext(exe_ctx)) {
254061da546Spatrick LanguageType language = eLanguageTypeUnknown;
255061da546Spatrick // See if we can figure out the language from the frame, otherwise use the
256061da546Spatrick // default language:
257061da546Spatrick CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
258061da546Spatrick if (comp_unit)
259061da546Spatrick language = comp_unit->GetLanguage();
260061da546Spatrick
261061da546Spatrick m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
262061da546Spatrick condition_text, llvm::StringRef(), language, Expression::eResultTypeAny,
263061da546Spatrick EvaluateExpressionOptions(), nullptr, error));
264061da546Spatrick if (error.Fail()) {
265061da546Spatrick LLDB_LOGF(log, "Error getting condition expression: %s.",
266061da546Spatrick error.AsCString());
267061da546Spatrick m_user_expression_sp.reset();
268061da546Spatrick return true;
269061da546Spatrick }
270061da546Spatrick
271061da546Spatrick if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
272061da546Spatrick eExecutionPolicyOnlyWhenNeeded, true,
273061da546Spatrick false)) {
274061da546Spatrick error.SetErrorStringWithFormat(
275061da546Spatrick "Couldn't parse conditional expression:\n%s",
276061da546Spatrick diagnostics.GetString().c_str());
277061da546Spatrick m_user_expression_sp.reset();
278061da546Spatrick return true;
279061da546Spatrick }
280061da546Spatrick
281061da546Spatrick m_condition_hash = condition_hash;
282061da546Spatrick }
283061da546Spatrick
284061da546Spatrick // We need to make sure the user sees any parse errors in their condition, so
285061da546Spatrick // we'll hook the constructor errors up to the debugger's Async I/O.
286061da546Spatrick
287061da546Spatrick ValueObjectSP result_value_sp;
288061da546Spatrick
289061da546Spatrick EvaluateExpressionOptions options;
290061da546Spatrick options.SetUnwindOnError(true);
291061da546Spatrick options.SetIgnoreBreakpoints(true);
292061da546Spatrick options.SetTryAllThreads(true);
293061da546Spatrick options.SetResultIsInternal(
294061da546Spatrick true); // Don't generate a user variable for condition expressions.
295061da546Spatrick
296061da546Spatrick Status expr_error;
297061da546Spatrick
298061da546Spatrick diagnostics.Clear();
299061da546Spatrick
300061da546Spatrick ExpressionVariableSP result_variable_sp;
301061da546Spatrick
302061da546Spatrick ExpressionResults result_code = m_user_expression_sp->Execute(
303061da546Spatrick diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);
304061da546Spatrick
305061da546Spatrick bool ret;
306061da546Spatrick
307061da546Spatrick if (result_code == eExpressionCompleted) {
308061da546Spatrick if (!result_variable_sp) {
309061da546Spatrick error.SetErrorString("Expression did not return a result");
310061da546Spatrick return false;
311061da546Spatrick }
312061da546Spatrick
313061da546Spatrick result_value_sp = result_variable_sp->GetValueObject();
314061da546Spatrick
315061da546Spatrick if (result_value_sp) {
316061da546Spatrick ret = result_value_sp->IsLogicalTrue(error);
317061da546Spatrick if (log) {
318061da546Spatrick if (error.Success()) {
319061da546Spatrick LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n",
320061da546Spatrick ret ? "true" : "false");
321061da546Spatrick } else {
322061da546Spatrick error.SetErrorString(
323061da546Spatrick "Failed to get an integer result from the expression");
324061da546Spatrick ret = false;
325061da546Spatrick }
326061da546Spatrick }
327061da546Spatrick } else {
328061da546Spatrick ret = false;
329061da546Spatrick error.SetErrorString("Failed to get any result from the expression");
330061da546Spatrick }
331061da546Spatrick } else {
332061da546Spatrick ret = false;
333061da546Spatrick error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
334061da546Spatrick diagnostics.GetString().c_str());
335061da546Spatrick }
336061da546Spatrick
337061da546Spatrick return ret;
338061da546Spatrick }
339061da546Spatrick
GetIgnoreCount() const340be691f3bSpatrick uint32_t BreakpointLocation::GetIgnoreCount() const {
341061da546Spatrick return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
342be691f3bSpatrick .GetIgnoreCount();
343061da546Spatrick }
344061da546Spatrick
SetIgnoreCount(uint32_t n)345061da546Spatrick void BreakpointLocation::SetIgnoreCount(uint32_t n) {
346be691f3bSpatrick GetLocationOptions().SetIgnoreCount(n);
347061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
348061da546Spatrick }
349061da546Spatrick
DecrementIgnoreCount()350061da546Spatrick void BreakpointLocation::DecrementIgnoreCount() {
351061da546Spatrick if (m_options_up != nullptr) {
352061da546Spatrick uint32_t loc_ignore = m_options_up->GetIgnoreCount();
353061da546Spatrick if (loc_ignore != 0)
354061da546Spatrick m_options_up->SetIgnoreCount(loc_ignore - 1);
355061da546Spatrick }
356061da546Spatrick }
357061da546Spatrick
IgnoreCountShouldStop()358061da546Spatrick bool BreakpointLocation::IgnoreCountShouldStop() {
359be691f3bSpatrick uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
360be691f3bSpatrick uint32_t loc_ignore = 0;
361be691f3bSpatrick if (m_options_up != nullptr)
362be691f3bSpatrick loc_ignore = m_options_up->GetIgnoreCount();
363be691f3bSpatrick
364be691f3bSpatrick if (loc_ignore != 0 || owner_ignore != 0) {
365061da546Spatrick m_owner.DecrementIgnoreCount();
366061da546Spatrick DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
367be691f3bSpatrick // since it won't get a chance to.
368061da546Spatrick return false;
369061da546Spatrick }
370061da546Spatrick return true;
371061da546Spatrick }
372061da546Spatrick
GetLocationOptions()373be691f3bSpatrick BreakpointOptions &BreakpointLocation::GetLocationOptions() {
374061da546Spatrick // If we make the copy we don't copy the callbacks because that is
375061da546Spatrick // potentially expensive and we don't want to do that for the simple case
376061da546Spatrick // where someone is just disabling the location.
377061da546Spatrick if (m_options_up == nullptr)
378dda28197Spatrick m_options_up = std::make_unique<BreakpointOptions>(false);
379061da546Spatrick
380be691f3bSpatrick return *m_options_up;
381061da546Spatrick }
382061da546Spatrick
ValidForThisThread(Thread & thread)383be691f3bSpatrick bool BreakpointLocation::ValidForThisThread(Thread &thread) {
384be691f3bSpatrick return thread.MatchesSpec(
385be691f3bSpatrick GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
386be691f3bSpatrick .GetThreadSpecNoCreate());
387061da546Spatrick }
388061da546Spatrick
389061da546Spatrick // RETURNS - true if we should stop at this breakpoint, false if we
390061da546Spatrick // should continue. Note, we don't check the thread spec for the breakpoint
391061da546Spatrick // here, since if the breakpoint is not for this thread, then the event won't
392061da546Spatrick // even get reported, so the check is redundant.
393061da546Spatrick
ShouldStop(StoppointCallbackContext * context)394061da546Spatrick bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
395061da546Spatrick bool should_stop = true;
396*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Breakpoints);
397061da546Spatrick
398061da546Spatrick // Do this first, if a location is disabled, it shouldn't increment its hit
399061da546Spatrick // count.
400061da546Spatrick if (!IsEnabled())
401061da546Spatrick return false;
402061da546Spatrick
403061da546Spatrick // We only run synchronous callbacks in ShouldStop:
404061da546Spatrick context->is_synchronous = true;
405061da546Spatrick should_stop = InvokeCallback(context);
406061da546Spatrick
407061da546Spatrick if (log) {
408061da546Spatrick StreamString s;
409061da546Spatrick GetDescription(&s, lldb::eDescriptionLevelVerbose);
410061da546Spatrick LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
411061da546Spatrick should_stop ? "stopping" : "continuing");
412061da546Spatrick }
413061da546Spatrick
414061da546Spatrick return should_stop;
415061da546Spatrick }
416061da546Spatrick
BumpHitCount()417061da546Spatrick void BreakpointLocation::BumpHitCount() {
418061da546Spatrick if (IsEnabled()) {
419061da546Spatrick // Step our hit count, and also step the hit count of the owner.
420be691f3bSpatrick m_hit_counter.Increment();
421be691f3bSpatrick m_owner.m_hit_counter.Increment();
422061da546Spatrick }
423061da546Spatrick }
424061da546Spatrick
UndoBumpHitCount()425061da546Spatrick void BreakpointLocation::UndoBumpHitCount() {
426061da546Spatrick if (IsEnabled()) {
427061da546Spatrick // Step our hit count, and also step the hit count of the owner.
428be691f3bSpatrick m_hit_counter.Decrement();
429be691f3bSpatrick m_owner.m_hit_counter.Decrement();
430061da546Spatrick }
431061da546Spatrick }
432061da546Spatrick
IsResolved() const433061da546Spatrick bool BreakpointLocation::IsResolved() const {
434061da546Spatrick return m_bp_site_sp.get() != nullptr;
435061da546Spatrick }
436061da546Spatrick
GetBreakpointSite() const437061da546Spatrick lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
438061da546Spatrick return m_bp_site_sp;
439061da546Spatrick }
440061da546Spatrick
ResolveBreakpointSite()441061da546Spatrick bool BreakpointLocation::ResolveBreakpointSite() {
442061da546Spatrick if (m_bp_site_sp)
443061da546Spatrick return true;
444061da546Spatrick
445061da546Spatrick Process *process = m_owner.GetTarget().GetProcessSP().get();
446061da546Spatrick if (process == nullptr)
447061da546Spatrick return false;
448061da546Spatrick
449061da546Spatrick lldb::break_id_t new_id =
450061da546Spatrick process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());
451061da546Spatrick
452061da546Spatrick if (new_id == LLDB_INVALID_BREAK_ID) {
453*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Breakpoints);
454061da546Spatrick if (log)
455061da546Spatrick log->Warning("Failed to add breakpoint site at 0x%" PRIx64,
456061da546Spatrick m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()));
457061da546Spatrick }
458061da546Spatrick
459061da546Spatrick return IsResolved();
460061da546Spatrick }
461061da546Spatrick
SetBreakpointSite(BreakpointSiteSP & bp_site_sp)462061da546Spatrick bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
463061da546Spatrick m_bp_site_sp = bp_site_sp;
464061da546Spatrick SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
465061da546Spatrick return true;
466061da546Spatrick }
467061da546Spatrick
ClearBreakpointSite()468061da546Spatrick bool BreakpointLocation::ClearBreakpointSite() {
469061da546Spatrick if (m_bp_site_sp.get()) {
470061da546Spatrick ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
471061da546Spatrick // If the process exists, get it to remove the owner, it will remove the
472061da546Spatrick // physical implementation of the breakpoint as well if there are no more
473061da546Spatrick // owners. Otherwise just remove this owner.
474061da546Spatrick if (process_sp)
475061da546Spatrick process_sp->RemoveOwnerFromBreakpointSite(GetBreakpoint().GetID(),
476061da546Spatrick GetID(), m_bp_site_sp);
477061da546Spatrick else
478061da546Spatrick m_bp_site_sp->RemoveOwner(GetBreakpoint().GetID(), GetID());
479061da546Spatrick
480061da546Spatrick m_bp_site_sp.reset();
481061da546Spatrick return true;
482061da546Spatrick }
483061da546Spatrick return false;
484061da546Spatrick }
485061da546Spatrick
GetDescription(Stream * s,lldb::DescriptionLevel level)486061da546Spatrick void BreakpointLocation::GetDescription(Stream *s,
487061da546Spatrick lldb::DescriptionLevel level) {
488061da546Spatrick SymbolContext sc;
489061da546Spatrick
490061da546Spatrick // If the description level is "initial" then the breakpoint is printing out
491061da546Spatrick // our initial state, and we should let it decide how it wants to print our
492061da546Spatrick // label.
493061da546Spatrick if (level != eDescriptionLevelInitial) {
494061da546Spatrick s->Indent();
495061da546Spatrick BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
496061da546Spatrick }
497061da546Spatrick
498061da546Spatrick if (level == lldb::eDescriptionLevelBrief)
499061da546Spatrick return;
500061da546Spatrick
501061da546Spatrick if (level != eDescriptionLevelInitial)
502061da546Spatrick s->PutCString(": ");
503061da546Spatrick
504061da546Spatrick if (level == lldb::eDescriptionLevelVerbose)
505061da546Spatrick s->IndentMore();
506061da546Spatrick
507061da546Spatrick if (m_address.IsSectionOffset()) {
508061da546Spatrick m_address.CalculateSymbolContext(&sc);
509061da546Spatrick
510061da546Spatrick if (level == lldb::eDescriptionLevelFull ||
511061da546Spatrick level == eDescriptionLevelInitial) {
512061da546Spatrick if (IsReExported())
513061da546Spatrick s->PutCString("re-exported target = ");
514061da546Spatrick else
515061da546Spatrick s->PutCString("where = ");
516061da546Spatrick sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
517061da546Spatrick false, true, false, true, true);
518061da546Spatrick } else {
519061da546Spatrick if (sc.module_sp) {
520061da546Spatrick s->EOL();
521061da546Spatrick s->Indent("module = ");
522061da546Spatrick sc.module_sp->GetFileSpec().Dump(s->AsRawOstream());
523061da546Spatrick }
524061da546Spatrick
525061da546Spatrick if (sc.comp_unit != nullptr) {
526061da546Spatrick s->EOL();
527061da546Spatrick s->Indent("compile unit = ");
528061da546Spatrick sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s);
529061da546Spatrick
530061da546Spatrick if (sc.function != nullptr) {
531061da546Spatrick s->EOL();
532061da546Spatrick s->Indent("function = ");
533061da546Spatrick s->PutCString(sc.function->GetName().AsCString("<unknown>"));
534061da546Spatrick }
535061da546Spatrick
536061da546Spatrick if (sc.line_entry.line > 0) {
537061da546Spatrick s->EOL();
538061da546Spatrick s->Indent("location = ");
539061da546Spatrick sc.line_entry.DumpStopContext(s, true);
540061da546Spatrick }
541061da546Spatrick
542061da546Spatrick } else {
543061da546Spatrick // If we don't have a comp unit, see if we have a symbol we can print.
544061da546Spatrick if (sc.symbol) {
545061da546Spatrick s->EOL();
546061da546Spatrick if (IsReExported())
547061da546Spatrick s->Indent("re-exported target = ");
548061da546Spatrick else
549061da546Spatrick s->Indent("symbol = ");
550061da546Spatrick s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
551061da546Spatrick }
552061da546Spatrick }
553061da546Spatrick }
554061da546Spatrick }
555061da546Spatrick
556061da546Spatrick if (level == lldb::eDescriptionLevelVerbose) {
557061da546Spatrick s->EOL();
558061da546Spatrick s->Indent();
559061da546Spatrick }
560061da546Spatrick
561061da546Spatrick if (m_address.IsSectionOffset() &&
562061da546Spatrick (level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
563061da546Spatrick s->Printf(", ");
564061da546Spatrick s->Printf("address = ");
565061da546Spatrick
566061da546Spatrick ExecutionContextScope *exe_scope = nullptr;
567061da546Spatrick Target *target = &m_owner.GetTarget();
568061da546Spatrick if (target)
569061da546Spatrick exe_scope = target->GetProcessSP().get();
570061da546Spatrick if (exe_scope == nullptr)
571061da546Spatrick exe_scope = target;
572061da546Spatrick
573061da546Spatrick if (level == eDescriptionLevelInitial)
574061da546Spatrick m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
575061da546Spatrick Address::DumpStyleFileAddress);
576061da546Spatrick else
577061da546Spatrick m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
578061da546Spatrick Address::DumpStyleModuleWithFileAddress);
579061da546Spatrick
580061da546Spatrick if (IsIndirect() && m_bp_site_sp) {
581061da546Spatrick Address resolved_address;
582061da546Spatrick resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
583061da546Spatrick Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
584061da546Spatrick if (resolved_symbol) {
585061da546Spatrick if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
586061da546Spatrick s->Printf(", ");
587061da546Spatrick else if (level == lldb::eDescriptionLevelVerbose) {
588061da546Spatrick s->EOL();
589061da546Spatrick s->Indent();
590061da546Spatrick }
591061da546Spatrick s->Printf("indirect target = %s",
592061da546Spatrick resolved_symbol->GetName().GetCString());
593061da546Spatrick }
594061da546Spatrick }
595061da546Spatrick
596be691f3bSpatrick bool is_resolved = IsResolved();
597be691f3bSpatrick bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
598be691f3bSpatrick
599061da546Spatrick if (level == lldb::eDescriptionLevelVerbose) {
600061da546Spatrick s->EOL();
601061da546Spatrick s->Indent();
602be691f3bSpatrick s->Printf("resolved = %s\n", is_resolved ? "true" : "false");
603dda28197Spatrick s->Indent();
604be691f3bSpatrick s->Printf("hardware = %s\n", is_hardware ? "true" : "false");
605061da546Spatrick s->Indent();
606061da546Spatrick s->Printf("hit count = %-4u\n", GetHitCount());
607061da546Spatrick
608061da546Spatrick if (m_options_up) {
609061da546Spatrick s->Indent();
610061da546Spatrick m_options_up->GetDescription(s, level);
611061da546Spatrick s->EOL();
612061da546Spatrick }
613061da546Spatrick s->IndentLess();
614061da546Spatrick } else if (level != eDescriptionLevelInitial) {
615be691f3bSpatrick s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"),
616be691f3bSpatrick (is_hardware ? "hardware, " : ""), GetHitCount());
617061da546Spatrick if (m_options_up) {
618061da546Spatrick m_options_up->GetDescription(s, level);
619061da546Spatrick }
620061da546Spatrick }
621061da546Spatrick }
622061da546Spatrick
Dump(Stream * s) const623061da546Spatrick void BreakpointLocation::Dump(Stream *s) const {
624061da546Spatrick if (s == nullptr)
625061da546Spatrick return;
626061da546Spatrick
627be691f3bSpatrick bool is_resolved = IsResolved();
628be691f3bSpatrick bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
629be691f3bSpatrick auto hardware_index = is_resolved ?
630be691f3bSpatrick m_bp_site_sp->GetHardwareIndex() : LLDB_INVALID_INDEX32;
631be691f3bSpatrick
632061da546Spatrick lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
633be691f3bSpatrick .GetThreadSpecNoCreate()
634be691f3bSpatrick ->GetTID();
635061da546Spatrick s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
636061da546Spatrick " load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint "
637061da546Spatrick "hw_index = %i hit_count = %-4u ignore_count = %-4u",
638061da546Spatrick GetID(), tid,
639061da546Spatrick (uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
640061da546Spatrick (m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
641061da546Spatrick ? "enabled "
642061da546Spatrick : "disabled",
643be691f3bSpatrick is_hardware ? "hardware" : "software", hardware_index,
644061da546Spatrick GetHitCount(),
645061da546Spatrick GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
646be691f3bSpatrick .GetIgnoreCount());
647061da546Spatrick }
648061da546Spatrick
SendBreakpointLocationChangedEvent(lldb::BreakpointEventType eventKind)649061da546Spatrick void BreakpointLocation::SendBreakpointLocationChangedEvent(
650061da546Spatrick lldb::BreakpointEventType eventKind) {
651061da546Spatrick if (!m_being_created && !m_owner.IsInternal() &&
652061da546Spatrick m_owner.GetTarget().EventTypeHasListeners(
653061da546Spatrick Target::eBroadcastBitBreakpointChanged)) {
654061da546Spatrick Breakpoint::BreakpointEventData *data = new Breakpoint::BreakpointEventData(
655061da546Spatrick eventKind, m_owner.shared_from_this());
656061da546Spatrick data->GetBreakpointLocationCollection().Add(shared_from_this());
657061da546Spatrick m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
658061da546Spatrick data);
659061da546Spatrick }
660061da546Spatrick }
661061da546Spatrick
SwapLocation(BreakpointLocationSP swap_from)662061da546Spatrick void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
663061da546Spatrick m_address = swap_from->m_address;
664061da546Spatrick m_should_resolve_indirect_functions =
665061da546Spatrick swap_from->m_should_resolve_indirect_functions;
666061da546Spatrick m_is_reexported = swap_from->m_is_reexported;
667061da546Spatrick m_is_indirect = swap_from->m_is_indirect;
668061da546Spatrick m_user_expression_sp.reset();
669061da546Spatrick }
670