Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Breakpoint/Breakpoint.cpp
39587 views
1
//===-- Breakpoint.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 "llvm/Support/Casting.h"
10
11
#include "lldb/Breakpoint/Breakpoint.h"
12
#include "lldb/Breakpoint/BreakpointLocation.h"
13
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
14
#include "lldb/Breakpoint/BreakpointPrecondition.h"
15
#include "lldb/Breakpoint/BreakpointResolver.h"
16
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
17
#include "lldb/Core/Address.h"
18
#include "lldb/Core/Module.h"
19
#include "lldb/Core/ModuleList.h"
20
#include "lldb/Core/SearchFilter.h"
21
#include "lldb/Core/Section.h"
22
#include "lldb/Symbol/CompileUnit.h"
23
#include "lldb/Symbol/Function.h"
24
#include "lldb/Symbol/Symbol.h"
25
#include "lldb/Symbol/SymbolContext.h"
26
#include "lldb/Target/SectionLoadList.h"
27
#include "lldb/Target/Target.h"
28
#include "lldb/Target/ThreadSpec.h"
29
#include "lldb/Utility/LLDBLog.h"
30
#include "lldb/Utility/Log.h"
31
#include "lldb/Utility/Stream.h"
32
#include "lldb/Utility/StreamString.h"
33
34
#include <memory>
35
36
using namespace lldb;
37
using namespace lldb_private;
38
using namespace llvm;
39
40
const char *Breakpoint::g_option_names[static_cast<uint32_t>(
41
Breakpoint::OptionNames::LastOptionName)]{"Names", "Hardware"};
42
43
// Breakpoint constructor
44
Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp,
45
BreakpointResolverSP &resolver_sp, bool hardware,
46
bool resolve_indirect_symbols)
47
: m_hardware(hardware), m_target(target), m_filter_sp(filter_sp),
48
m_resolver_sp(resolver_sp), m_options(true), m_locations(*this),
49
m_resolve_indirect_symbols(resolve_indirect_symbols), m_hit_counter() {}
50
51
Breakpoint::Breakpoint(Target &new_target, const Breakpoint &source_bp)
52
: m_hardware(source_bp.m_hardware), m_target(new_target),
53
m_name_list(source_bp.m_name_list), m_options(source_bp.m_options),
54
m_locations(*this),
55
m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols),
56
m_hit_counter() {}
57
58
// Destructor
59
Breakpoint::~Breakpoint() = default;
60
61
BreakpointSP Breakpoint::CopyFromBreakpoint(TargetSP new_target,
62
const Breakpoint& bp_to_copy_from) {
63
if (!new_target)
64
return BreakpointSP();
65
66
BreakpointSP bp(new Breakpoint(*new_target, bp_to_copy_from));
67
// Now go through and copy the filter & resolver:
68
bp->m_resolver_sp = bp_to_copy_from.m_resolver_sp->CopyForBreakpoint(bp);
69
bp->m_filter_sp = bp_to_copy_from.m_filter_sp->CreateCopy(new_target);
70
return bp;
71
}
72
73
// Serialization
74
StructuredData::ObjectSP Breakpoint::SerializeToStructuredData() {
75
// Serialize the resolver:
76
StructuredData::DictionarySP breakpoint_dict_sp(
77
new StructuredData::Dictionary());
78
StructuredData::DictionarySP breakpoint_contents_sp(
79
new StructuredData::Dictionary());
80
81
if (!m_name_list.empty()) {
82
StructuredData::ArraySP names_array_sp(new StructuredData::Array());
83
for (auto name : m_name_list) {
84
names_array_sp->AddItem(
85
StructuredData::StringSP(new StructuredData::String(name)));
86
}
87
breakpoint_contents_sp->AddItem(Breakpoint::GetKey(OptionNames::Names),
88
names_array_sp);
89
}
90
91
breakpoint_contents_sp->AddBooleanItem(
92
Breakpoint::GetKey(OptionNames::Hardware), m_hardware);
93
94
StructuredData::ObjectSP resolver_dict_sp(
95
m_resolver_sp->SerializeToStructuredData());
96
if (!resolver_dict_sp)
97
return StructuredData::ObjectSP();
98
99
breakpoint_contents_sp->AddItem(BreakpointResolver::GetSerializationKey(),
100
resolver_dict_sp);
101
102
StructuredData::ObjectSP filter_dict_sp(
103
m_filter_sp->SerializeToStructuredData());
104
if (!filter_dict_sp)
105
return StructuredData::ObjectSP();
106
107
breakpoint_contents_sp->AddItem(SearchFilter::GetSerializationKey(),
108
filter_dict_sp);
109
110
StructuredData::ObjectSP options_dict_sp(
111
m_options.SerializeToStructuredData());
112
if (!options_dict_sp)
113
return StructuredData::ObjectSP();
114
115
breakpoint_contents_sp->AddItem(BreakpointOptions::GetSerializationKey(),
116
options_dict_sp);
117
118
breakpoint_dict_sp->AddItem(GetSerializationKey(), breakpoint_contents_sp);
119
return breakpoint_dict_sp;
120
}
121
122
lldb::BreakpointSP Breakpoint::CreateFromStructuredData(
123
TargetSP target_sp, StructuredData::ObjectSP &object_data, Status &error) {
124
BreakpointSP result_sp;
125
if (!target_sp)
126
return result_sp;
127
128
StructuredData::Dictionary *breakpoint_dict = object_data->GetAsDictionary();
129
130
if (!breakpoint_dict || !breakpoint_dict->IsValid()) {
131
error.SetErrorString("Can't deserialize from an invalid data object.");
132
return result_sp;
133
}
134
135
StructuredData::Dictionary *resolver_dict;
136
bool success = breakpoint_dict->GetValueForKeyAsDictionary(
137
BreakpointResolver::GetSerializationKey(), resolver_dict);
138
if (!success) {
139
error.SetErrorString("Breakpoint data missing toplevel resolver key");
140
return result_sp;
141
}
142
143
Status create_error;
144
BreakpointResolverSP resolver_sp =
145
BreakpointResolver::CreateFromStructuredData(*resolver_dict,
146
create_error);
147
if (create_error.Fail()) {
148
error.SetErrorStringWithFormat(
149
"Error creating breakpoint resolver from data: %s.",
150
create_error.AsCString());
151
return result_sp;
152
}
153
154
StructuredData::Dictionary *filter_dict;
155
success = breakpoint_dict->GetValueForKeyAsDictionary(
156
SearchFilter::GetSerializationKey(), filter_dict);
157
SearchFilterSP filter_sp;
158
if (!success)
159
filter_sp =
160
std::make_shared<SearchFilterForUnconstrainedSearches>(target_sp);
161
else {
162
filter_sp = SearchFilter::CreateFromStructuredData(target_sp, *filter_dict,
163
create_error);
164
if (create_error.Fail()) {
165
error.SetErrorStringWithFormat(
166
"Error creating breakpoint filter from data: %s.",
167
create_error.AsCString());
168
return result_sp;
169
}
170
}
171
172
std::unique_ptr<BreakpointOptions> options_up;
173
StructuredData::Dictionary *options_dict;
174
Target& target = *target_sp;
175
success = breakpoint_dict->GetValueForKeyAsDictionary(
176
BreakpointOptions::GetSerializationKey(), options_dict);
177
if (success) {
178
options_up = BreakpointOptions::CreateFromStructuredData(
179
target, *options_dict, create_error);
180
if (create_error.Fail()) {
181
error.SetErrorStringWithFormat(
182
"Error creating breakpoint options from data: %s.",
183
create_error.AsCString());
184
return result_sp;
185
}
186
}
187
188
bool hardware = false;
189
success = breakpoint_dict->GetValueForKeyAsBoolean(
190
Breakpoint::GetKey(OptionNames::Hardware), hardware);
191
192
result_sp = target.CreateBreakpoint(filter_sp, resolver_sp, false,
193
hardware, true);
194
195
if (result_sp && options_up) {
196
result_sp->m_options = *options_up;
197
}
198
199
StructuredData::Array *names_array;
200
success = breakpoint_dict->GetValueForKeyAsArray(
201
Breakpoint::GetKey(OptionNames::Names), names_array);
202
if (success && names_array) {
203
size_t num_names = names_array->GetSize();
204
for (size_t i = 0; i < num_names; i++) {
205
if (std::optional<llvm::StringRef> maybe_name =
206
names_array->GetItemAtIndexAsString(i))
207
target.AddNameToBreakpoint(result_sp, *maybe_name, error);
208
}
209
}
210
211
return result_sp;
212
}
213
214
bool Breakpoint::SerializedBreakpointMatchesNames(
215
StructuredData::ObjectSP &bkpt_object_sp, std::vector<std::string> &names) {
216
if (!bkpt_object_sp)
217
return false;
218
219
StructuredData::Dictionary *bkpt_dict = bkpt_object_sp->GetAsDictionary();
220
if (!bkpt_dict)
221
return false;
222
223
if (names.empty())
224
return true;
225
226
StructuredData::Array *names_array;
227
228
bool success =
229
bkpt_dict->GetValueForKeyAsArray(GetKey(OptionNames::Names), names_array);
230
// If there are no names, it can't match these names;
231
if (!success)
232
return false;
233
234
size_t num_names = names_array->GetSize();
235
236
for (size_t i = 0; i < num_names; i++) {
237
std::optional<llvm::StringRef> maybe_name =
238
names_array->GetItemAtIndexAsString(i);
239
if (maybe_name && llvm::is_contained(names, *maybe_name))
240
return true;
241
}
242
return false;
243
}
244
245
const lldb::TargetSP Breakpoint::GetTargetSP() {
246
return m_target.shared_from_this();
247
}
248
249
bool Breakpoint::IsInternal() const { return LLDB_BREAK_ID_IS_INTERNAL(m_bid); }
250
251
BreakpointLocationSP Breakpoint::AddLocation(const Address &addr,
252
bool *new_location) {
253
return m_locations.AddLocation(addr, m_resolve_indirect_symbols,
254
new_location);
255
}
256
257
BreakpointLocationSP Breakpoint::FindLocationByAddress(const Address &addr) {
258
return m_locations.FindByAddress(addr);
259
}
260
261
break_id_t Breakpoint::FindLocationIDByAddress(const Address &addr) {
262
return m_locations.FindIDByAddress(addr);
263
}
264
265
BreakpointLocationSP Breakpoint::FindLocationByID(break_id_t bp_loc_id) {
266
return m_locations.FindByID(bp_loc_id);
267
}
268
269
BreakpointLocationSP Breakpoint::GetLocationAtIndex(size_t index) {
270
return m_locations.GetByIndex(index);
271
}
272
273
void Breakpoint::RemoveInvalidLocations(const ArchSpec &arch) {
274
m_locations.RemoveInvalidLocations(arch);
275
}
276
277
// For each of the overall options we need to decide how they propagate to the
278
// location options. This will determine the precedence of options on the
279
// breakpoint vs. its locations.
280
281
// Disable at the breakpoint level should override the location settings. That
282
// way you can conveniently turn off a whole breakpoint without messing up the
283
// individual settings.
284
285
void Breakpoint::SetEnabled(bool enable) {
286
if (enable == m_options.IsEnabled())
287
return;
288
289
m_options.SetEnabled(enable);
290
if (enable)
291
m_locations.ResolveAllBreakpointSites();
292
else
293
m_locations.ClearAllBreakpointSites();
294
295
SendBreakpointChangedEvent(enable ? eBreakpointEventTypeEnabled
296
: eBreakpointEventTypeDisabled);
297
}
298
299
bool Breakpoint::IsEnabled() { return m_options.IsEnabled(); }
300
301
void Breakpoint::SetIgnoreCount(uint32_t n) {
302
if (m_options.GetIgnoreCount() == n)
303
return;
304
305
m_options.SetIgnoreCount(n);
306
SendBreakpointChangedEvent(eBreakpointEventTypeIgnoreChanged);
307
}
308
309
void Breakpoint::DecrementIgnoreCount() {
310
uint32_t ignore = m_options.GetIgnoreCount();
311
if (ignore != 0)
312
m_options.SetIgnoreCount(ignore - 1);
313
}
314
315
uint32_t Breakpoint::GetIgnoreCount() const {
316
return m_options.GetIgnoreCount();
317
}
318
319
uint32_t Breakpoint::GetHitCount() const { return m_hit_counter.GetValue(); }
320
321
void Breakpoint::ResetHitCount() {
322
m_hit_counter.Reset();
323
m_locations.ResetHitCount();
324
}
325
326
bool Breakpoint::IsOneShot() const { return m_options.IsOneShot(); }
327
328
void Breakpoint::SetOneShot(bool one_shot) { m_options.SetOneShot(one_shot); }
329
330
bool Breakpoint::IsAutoContinue() const { return m_options.IsAutoContinue(); }
331
332
void Breakpoint::SetAutoContinue(bool auto_continue) {
333
m_options.SetAutoContinue(auto_continue);
334
}
335
336
void Breakpoint::SetThreadID(lldb::tid_t thread_id) {
337
if (m_options.GetThreadSpec()->GetTID() == thread_id)
338
return;
339
340
m_options.GetThreadSpec()->SetTID(thread_id);
341
SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
342
}
343
344
lldb::tid_t Breakpoint::GetThreadID() const {
345
if (m_options.GetThreadSpecNoCreate() == nullptr)
346
return LLDB_INVALID_THREAD_ID;
347
else
348
return m_options.GetThreadSpecNoCreate()->GetTID();
349
}
350
351
void Breakpoint::SetThreadIndex(uint32_t index) {
352
if (m_options.GetThreadSpec()->GetIndex() == index)
353
return;
354
355
m_options.GetThreadSpec()->SetIndex(index);
356
SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
357
}
358
359
uint32_t Breakpoint::GetThreadIndex() const {
360
if (m_options.GetThreadSpecNoCreate() == nullptr)
361
return 0;
362
else
363
return m_options.GetThreadSpecNoCreate()->GetIndex();
364
}
365
366
void Breakpoint::SetThreadName(const char *thread_name) {
367
if (m_options.GetThreadSpec()->GetName() != nullptr &&
368
::strcmp(m_options.GetThreadSpec()->GetName(), thread_name) == 0)
369
return;
370
371
m_options.GetThreadSpec()->SetName(thread_name);
372
SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
373
}
374
375
const char *Breakpoint::GetThreadName() const {
376
if (m_options.GetThreadSpecNoCreate() == nullptr)
377
return nullptr;
378
else
379
return m_options.GetThreadSpecNoCreate()->GetName();
380
}
381
382
void Breakpoint::SetQueueName(const char *queue_name) {
383
if (m_options.GetThreadSpec()->GetQueueName() != nullptr &&
384
::strcmp(m_options.GetThreadSpec()->GetQueueName(), queue_name) == 0)
385
return;
386
387
m_options.GetThreadSpec()->SetQueueName(queue_name);
388
SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);
389
}
390
391
const char *Breakpoint::GetQueueName() const {
392
if (m_options.GetThreadSpecNoCreate() == nullptr)
393
return nullptr;
394
else
395
return m_options.GetThreadSpecNoCreate()->GetQueueName();
396
}
397
398
void Breakpoint::SetCondition(const char *condition) {
399
m_options.SetCondition(condition);
400
SendBreakpointChangedEvent(eBreakpointEventTypeConditionChanged);
401
}
402
403
const char *Breakpoint::GetConditionText() const {
404
return m_options.GetConditionText();
405
}
406
407
// This function is used when "baton" doesn't need to be freed
408
void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton,
409
bool is_synchronous) {
410
// The default "Baton" class will keep a copy of "baton" and won't free or
411
// delete it when it goes out of scope.
412
m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton),
413
is_synchronous);
414
415
SendBreakpointChangedEvent(eBreakpointEventTypeCommandChanged);
416
}
417
418
// This function is used when a baton needs to be freed and therefore is
419
// contained in a "Baton" subclass.
420
void Breakpoint::SetCallback(BreakpointHitCallback callback,
421
const BatonSP &callback_baton_sp,
422
bool is_synchronous) {
423
m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
424
}
425
426
void Breakpoint::ClearCallback() { m_options.ClearCallback(); }
427
428
bool Breakpoint::InvokeCallback(StoppointCallbackContext *context,
429
break_id_t bp_loc_id) {
430
return m_options.InvokeCallback(context, GetID(), bp_loc_id);
431
}
432
433
BreakpointOptions &Breakpoint::GetOptions() { return m_options; }
434
435
const BreakpointOptions &Breakpoint::GetOptions() const { return m_options; }
436
437
void Breakpoint::ResolveBreakpoint() {
438
if (m_resolver_sp) {
439
ElapsedTime elapsed(m_resolve_time);
440
m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
441
}
442
}
443
444
void Breakpoint::ResolveBreakpointInModules(
445
ModuleList &module_list, BreakpointLocationCollection &new_locations) {
446
ElapsedTime elapsed(m_resolve_time);
447
m_locations.StartRecordingNewLocations(new_locations);
448
449
m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
450
451
m_locations.StopRecordingNewLocations();
452
}
453
454
void Breakpoint::ResolveBreakpointInModules(ModuleList &module_list,
455
bool send_event) {
456
if (m_resolver_sp) {
457
// If this is not an internal breakpoint, set up to record the new
458
// locations, then dispatch an event with the new locations.
459
if (!IsInternal() && send_event) {
460
std::shared_ptr<BreakpointEventData> new_locations_event =
461
std::make_shared<BreakpointEventData>(
462
eBreakpointEventTypeLocationsAdded, shared_from_this());
463
ResolveBreakpointInModules(
464
module_list, new_locations_event->GetBreakpointLocationCollection());
465
if (new_locations_event->GetBreakpointLocationCollection().GetSize() != 0)
466
SendBreakpointChangedEvent(new_locations_event);
467
} else {
468
ElapsedTime elapsed(m_resolve_time);
469
m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
470
}
471
}
472
}
473
474
void Breakpoint::ClearAllBreakpointSites() {
475
m_locations.ClearAllBreakpointSites();
476
}
477
478
// ModulesChanged: Pass in a list of new modules, and
479
480
void Breakpoint::ModulesChanged(ModuleList &module_list, bool load,
481
bool delete_locations) {
482
Log *log = GetLog(LLDBLog::Breakpoints);
483
LLDB_LOGF(log,
484
"Breakpoint::ModulesChanged: num_modules: %zu load: %i "
485
"delete_locations: %i\n",
486
module_list.GetSize(), load, delete_locations);
487
488
if (load) {
489
// The logic for handling new modules is:
490
// 1) If the filter rejects this module, then skip it. 2) Run through the
491
// current location list and if there are any locations
492
// for that module, we mark the module as "seen" and we don't try to
493
// re-resolve
494
// breakpoint locations for that module.
495
// However, we do add breakpoint sites to these locations if needed.
496
// 3) If we don't see this module in our breakpoint location list, call
497
// ResolveInModules.
498
499
ModuleList new_modules; // We'll stuff the "unseen" modules in this list,
500
// and then resolve
501
// them after the locations pass. Have to do it this way because resolving
502
// breakpoints will add new locations potentially.
503
504
for (ModuleSP module_sp : module_list.Modules()) {
505
bool seen = false;
506
if (!m_filter_sp->ModulePasses(module_sp))
507
continue;
508
509
BreakpointLocationCollection locations_with_no_section;
510
for (BreakpointLocationSP break_loc_sp :
511
m_locations.BreakpointLocations()) {
512
513
// If the section for this location was deleted, that means it's Module
514
// has gone away but somebody forgot to tell us. Let's clean it up
515
// here.
516
Address section_addr(break_loc_sp->GetAddress());
517
if (section_addr.SectionWasDeleted()) {
518
locations_with_no_section.Add(break_loc_sp);
519
continue;
520
}
521
522
if (!break_loc_sp->IsEnabled())
523
continue;
524
525
SectionSP section_sp(section_addr.GetSection());
526
527
// If we don't have a Section, that means this location is a raw
528
// address that we haven't resolved to a section yet. So we'll have to
529
// look in all the new modules to resolve this location. Otherwise, if
530
// it was set in this module, re-resolve it here.
531
if (section_sp && section_sp->GetModule() == module_sp) {
532
if (!seen)
533
seen = true;
534
535
if (!break_loc_sp->ResolveBreakpointSite()) {
536
LLDB_LOGF(log,
537
"Warning: could not set breakpoint site for "
538
"breakpoint location %d of breakpoint %d.\n",
539
break_loc_sp->GetID(), GetID());
540
}
541
}
542
}
543
544
size_t num_to_delete = locations_with_no_section.GetSize();
545
546
for (size_t i = 0; i < num_to_delete; i++)
547
m_locations.RemoveLocation(locations_with_no_section.GetByIndex(i));
548
549
if (!seen)
550
new_modules.AppendIfNeeded(module_sp);
551
}
552
553
if (new_modules.GetSize() > 0) {
554
ResolveBreakpointInModules(new_modules);
555
}
556
} else {
557
// Go through the currently set locations and if any have breakpoints in
558
// the module list, then remove their breakpoint sites, and their locations
559
// if asked to.
560
561
std::shared_ptr<BreakpointEventData> removed_locations_event;
562
if (!IsInternal())
563
removed_locations_event = std::make_shared<BreakpointEventData>(
564
eBreakpointEventTypeLocationsRemoved, shared_from_this());
565
566
for (ModuleSP module_sp : module_list.Modules()) {
567
if (m_filter_sp->ModulePasses(module_sp)) {
568
size_t loc_idx = 0;
569
size_t num_locations = m_locations.GetSize();
570
BreakpointLocationCollection locations_to_remove;
571
for (loc_idx = 0; loc_idx < num_locations; loc_idx++) {
572
BreakpointLocationSP break_loc_sp(m_locations.GetByIndex(loc_idx));
573
SectionSP section_sp(break_loc_sp->GetAddress().GetSection());
574
if (section_sp && section_sp->GetModule() == module_sp) {
575
// Remove this breakpoint since the shared library is unloaded, but
576
// keep the breakpoint location around so we always get complete
577
// hit count and breakpoint lifetime info
578
break_loc_sp->ClearBreakpointSite();
579
if (removed_locations_event) {
580
removed_locations_event->GetBreakpointLocationCollection().Add(
581
break_loc_sp);
582
}
583
if (delete_locations)
584
locations_to_remove.Add(break_loc_sp);
585
}
586
}
587
588
if (delete_locations) {
589
size_t num_locations_to_remove = locations_to_remove.GetSize();
590
for (loc_idx = 0; loc_idx < num_locations_to_remove; loc_idx++)
591
m_locations.RemoveLocation(locations_to_remove.GetByIndex(loc_idx));
592
}
593
}
594
}
595
SendBreakpointChangedEvent(removed_locations_event);
596
}
597
}
598
599
static bool SymbolContextsMightBeEquivalent(SymbolContext &old_sc,
600
SymbolContext &new_sc) {
601
bool equivalent_scs = false;
602
603
if (old_sc.module_sp.get() == new_sc.module_sp.get()) {
604
// If these come from the same module, we can directly compare the
605
// pointers:
606
if (old_sc.comp_unit && new_sc.comp_unit &&
607
(old_sc.comp_unit == new_sc.comp_unit)) {
608
if (old_sc.function && new_sc.function &&
609
(old_sc.function == new_sc.function)) {
610
equivalent_scs = true;
611
}
612
} else if (old_sc.symbol && new_sc.symbol &&
613
(old_sc.symbol == new_sc.symbol)) {
614
equivalent_scs = true;
615
}
616
} else {
617
// Otherwise we will compare by name...
618
if (old_sc.comp_unit && new_sc.comp_unit) {
619
if (old_sc.comp_unit->GetPrimaryFile() ==
620
new_sc.comp_unit->GetPrimaryFile()) {
621
// Now check the functions:
622
if (old_sc.function && new_sc.function &&
623
(old_sc.function->GetName() == new_sc.function->GetName())) {
624
equivalent_scs = true;
625
}
626
}
627
} else if (old_sc.symbol && new_sc.symbol) {
628
if (Mangled::Compare(old_sc.symbol->GetMangled(),
629
new_sc.symbol->GetMangled()) == 0) {
630
equivalent_scs = true;
631
}
632
}
633
}
634
return equivalent_scs;
635
}
636
637
void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
638
ModuleSP new_module_sp) {
639
Log *log = GetLog(LLDBLog::Breakpoints);
640
LLDB_LOGF(log, "Breakpoint::ModulesReplaced for %s\n",
641
old_module_sp->GetSpecificationDescription().c_str());
642
// First find all the locations that are in the old module
643
644
BreakpointLocationCollection old_break_locs;
645
for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations()) {
646
SectionSP section_sp = break_loc_sp->GetAddress().GetSection();
647
if (section_sp && section_sp->GetModule() == old_module_sp) {
648
old_break_locs.Add(break_loc_sp);
649
}
650
}
651
652
size_t num_old_locations = old_break_locs.GetSize();
653
654
if (num_old_locations == 0) {
655
// There were no locations in the old module, so we just need to check if
656
// there were any in the new module.
657
ModuleList temp_list;
658
temp_list.Append(new_module_sp);
659
ResolveBreakpointInModules(temp_list);
660
} else {
661
// First search the new module for locations. Then compare this with the
662
// old list, copy over locations that "look the same" Then delete the old
663
// locations. Finally remember to post the creation event.
664
//
665
// Two locations are the same if they have the same comp unit & function
666
// (by name) and there are the same number of locations in the old function
667
// as in the new one.
668
669
ModuleList temp_list;
670
temp_list.Append(new_module_sp);
671
BreakpointLocationCollection new_break_locs;
672
ResolveBreakpointInModules(temp_list, new_break_locs);
673
BreakpointLocationCollection locations_to_remove;
674
BreakpointLocationCollection locations_to_announce;
675
676
size_t num_new_locations = new_break_locs.GetSize();
677
678
if (num_new_locations > 0) {
679
// Break out the case of one location -> one location since that's the
680
// most common one, and there's no need to build up the structures needed
681
// for the merge in that case.
682
if (num_new_locations == 1 && num_old_locations == 1) {
683
bool equivalent_locations = false;
684
SymbolContext old_sc, new_sc;
685
// The only way the old and new location can be equivalent is if they
686
// have the same amount of information:
687
BreakpointLocationSP old_loc_sp = old_break_locs.GetByIndex(0);
688
BreakpointLocationSP new_loc_sp = new_break_locs.GetByIndex(0);
689
690
if (old_loc_sp->GetAddress().CalculateSymbolContext(&old_sc) ==
691
new_loc_sp->GetAddress().CalculateSymbolContext(&new_sc)) {
692
equivalent_locations =
693
SymbolContextsMightBeEquivalent(old_sc, new_sc);
694
}
695
696
if (equivalent_locations) {
697
m_locations.SwapLocation(old_loc_sp, new_loc_sp);
698
} else {
699
locations_to_remove.Add(old_loc_sp);
700
locations_to_announce.Add(new_loc_sp);
701
}
702
} else {
703
// We don't want to have to keep computing the SymbolContexts for these
704
// addresses over and over, so lets get them up front:
705
706
typedef std::map<lldb::break_id_t, SymbolContext> IDToSCMap;
707
IDToSCMap old_sc_map;
708
for (size_t idx = 0; idx < num_old_locations; idx++) {
709
SymbolContext sc;
710
BreakpointLocationSP bp_loc_sp = old_break_locs.GetByIndex(idx);
711
lldb::break_id_t loc_id = bp_loc_sp->GetID();
712
bp_loc_sp->GetAddress().CalculateSymbolContext(&old_sc_map[loc_id]);
713
}
714
715
std::map<lldb::break_id_t, SymbolContext> new_sc_map;
716
for (size_t idx = 0; idx < num_new_locations; idx++) {
717
SymbolContext sc;
718
BreakpointLocationSP bp_loc_sp = new_break_locs.GetByIndex(idx);
719
lldb::break_id_t loc_id = bp_loc_sp->GetID();
720
bp_loc_sp->GetAddress().CalculateSymbolContext(&new_sc_map[loc_id]);
721
}
722
// Take an element from the old Symbol Contexts
723
while (old_sc_map.size() > 0) {
724
lldb::break_id_t old_id = old_sc_map.begin()->first;
725
SymbolContext &old_sc = old_sc_map.begin()->second;
726
727
// Count the number of entries equivalent to this SC for the old
728
// list:
729
std::vector<lldb::break_id_t> old_id_vec;
730
old_id_vec.push_back(old_id);
731
732
IDToSCMap::iterator tmp_iter;
733
for (tmp_iter = ++old_sc_map.begin(); tmp_iter != old_sc_map.end();
734
tmp_iter++) {
735
if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second))
736
old_id_vec.push_back(tmp_iter->first);
737
}
738
739
// Now find all the equivalent locations in the new list.
740
std::vector<lldb::break_id_t> new_id_vec;
741
for (tmp_iter = new_sc_map.begin(); tmp_iter != new_sc_map.end();
742
tmp_iter++) {
743
if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second))
744
new_id_vec.push_back(tmp_iter->first);
745
}
746
747
// Alright, if we have the same number of potentially equivalent
748
// locations in the old and new modules, we'll just map them one to
749
// one in ascending ID order (assuming the resolver's order would
750
// match the equivalent ones. Otherwise, we'll dump all the old ones,
751
// and just take the new ones, erasing the elements from both maps as
752
// we go.
753
754
if (old_id_vec.size() == new_id_vec.size()) {
755
llvm::sort(old_id_vec);
756
llvm::sort(new_id_vec);
757
size_t num_elements = old_id_vec.size();
758
for (size_t idx = 0; idx < num_elements; idx++) {
759
BreakpointLocationSP old_loc_sp =
760
old_break_locs.FindByIDPair(GetID(), old_id_vec[idx]);
761
BreakpointLocationSP new_loc_sp =
762
new_break_locs.FindByIDPair(GetID(), new_id_vec[idx]);
763
m_locations.SwapLocation(old_loc_sp, new_loc_sp);
764
old_sc_map.erase(old_id_vec[idx]);
765
new_sc_map.erase(new_id_vec[idx]);
766
}
767
} else {
768
for (lldb::break_id_t old_id : old_id_vec) {
769
locations_to_remove.Add(
770
old_break_locs.FindByIDPair(GetID(), old_id));
771
old_sc_map.erase(old_id);
772
}
773
for (lldb::break_id_t new_id : new_id_vec) {
774
locations_to_announce.Add(
775
new_break_locs.FindByIDPair(GetID(), new_id));
776
new_sc_map.erase(new_id);
777
}
778
}
779
}
780
}
781
}
782
783
// Now remove the remaining old locations, and cons up a removed locations
784
// event. Note, we don't put the new locations that were swapped with an
785
// old location on the locations_to_remove list, so we don't need to worry
786
// about telling the world about removing a location we didn't tell them
787
// about adding.
788
789
std::shared_ptr<BreakpointEventData> removed_locations_event;
790
if (!IsInternal())
791
removed_locations_event = std::make_shared<BreakpointEventData>(
792
eBreakpointEventTypeLocationsRemoved, shared_from_this());
793
794
for (BreakpointLocationSP loc_sp :
795
locations_to_remove.BreakpointLocations()) {
796
m_locations.RemoveLocation(loc_sp);
797
if (removed_locations_event)
798
removed_locations_event->GetBreakpointLocationCollection().Add(loc_sp);
799
}
800
SendBreakpointChangedEvent(removed_locations_event);
801
802
// And announce the new ones.
803
804
if (!IsInternal()) {
805
std::shared_ptr<BreakpointEventData> added_locations_event =
806
std::make_shared<BreakpointEventData>(
807
eBreakpointEventTypeLocationsAdded, shared_from_this());
808
for (BreakpointLocationSP loc_sp :
809
locations_to_announce.BreakpointLocations())
810
added_locations_event->GetBreakpointLocationCollection().Add(loc_sp);
811
812
SendBreakpointChangedEvent(added_locations_event);
813
}
814
m_locations.Compact();
815
}
816
}
817
818
void Breakpoint::Dump(Stream *) {}
819
820
size_t Breakpoint::GetNumResolvedLocations() const {
821
// Return the number of breakpoints that are actually resolved and set down
822
// in the inferior process.
823
return m_locations.GetNumResolvedLocations();
824
}
825
826
bool Breakpoint::HasResolvedLocations() const {
827
return GetNumResolvedLocations() > 0;
828
}
829
830
size_t Breakpoint::GetNumLocations() const { return m_locations.GetSize(); }
831
832
void Breakpoint::AddName(llvm::StringRef new_name) {
833
m_name_list.insert(new_name.str());
834
}
835
836
void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level,
837
bool show_locations) {
838
assert(s != nullptr);
839
840
if (!m_kind_description.empty()) {
841
if (level == eDescriptionLevelBrief) {
842
s->PutCString(GetBreakpointKind());
843
return;
844
} else
845
s->Printf("Kind: %s\n", GetBreakpointKind());
846
}
847
848
const size_t num_locations = GetNumLocations();
849
const size_t num_resolved_locations = GetNumResolvedLocations();
850
851
// They just made the breakpoint, they don't need to be told HOW they made
852
// it... Also, we'll print the breakpoint number differently depending on
853
// whether there is 1 or more locations.
854
if (level != eDescriptionLevelInitial) {
855
s->Printf("%i: ", GetID());
856
GetResolverDescription(s);
857
GetFilterDescription(s);
858
}
859
860
switch (level) {
861
case lldb::eDescriptionLevelBrief:
862
case lldb::eDescriptionLevelFull:
863
if (num_locations > 0) {
864
s->Printf(", locations = %" PRIu64, (uint64_t)num_locations);
865
if (num_resolved_locations > 0)
866
s->Printf(", resolved = %" PRIu64 ", hit count = %d",
867
(uint64_t)num_resolved_locations, GetHitCount());
868
} else {
869
// Don't print the pending notification for exception resolvers since we
870
// don't generally know how to set them until the target is run.
871
if (m_resolver_sp->getResolverID() !=
872
BreakpointResolver::ExceptionResolver)
873
s->Printf(", locations = 0 (pending)");
874
}
875
876
m_options.GetDescription(s, level);
877
878
if (m_precondition_sp)
879
m_precondition_sp->GetDescription(*s, level);
880
881
if (level == lldb::eDescriptionLevelFull) {
882
if (!m_name_list.empty()) {
883
s->EOL();
884
s->Indent();
885
s->Printf("Names:");
886
s->EOL();
887
s->IndentMore();
888
for (const std::string &name : m_name_list) {
889
s->Indent();
890
s->Printf("%s\n", name.c_str());
891
}
892
s->IndentLess();
893
}
894
s->IndentLess();
895
s->EOL();
896
}
897
break;
898
899
case lldb::eDescriptionLevelInitial:
900
s->Printf("Breakpoint %i: ", GetID());
901
if (num_locations == 0) {
902
s->Printf("no locations (pending).");
903
} else if (num_locations == 1 && !show_locations) {
904
// There is only one location, so we'll just print that location
905
// information.
906
GetLocationAtIndex(0)->GetDescription(s, level);
907
} else {
908
s->Printf("%" PRIu64 " locations.", static_cast<uint64_t>(num_locations));
909
}
910
s->EOL();
911
break;
912
913
case lldb::eDescriptionLevelVerbose:
914
// Verbose mode does a debug dump of the breakpoint
915
Dump(s);
916
s->EOL();
917
// s->Indent();
918
m_options.GetDescription(s, level);
919
break;
920
921
default:
922
break;
923
}
924
925
// The brief description is just the location name (1.2 or whatever). That's
926
// pointless to show in the breakpoint's description, so suppress it.
927
if (show_locations && level != lldb::eDescriptionLevelBrief) {
928
s->IndentMore();
929
for (size_t i = 0; i < num_locations; ++i) {
930
BreakpointLocation *loc = GetLocationAtIndex(i).get();
931
loc->GetDescription(s, level);
932
s->EOL();
933
}
934
s->IndentLess();
935
}
936
}
937
938
void Breakpoint::GetResolverDescription(Stream *s) {
939
if (m_resolver_sp)
940
m_resolver_sp->GetDescription(s);
941
}
942
943
bool Breakpoint::GetMatchingFileLine(ConstString filename,
944
uint32_t line_number,
945
BreakpointLocationCollection &loc_coll) {
946
// TODO: To be correct, this method needs to fill the breakpoint location
947
// collection
948
// with the location IDs which match the filename and line_number.
949
//
950
951
if (m_resolver_sp) {
952
BreakpointResolverFileLine *resolverFileLine =
953
dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get());
954
955
// TODO: Handle SourceLocationSpec column information
956
if (resolverFileLine &&
957
resolverFileLine->m_location_spec.GetFileSpec().GetFilename() ==
958
filename &&
959
resolverFileLine->m_location_spec.GetLine() == line_number) {
960
return true;
961
}
962
}
963
return false;
964
}
965
966
void Breakpoint::GetFilterDescription(Stream *s) {
967
m_filter_sp->GetDescription(s);
968
}
969
970
bool Breakpoint::EvaluatePrecondition(StoppointCallbackContext &context) {
971
if (!m_precondition_sp)
972
return true;
973
974
return m_precondition_sp->EvaluatePrecondition(context);
975
}
976
977
void Breakpoint::SendBreakpointChangedEvent(
978
lldb::BreakpointEventType eventKind) {
979
if (!IsInternal() && GetTarget().EventTypeHasListeners(
980
Target::eBroadcastBitBreakpointChanged)) {
981
std::shared_ptr<BreakpointEventData> data =
982
std::make_shared<BreakpointEventData>(eventKind, shared_from_this());
983
984
GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, data);
985
}
986
}
987
988
void Breakpoint::SendBreakpointChangedEvent(
989
const lldb::EventDataSP &breakpoint_data_sp) {
990
if (!breakpoint_data_sp)
991
return;
992
993
if (!IsInternal() &&
994
GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
995
GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
996
breakpoint_data_sp);
997
}
998
999
const char *Breakpoint::BreakpointEventTypeAsCString(BreakpointEventType type) {
1000
switch (type) {
1001
case eBreakpointEventTypeInvalidType: return "invalid";
1002
case eBreakpointEventTypeAdded: return "breakpoint added";
1003
case eBreakpointEventTypeRemoved: return "breakpoint removed";
1004
case eBreakpointEventTypeLocationsAdded: return "locations added";
1005
case eBreakpointEventTypeLocationsRemoved: return "locations removed";
1006
case eBreakpointEventTypeLocationsResolved: return "locations resolved";
1007
case eBreakpointEventTypeEnabled: return "breakpoint enabled";
1008
case eBreakpointEventTypeDisabled: return "breakpoint disabled";
1009
case eBreakpointEventTypeCommandChanged: return "command changed";
1010
case eBreakpointEventTypeConditionChanged: return "condition changed";
1011
case eBreakpointEventTypeIgnoreChanged: return "ignore count changed";
1012
case eBreakpointEventTypeThreadChanged: return "thread changed";
1013
case eBreakpointEventTypeAutoContinueChanged: return "autocontinue changed";
1014
};
1015
llvm_unreachable("Fully covered switch above!");
1016
}
1017
1018
Log *Breakpoint::BreakpointEventData::GetLogChannel() {
1019
return GetLog(LLDBLog::Breakpoints);
1020
}
1021
1022
Breakpoint::BreakpointEventData::BreakpointEventData(
1023
BreakpointEventType sub_type, const BreakpointSP &new_breakpoint_sp)
1024
: m_breakpoint_event(sub_type), m_new_breakpoint_sp(new_breakpoint_sp) {}
1025
1026
Breakpoint::BreakpointEventData::~BreakpointEventData() = default;
1027
1028
llvm::StringRef Breakpoint::BreakpointEventData::GetFlavorString() {
1029
return "Breakpoint::BreakpointEventData";
1030
}
1031
1032
llvm::StringRef Breakpoint::BreakpointEventData::GetFlavor() const {
1033
return BreakpointEventData::GetFlavorString();
1034
}
1035
1036
BreakpointSP Breakpoint::BreakpointEventData::GetBreakpoint() const {
1037
return m_new_breakpoint_sp;
1038
}
1039
1040
BreakpointEventType
1041
Breakpoint::BreakpointEventData::GetBreakpointEventType() const {
1042
return m_breakpoint_event;
1043
}
1044
1045
void Breakpoint::BreakpointEventData::Dump(Stream *s) const {
1046
if (!s)
1047
return;
1048
BreakpointEventType event_type = GetBreakpointEventType();
1049
break_id_t bkpt_id = GetBreakpoint()->GetID();
1050
s->Format("bkpt: {0} type: {1}", bkpt_id,
1051
BreakpointEventTypeAsCString(event_type));
1052
}
1053
1054
const Breakpoint::BreakpointEventData *
1055
Breakpoint::BreakpointEventData::GetEventDataFromEvent(const Event *event) {
1056
if (event) {
1057
const EventData *event_data = event->GetData();
1058
if (event_data &&
1059
event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
1060
return static_cast<const BreakpointEventData *>(event->GetData());
1061
}
1062
return nullptr;
1063
}
1064
1065
BreakpointEventType
1066
Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1067
const EventSP &event_sp) {
1068
const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());
1069
1070
if (data == nullptr)
1071
return eBreakpointEventTypeInvalidType;
1072
else
1073
return data->GetBreakpointEventType();
1074
}
1075
1076
BreakpointSP Breakpoint::BreakpointEventData::GetBreakpointFromEvent(
1077
const EventSP &event_sp) {
1078
BreakpointSP bp_sp;
1079
1080
const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());
1081
if (data)
1082
bp_sp = data->m_new_breakpoint_sp;
1083
1084
return bp_sp;
1085
}
1086
1087
size_t Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1088
const EventSP &event_sp) {
1089
const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());
1090
if (data)
1091
return data->m_locations.GetSize();
1092
1093
return 0;
1094
}
1095
1096
lldb::BreakpointLocationSP
1097
Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent(
1098
const lldb::EventSP &event_sp, uint32_t bp_loc_idx) {
1099
lldb::BreakpointLocationSP bp_loc_sp;
1100
1101
const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());
1102
if (data) {
1103
bp_loc_sp = data->m_locations.GetByIndex(bp_loc_idx);
1104
}
1105
1106
return bp_loc_sp;
1107
}
1108
1109
json::Value Breakpoint::GetStatistics() {
1110
json::Object bp;
1111
bp.try_emplace("id", GetID());
1112
bp.try_emplace("resolveTime", m_resolve_time.get().count());
1113
bp.try_emplace("numLocations", (int64_t)GetNumLocations());
1114
bp.try_emplace("numResolvedLocations", (int64_t)GetNumResolvedLocations());
1115
bp.try_emplace("hitCount", (int64_t)GetHitCount());
1116
bp.try_emplace("internal", IsInternal());
1117
if (!m_kind_description.empty())
1118
bp.try_emplace("kindDescription", m_kind_description);
1119
// Put the full structured data for reproducing this breakpoint in a key/value
1120
// pair named "details". This allows the breakpoint's details to be visible
1121
// in the stats in case we need to reproduce a breakpoint that has long
1122
// resolve times
1123
StructuredData::ObjectSP bp_data_sp = SerializeToStructuredData();
1124
if (bp_data_sp) {
1125
std::string buffer;
1126
llvm::raw_string_ostream ss(buffer);
1127
json::OStream json_os(ss);
1128
bp_data_sp->Serialize(json_os);
1129
if (auto expected_value = llvm::json::parse(ss.str())) {
1130
bp.try_emplace("details", std::move(*expected_value));
1131
} else {
1132
std::string details_error = toString(expected_value.takeError());
1133
json::Object details;
1134
details.try_emplace("error", details_error);
1135
bp.try_emplace("details", std::move(details));
1136
}
1137
}
1138
return json::Value(std::move(bp));
1139
}
1140
1141