Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Breakpoint/BreakpointLocation.cpp
39587 views
1
//===-- BreakpointLocation.cpp --------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "lldb/Breakpoint/BreakpointLocation.h"
10
#include "lldb/Breakpoint/BreakpointID.h"
11
#include "lldb/Breakpoint/StoppointCallbackContext.h"
12
#include "lldb/Core/Debugger.h"
13
#include "lldb/Core/Module.h"
14
#include "lldb/Core/ValueObject.h"
15
#include "lldb/Expression/DiagnosticManager.h"
16
#include "lldb/Expression/ExpressionVariable.h"
17
#include "lldb/Expression/UserExpression.h"
18
#include "lldb/Symbol/CompileUnit.h"
19
#include "lldb/Symbol/Symbol.h"
20
#include "lldb/Symbol/TypeSystem.h"
21
#include "lldb/Target/Process.h"
22
#include "lldb/Target/Target.h"
23
#include "lldb/Target/Thread.h"
24
#include "lldb/Target/ThreadSpec.h"
25
#include "lldb/Utility/LLDBLog.h"
26
#include "lldb/Utility/Log.h"
27
#include "lldb/Utility/StreamString.h"
28
29
using namespace lldb;
30
using namespace lldb_private;
31
32
BreakpointLocation::BreakpointLocation(break_id_t loc_id, Breakpoint &owner,
33
const Address &addr, lldb::tid_t tid,
34
bool hardware, bool check_for_resolver)
35
: m_should_resolve_indirect_functions(false), m_is_reexported(false),
36
m_is_indirect(false), m_address(addr), m_owner(owner),
37
m_condition_hash(0), m_loc_id(loc_id), m_hit_counter() {
38
if (check_for_resolver) {
39
Symbol *symbol = m_address.CalculateSymbolContextSymbol();
40
if (symbol && symbol->IsIndirect()) {
41
SetShouldResolveIndirectFunctions(true);
42
}
43
}
44
45
SetThreadIDInternal(tid);
46
}
47
48
BreakpointLocation::~BreakpointLocation() { ClearBreakpointSite(); }
49
50
lldb::addr_t BreakpointLocation::GetLoadAddress() const {
51
return m_address.GetOpcodeLoadAddress(&m_owner.GetTarget());
52
}
53
54
const BreakpointOptions &BreakpointLocation::GetOptionsSpecifyingKind(
55
BreakpointOptions::OptionKind kind) const {
56
if (m_options_up && m_options_up->IsOptionSet(kind))
57
return *m_options_up;
58
else
59
return m_owner.GetOptions();
60
}
61
62
Address &BreakpointLocation::GetAddress() { return m_address; }
63
64
Breakpoint &BreakpointLocation::GetBreakpoint() { return m_owner; }
65
66
Target &BreakpointLocation::GetTarget() { return m_owner.GetTarget(); }
67
68
bool BreakpointLocation::IsEnabled() const {
69
if (!m_owner.IsEnabled())
70
return false;
71
else if (m_options_up != nullptr)
72
return m_options_up->IsEnabled();
73
else
74
return true;
75
}
76
77
void BreakpointLocation::SetEnabled(bool enabled) {
78
GetLocationOptions().SetEnabled(enabled);
79
if (enabled) {
80
ResolveBreakpointSite();
81
} else {
82
ClearBreakpointSite();
83
}
84
SendBreakpointLocationChangedEvent(enabled ? eBreakpointEventTypeEnabled
85
: eBreakpointEventTypeDisabled);
86
}
87
88
bool BreakpointLocation::IsAutoContinue() const {
89
if (m_options_up &&
90
m_options_up->IsOptionSet(BreakpointOptions::eAutoContinue))
91
return m_options_up->IsAutoContinue();
92
else
93
return m_owner.IsAutoContinue();
94
}
95
96
void BreakpointLocation::SetAutoContinue(bool auto_continue) {
97
GetLocationOptions().SetAutoContinue(auto_continue);
98
SendBreakpointLocationChangedEvent(eBreakpointEventTypeAutoContinueChanged);
99
}
100
101
void BreakpointLocation::SetThreadID(lldb::tid_t thread_id) {
102
SetThreadIDInternal(thread_id);
103
SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
104
}
105
106
lldb::tid_t BreakpointLocation::GetThreadID() {
107
const ThreadSpec *thread_spec =
108
GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
109
.GetThreadSpecNoCreate();
110
if (thread_spec)
111
return thread_spec->GetTID();
112
else
113
return LLDB_INVALID_THREAD_ID;
114
}
115
116
void BreakpointLocation::SetThreadIndex(uint32_t index) {
117
if (index != 0)
118
GetLocationOptions().GetThreadSpec()->SetIndex(index);
119
else {
120
// If we're resetting this to an invalid thread id, then don't make an
121
// options pointer just to do that.
122
if (m_options_up != nullptr)
123
m_options_up->GetThreadSpec()->SetIndex(index);
124
}
125
SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
126
}
127
128
uint32_t BreakpointLocation::GetThreadIndex() const {
129
const ThreadSpec *thread_spec =
130
GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
131
.GetThreadSpecNoCreate();
132
if (thread_spec)
133
return thread_spec->GetIndex();
134
else
135
return 0;
136
}
137
138
void BreakpointLocation::SetThreadName(const char *thread_name) {
139
if (thread_name != nullptr)
140
GetLocationOptions().GetThreadSpec()->SetName(thread_name);
141
else {
142
// If we're resetting this to an invalid thread id, then don't make an
143
// options pointer just to do that.
144
if (m_options_up != nullptr)
145
m_options_up->GetThreadSpec()->SetName(thread_name);
146
}
147
SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
148
}
149
150
const char *BreakpointLocation::GetThreadName() const {
151
const ThreadSpec *thread_spec =
152
GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
153
.GetThreadSpecNoCreate();
154
if (thread_spec)
155
return thread_spec->GetName();
156
else
157
return nullptr;
158
}
159
160
void BreakpointLocation::SetQueueName(const char *queue_name) {
161
if (queue_name != nullptr)
162
GetLocationOptions().GetThreadSpec()->SetQueueName(queue_name);
163
else {
164
// If we're resetting this to an invalid thread id, then don't make an
165
// options pointer just to do that.
166
if (m_options_up != nullptr)
167
m_options_up->GetThreadSpec()->SetQueueName(queue_name);
168
}
169
SendBreakpointLocationChangedEvent(eBreakpointEventTypeThreadChanged);
170
}
171
172
const char *BreakpointLocation::GetQueueName() const {
173
const ThreadSpec *thread_spec =
174
GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
175
.GetThreadSpecNoCreate();
176
if (thread_spec)
177
return thread_spec->GetQueueName();
178
else
179
return nullptr;
180
}
181
182
bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
183
if (m_options_up != nullptr && m_options_up->HasCallback())
184
return m_options_up->InvokeCallback(context, m_owner.GetID(), GetID());
185
else
186
return m_owner.InvokeCallback(context, GetID());
187
}
188
189
bool BreakpointLocation::IsCallbackSynchronous() {
190
if (m_options_up != nullptr && m_options_up->HasCallback())
191
return m_options_up->IsCallbackSynchronous();
192
else
193
return m_owner.GetOptions().IsCallbackSynchronous();
194
}
195
196
void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
197
void *baton, bool is_synchronous) {
198
// The default "Baton" class will keep a copy of "baton" and won't free or
199
// delete it when it goes out of scope.
200
GetLocationOptions().SetCallback(
201
callback, std::make_shared<UntypedBaton>(baton), is_synchronous);
202
SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
203
}
204
205
void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
206
const BatonSP &baton_sp,
207
bool is_synchronous) {
208
GetLocationOptions().SetCallback(callback, baton_sp, is_synchronous);
209
SendBreakpointLocationChangedEvent(eBreakpointEventTypeCommandChanged);
210
}
211
212
void BreakpointLocation::ClearCallback() {
213
GetLocationOptions().ClearCallback();
214
}
215
216
void BreakpointLocation::SetCondition(const char *condition) {
217
GetLocationOptions().SetCondition(condition);
218
SendBreakpointLocationChangedEvent(eBreakpointEventTypeConditionChanged);
219
}
220
221
const char *BreakpointLocation::GetConditionText(size_t *hash) const {
222
return GetOptionsSpecifyingKind(BreakpointOptions::eCondition)
223
.GetConditionText(hash);
224
}
225
226
bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx,
227
Status &error) {
228
Log *log = GetLog(LLDBLog::Breakpoints);
229
230
std::lock_guard<std::mutex> guard(m_condition_mutex);
231
232
size_t condition_hash;
233
const char *condition_text = GetConditionText(&condition_hash);
234
235
if (!condition_text) {
236
m_user_expression_sp.reset();
237
return false;
238
}
239
240
error.Clear();
241
242
DiagnosticManager diagnostics;
243
244
if (condition_hash != m_condition_hash || !m_user_expression_sp ||
245
!m_user_expression_sp->IsParseCacheable() ||
246
!m_user_expression_sp->MatchesContext(exe_ctx)) {
247
LanguageType language = eLanguageTypeUnknown;
248
// See if we can figure out the language from the frame, otherwise use the
249
// default language:
250
CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
251
if (comp_unit)
252
language = comp_unit->GetLanguage();
253
254
m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(
255
condition_text, llvm::StringRef(), language, Expression::eResultTypeAny,
256
EvaluateExpressionOptions(), nullptr, error));
257
if (error.Fail()) {
258
LLDB_LOGF(log, "Error getting condition expression: %s.",
259
error.AsCString());
260
m_user_expression_sp.reset();
261
return true;
262
}
263
264
if (!m_user_expression_sp->Parse(diagnostics, exe_ctx,
265
eExecutionPolicyOnlyWhenNeeded, true,
266
false)) {
267
error.SetErrorStringWithFormat(
268
"Couldn't parse conditional expression:\n%s",
269
diagnostics.GetString().c_str());
270
m_user_expression_sp.reset();
271
return true;
272
}
273
274
m_condition_hash = condition_hash;
275
}
276
277
// We need to make sure the user sees any parse errors in their condition, so
278
// we'll hook the constructor errors up to the debugger's Async I/O.
279
280
ValueObjectSP result_value_sp;
281
282
EvaluateExpressionOptions options;
283
options.SetUnwindOnError(true);
284
options.SetIgnoreBreakpoints(true);
285
options.SetTryAllThreads(true);
286
options.SetSuppressPersistentResult(
287
true); // Don't generate a user variable for condition expressions.
288
289
Status expr_error;
290
291
diagnostics.Clear();
292
293
ExpressionVariableSP result_variable_sp;
294
295
ExpressionResults result_code = m_user_expression_sp->Execute(
296
diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp);
297
298
bool ret;
299
300
if (result_code == eExpressionCompleted) {
301
if (!result_variable_sp) {
302
error.SetErrorString("Expression did not return a result");
303
return false;
304
}
305
306
result_value_sp = result_variable_sp->GetValueObject();
307
308
if (result_value_sp) {
309
ret = result_value_sp->IsLogicalTrue(error);
310
if (log) {
311
if (error.Success()) {
312
LLDB_LOGF(log, "Condition successfully evaluated, result is %s.\n",
313
ret ? "true" : "false");
314
} else {
315
error.SetErrorString(
316
"Failed to get an integer result from the expression");
317
ret = false;
318
}
319
}
320
} else {
321
ret = false;
322
error.SetErrorString("Failed to get any result from the expression");
323
}
324
} else {
325
ret = false;
326
error.SetErrorStringWithFormat("Couldn't execute expression:\n%s",
327
diagnostics.GetString().c_str());
328
}
329
330
return ret;
331
}
332
333
uint32_t BreakpointLocation::GetIgnoreCount() const {
334
return GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
335
.GetIgnoreCount();
336
}
337
338
void BreakpointLocation::SetIgnoreCount(uint32_t n) {
339
GetLocationOptions().SetIgnoreCount(n);
340
SendBreakpointLocationChangedEvent(eBreakpointEventTypeIgnoreChanged);
341
}
342
343
void BreakpointLocation::DecrementIgnoreCount() {
344
if (m_options_up != nullptr) {
345
uint32_t loc_ignore = m_options_up->GetIgnoreCount();
346
if (loc_ignore != 0)
347
m_options_up->SetIgnoreCount(loc_ignore - 1);
348
}
349
}
350
351
bool BreakpointLocation::IgnoreCountShouldStop() {
352
uint32_t owner_ignore = GetBreakpoint().GetIgnoreCount();
353
uint32_t loc_ignore = 0;
354
if (m_options_up != nullptr)
355
loc_ignore = m_options_up->GetIgnoreCount();
356
357
if (loc_ignore != 0 || owner_ignore != 0) {
358
m_owner.DecrementIgnoreCount();
359
DecrementIgnoreCount(); // Have to decrement our owners' ignore count,
360
// since it won't get a chance to.
361
return false;
362
}
363
return true;
364
}
365
366
BreakpointOptions &BreakpointLocation::GetLocationOptions() {
367
// If we make the copy we don't copy the callbacks because that is
368
// potentially expensive and we don't want to do that for the simple case
369
// where someone is just disabling the location.
370
if (m_options_up == nullptr)
371
m_options_up = std::make_unique<BreakpointOptions>(false);
372
373
return *m_options_up;
374
}
375
376
bool BreakpointLocation::ValidForThisThread(Thread &thread) {
377
return thread.MatchesSpec(
378
GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
379
.GetThreadSpecNoCreate());
380
}
381
382
// RETURNS - true if we should stop at this breakpoint, false if we
383
// should continue. Note, we don't check the thread spec for the breakpoint
384
// here, since if the breakpoint is not for this thread, then the event won't
385
// even get reported, so the check is redundant.
386
387
bool BreakpointLocation::ShouldStop(StoppointCallbackContext *context) {
388
bool should_stop = true;
389
Log *log = GetLog(LLDBLog::Breakpoints);
390
391
// Do this first, if a location is disabled, it shouldn't increment its hit
392
// count.
393
if (!IsEnabled())
394
return false;
395
396
// We only run synchronous callbacks in ShouldStop:
397
context->is_synchronous = true;
398
should_stop = InvokeCallback(context);
399
400
if (log) {
401
StreamString s;
402
GetDescription(&s, lldb::eDescriptionLevelVerbose);
403
LLDB_LOGF(log, "Hit breakpoint location: %s, %s.\n", s.GetData(),
404
should_stop ? "stopping" : "continuing");
405
}
406
407
return should_stop;
408
}
409
410
void BreakpointLocation::BumpHitCount() {
411
if (IsEnabled()) {
412
// Step our hit count, and also step the hit count of the owner.
413
m_hit_counter.Increment();
414
m_owner.m_hit_counter.Increment();
415
}
416
}
417
418
void BreakpointLocation::UndoBumpHitCount() {
419
if (IsEnabled()) {
420
// Step our hit count, and also step the hit count of the owner.
421
m_hit_counter.Decrement();
422
m_owner.m_hit_counter.Decrement();
423
}
424
}
425
426
bool BreakpointLocation::IsResolved() const {
427
return m_bp_site_sp.get() != nullptr;
428
}
429
430
lldb::BreakpointSiteSP BreakpointLocation::GetBreakpointSite() const {
431
return m_bp_site_sp;
432
}
433
434
bool BreakpointLocation::ResolveBreakpointSite() {
435
if (m_bp_site_sp)
436
return true;
437
438
Process *process = m_owner.GetTarget().GetProcessSP().get();
439
if (process == nullptr)
440
return false;
441
442
lldb::break_id_t new_id =
443
process->CreateBreakpointSite(shared_from_this(), m_owner.IsHardware());
444
445
if (new_id == LLDB_INVALID_BREAK_ID) {
446
Log *log = GetLog(LLDBLog::Breakpoints);
447
if (log)
448
log->Warning("Failed to add breakpoint site at 0x%" PRIx64,
449
m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()));
450
}
451
452
return IsResolved();
453
}
454
455
bool BreakpointLocation::SetBreakpointSite(BreakpointSiteSP &bp_site_sp) {
456
m_bp_site_sp = bp_site_sp;
457
SendBreakpointLocationChangedEvent(eBreakpointEventTypeLocationsResolved);
458
return true;
459
}
460
461
bool BreakpointLocation::ClearBreakpointSite() {
462
if (m_bp_site_sp.get()) {
463
ProcessSP process_sp(m_owner.GetTarget().GetProcessSP());
464
// If the process exists, get it to remove the owner, it will remove the
465
// physical implementation of the breakpoint as well if there are no more
466
// owners. Otherwise just remove this owner.
467
if (process_sp)
468
process_sp->RemoveConstituentFromBreakpointSite(GetBreakpoint().GetID(),
469
GetID(), m_bp_site_sp);
470
else
471
m_bp_site_sp->RemoveConstituent(GetBreakpoint().GetID(), GetID());
472
473
m_bp_site_sp.reset();
474
return true;
475
}
476
return false;
477
}
478
479
void BreakpointLocation::GetDescription(Stream *s,
480
lldb::DescriptionLevel level) {
481
SymbolContext sc;
482
483
// If the description level is "initial" then the breakpoint is printing out
484
// our initial state, and we should let it decide how it wants to print our
485
// label.
486
if (level != eDescriptionLevelInitial) {
487
s->Indent();
488
BreakpointID::GetCanonicalReference(s, m_owner.GetID(), GetID());
489
}
490
491
if (level == lldb::eDescriptionLevelBrief)
492
return;
493
494
if (level != eDescriptionLevelInitial)
495
s->PutCString(": ");
496
497
if (level == lldb::eDescriptionLevelVerbose)
498
s->IndentMore();
499
500
if (m_address.IsSectionOffset()) {
501
m_address.CalculateSymbolContext(&sc);
502
503
if (level == lldb::eDescriptionLevelFull ||
504
level == eDescriptionLevelInitial) {
505
if (IsReExported())
506
s->PutCString("re-exported target = ");
507
else
508
s->PutCString("where = ");
509
sc.DumpStopContext(s, m_owner.GetTarget().GetProcessSP().get(), m_address,
510
false, true, false, true, true, true);
511
} else {
512
if (sc.module_sp) {
513
s->EOL();
514
s->Indent("module = ");
515
sc.module_sp->GetFileSpec().Dump(s->AsRawOstream());
516
}
517
518
if (sc.comp_unit != nullptr) {
519
s->EOL();
520
s->Indent("compile unit = ");
521
sc.comp_unit->GetPrimaryFile().GetFilename().Dump(s);
522
523
if (sc.function != nullptr) {
524
s->EOL();
525
s->Indent("function = ");
526
s->PutCString(sc.function->GetName().AsCString("<unknown>"));
527
if (ConstString mangled_name =
528
sc.function->GetMangled().GetMangledName()) {
529
s->EOL();
530
s->Indent("mangled function = ");
531
s->PutCString(mangled_name.AsCString());
532
}
533
}
534
535
if (sc.line_entry.line > 0) {
536
s->EOL();
537
s->Indent("location = ");
538
sc.line_entry.DumpStopContext(s, true);
539
}
540
541
} else {
542
// If we don't have a comp unit, see if we have a symbol we can print.
543
if (sc.symbol) {
544
s->EOL();
545
if (IsReExported())
546
s->Indent("re-exported target = ");
547
else
548
s->Indent("symbol = ");
549
s->PutCString(sc.symbol->GetName().AsCString("<unknown>"));
550
}
551
}
552
}
553
}
554
555
if (level == lldb::eDescriptionLevelVerbose) {
556
s->EOL();
557
s->Indent();
558
}
559
560
if (m_address.IsSectionOffset() &&
561
(level == eDescriptionLevelFull || level == eDescriptionLevelInitial))
562
s->Printf(", ");
563
s->Printf("address = ");
564
565
ExecutionContextScope *exe_scope = nullptr;
566
Target *target = &m_owner.GetTarget();
567
if (target)
568
exe_scope = target->GetProcessSP().get();
569
if (exe_scope == nullptr)
570
exe_scope = target;
571
572
if (level == eDescriptionLevelInitial)
573
m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
574
Address::DumpStyleFileAddress);
575
else
576
m_address.Dump(s, exe_scope, Address::DumpStyleLoadAddress,
577
Address::DumpStyleModuleWithFileAddress);
578
579
if (IsIndirect() && m_bp_site_sp) {
580
Address resolved_address;
581
resolved_address.SetLoadAddress(m_bp_site_sp->GetLoadAddress(), target);
582
Symbol *resolved_symbol = resolved_address.CalculateSymbolContextSymbol();
583
if (resolved_symbol) {
584
if (level == eDescriptionLevelFull || level == eDescriptionLevelInitial)
585
s->Printf(", ");
586
else if (level == lldb::eDescriptionLevelVerbose) {
587
s->EOL();
588
s->Indent();
589
}
590
s->Printf("indirect target = %s",
591
resolved_symbol->GetName().GetCString());
592
}
593
}
594
595
bool is_resolved = IsResolved();
596
bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
597
598
if (level == lldb::eDescriptionLevelVerbose) {
599
s->EOL();
600
s->Indent();
601
s->Printf("resolved = %s\n", is_resolved ? "true" : "false");
602
s->Indent();
603
s->Printf("hardware = %s\n", is_hardware ? "true" : "false");
604
s->Indent();
605
s->Printf("hit count = %-4u\n", GetHitCount());
606
607
if (m_options_up) {
608
s->Indent();
609
m_options_up->GetDescription(s, level);
610
s->EOL();
611
}
612
s->IndentLess();
613
} else if (level != eDescriptionLevelInitial) {
614
s->Printf(", %sresolved, %shit count = %u ", (is_resolved ? "" : "un"),
615
(is_hardware ? "hardware, " : ""), GetHitCount());
616
if (m_options_up) {
617
m_options_up->GetDescription(s, level);
618
}
619
}
620
}
621
622
void BreakpointLocation::Dump(Stream *s) const {
623
if (s == nullptr)
624
return;
625
626
bool is_resolved = IsResolved();
627
bool is_hardware = is_resolved && m_bp_site_sp->IsHardware();
628
629
lldb::tid_t tid = GetOptionsSpecifyingKind(BreakpointOptions::eThreadSpec)
630
.GetThreadSpecNoCreate()
631
->GetTID();
632
s->Printf("BreakpointLocation %u: tid = %4.4" PRIx64
633
" load addr = 0x%8.8" PRIx64 " state = %s type = %s breakpoint "
634
"hit_count = %-4u ignore_count = %-4u",
635
GetID(), tid,
636
(uint64_t)m_address.GetOpcodeLoadAddress(&m_owner.GetTarget()),
637
(m_options_up ? m_options_up->IsEnabled() : m_owner.IsEnabled())
638
? "enabled "
639
: "disabled",
640
is_hardware ? "hardware" : "software", GetHitCount(),
641
GetOptionsSpecifyingKind(BreakpointOptions::eIgnoreCount)
642
.GetIgnoreCount());
643
}
644
645
void BreakpointLocation::SendBreakpointLocationChangedEvent(
646
lldb::BreakpointEventType eventKind) {
647
if (!m_owner.IsInternal() && m_owner.GetTarget().EventTypeHasListeners(
648
Target::eBroadcastBitBreakpointChanged)) {
649
auto data_sp = std::make_shared<Breakpoint::BreakpointEventData>(
650
eventKind, m_owner.shared_from_this());
651
data_sp->GetBreakpointLocationCollection().Add(shared_from_this());
652
m_owner.GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
653
data_sp);
654
}
655
}
656
657
void BreakpointLocation::SwapLocation(BreakpointLocationSP swap_from) {
658
m_address = swap_from->m_address;
659
m_should_resolve_indirect_functions =
660
swap_from->m_should_resolve_indirect_functions;
661
m_is_reexported = swap_from->m_is_reexported;
662
m_is_indirect = swap_from->m_is_indirect;
663
m_user_expression_sp.reset();
664
}
665
666
void BreakpointLocation::SetThreadIDInternal(lldb::tid_t thread_id) {
667
if (thread_id != LLDB_INVALID_THREAD_ID)
668
GetLocationOptions().SetThreadID(thread_id);
669
else {
670
// If we're resetting this to an invalid thread id, then don't make an
671
// options pointer just to do that.
672
if (m_options_up != nullptr)
673
m_options_up->SetThreadID(thread_id);
674
}
675
}
676
677