1 //===-- Breakpoint.cpp ----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/Casting.h"
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"
37 using namespace lldb_private
;
40 const char *Breakpoint::g_option_names
[static_cast<uint32_t>(
41 Breakpoint::OptionNames::LastOptionName
)]{"Names", "Hardware"};
43 // Breakpoint constructor
44 Breakpoint::Breakpoint(Target
&target
, SearchFilterSP
&filter_sp
,
45 BreakpointResolverSP
&resolver_sp
, bool hardware
,
46 bool resolve_indirect_symbols
)
47 : m_being_created(true), m_hardware(hardware
), m_target(target
),
48 m_filter_sp(filter_sp
), m_resolver_sp(resolver_sp
), m_options(true),
49 m_locations(*this), m_resolve_indirect_symbols(resolve_indirect_symbols
),
51 m_being_created
= false;
54 Breakpoint::Breakpoint(Target
&new_target
, const Breakpoint
&source_bp
)
55 : m_being_created(true), m_hardware(source_bp
.m_hardware
),
56 m_target(new_target
), m_name_list(source_bp
.m_name_list
),
57 m_options(source_bp
.m_options
), m_locations(*this),
58 m_resolve_indirect_symbols(source_bp
.m_resolve_indirect_symbols
),
62 Breakpoint::~Breakpoint() = default;
64 BreakpointSP
Breakpoint::CopyFromBreakpoint(TargetSP new_target
,
65 const Breakpoint
& bp_to_copy_from
) {
67 return BreakpointSP();
69 BreakpointSP
bp(new Breakpoint(*new_target
, bp_to_copy_from
));
70 // Now go through and copy the filter & resolver:
71 bp
->m_resolver_sp
= bp_to_copy_from
.m_resolver_sp
->CopyForBreakpoint(bp
);
72 bp
->m_filter_sp
= bp_to_copy_from
.m_filter_sp
->CreateCopy(new_target
);
77 StructuredData::ObjectSP
Breakpoint::SerializeToStructuredData() {
78 // Serialize the resolver:
79 StructuredData::DictionarySP
breakpoint_dict_sp(
80 new StructuredData::Dictionary());
81 StructuredData::DictionarySP
breakpoint_contents_sp(
82 new StructuredData::Dictionary());
84 if (!m_name_list
.empty()) {
85 StructuredData::ArraySP
names_array_sp(new StructuredData::Array());
86 for (auto name
: m_name_list
) {
87 names_array_sp
->AddItem(
88 StructuredData::StringSP(new StructuredData::String(name
)));
90 breakpoint_contents_sp
->AddItem(Breakpoint::GetKey(OptionNames::Names
),
94 breakpoint_contents_sp
->AddBooleanItem(
95 Breakpoint::GetKey(OptionNames::Hardware
), m_hardware
);
97 StructuredData::ObjectSP
resolver_dict_sp(
98 m_resolver_sp
->SerializeToStructuredData());
99 if (!resolver_dict_sp
)
100 return StructuredData::ObjectSP();
102 breakpoint_contents_sp
->AddItem(BreakpointResolver::GetSerializationKey(),
105 StructuredData::ObjectSP
filter_dict_sp(
106 m_filter_sp
->SerializeToStructuredData());
108 return StructuredData::ObjectSP();
110 breakpoint_contents_sp
->AddItem(SearchFilter::GetSerializationKey(),
113 StructuredData::ObjectSP
options_dict_sp(
114 m_options
.SerializeToStructuredData());
115 if (!options_dict_sp
)
116 return StructuredData::ObjectSP();
118 breakpoint_contents_sp
->AddItem(BreakpointOptions::GetSerializationKey(),
121 breakpoint_dict_sp
->AddItem(GetSerializationKey(), breakpoint_contents_sp
);
122 return breakpoint_dict_sp
;
125 lldb::BreakpointSP
Breakpoint::CreateFromStructuredData(
126 TargetSP target_sp
, StructuredData::ObjectSP
&object_data
, Status
&error
) {
127 BreakpointSP result_sp
;
131 StructuredData::Dictionary
*breakpoint_dict
= object_data
->GetAsDictionary();
133 if (!breakpoint_dict
|| !breakpoint_dict
->IsValid()) {
134 error
.SetErrorString("Can't deserialize from an invalid data object.");
138 StructuredData::Dictionary
*resolver_dict
;
139 bool success
= breakpoint_dict
->GetValueForKeyAsDictionary(
140 BreakpointResolver::GetSerializationKey(), resolver_dict
);
142 error
.SetErrorString("Breakpoint data missing toplevel resolver key");
147 BreakpointResolverSP resolver_sp
=
148 BreakpointResolver::CreateFromStructuredData(*resolver_dict
,
150 if (create_error
.Fail()) {
151 error
.SetErrorStringWithFormat(
152 "Error creating breakpoint resolver from data: %s.",
153 create_error
.AsCString());
157 StructuredData::Dictionary
*filter_dict
;
158 success
= breakpoint_dict
->GetValueForKeyAsDictionary(
159 SearchFilter::GetSerializationKey(), filter_dict
);
160 SearchFilterSP filter_sp
;
163 std::make_shared
<SearchFilterForUnconstrainedSearches
>(target_sp
);
165 filter_sp
= SearchFilter::CreateFromStructuredData(target_sp
, *filter_dict
,
167 if (create_error
.Fail()) {
168 error
.SetErrorStringWithFormat(
169 "Error creating breakpoint filter from data: %s.",
170 create_error
.AsCString());
175 std::unique_ptr
<BreakpointOptions
> options_up
;
176 StructuredData::Dictionary
*options_dict
;
177 Target
& target
= *target_sp
;
178 success
= breakpoint_dict
->GetValueForKeyAsDictionary(
179 BreakpointOptions::GetSerializationKey(), options_dict
);
181 options_up
= BreakpointOptions::CreateFromStructuredData(
182 target
, *options_dict
, create_error
);
183 if (create_error
.Fail()) {
184 error
.SetErrorStringWithFormat(
185 "Error creating breakpoint options from data: %s.",
186 create_error
.AsCString());
191 bool hardware
= false;
192 success
= breakpoint_dict
->GetValueForKeyAsBoolean(
193 Breakpoint::GetKey(OptionNames::Hardware
), hardware
);
195 result_sp
= target
.CreateBreakpoint(filter_sp
, resolver_sp
, false,
198 if (result_sp
&& options_up
) {
199 result_sp
->m_options
= *options_up
;
202 StructuredData::Array
*names_array
;
203 success
= breakpoint_dict
->GetValueForKeyAsArray(
204 Breakpoint::GetKey(OptionNames::Names
), names_array
);
205 if (success
&& names_array
) {
206 size_t num_names
= names_array
->GetSize();
207 for (size_t i
= 0; i
< num_names
; i
++) {
208 llvm::StringRef name
;
210 success
= names_array
->GetItemAtIndexAsString(i
, name
);
211 target
.AddNameToBreakpoint(result_sp
, name
.str().c_str(), error
);
218 bool Breakpoint::SerializedBreakpointMatchesNames(
219 StructuredData::ObjectSP
&bkpt_object_sp
, std::vector
<std::string
> &names
) {
223 StructuredData::Dictionary
*bkpt_dict
= bkpt_object_sp
->GetAsDictionary();
230 StructuredData::Array
*names_array
;
233 bkpt_dict
->GetValueForKeyAsArray(GetKey(OptionNames::Names
), names_array
);
234 // If there are no names, it can't match these names;
238 size_t num_names
= names_array
->GetSize();
240 for (size_t i
= 0; i
< num_names
; i
++) {
241 llvm::StringRef name
;
242 if (names_array
->GetItemAtIndexAsString(i
, name
)) {
243 if (llvm::is_contained(names
, name
))
250 const lldb::TargetSP
Breakpoint::GetTargetSP() {
251 return m_target
.shared_from_this();
254 bool Breakpoint::IsInternal() const { return LLDB_BREAK_ID_IS_INTERNAL(m_bid
); }
256 BreakpointLocationSP
Breakpoint::AddLocation(const Address
&addr
,
257 bool *new_location
) {
258 return m_locations
.AddLocation(addr
, m_resolve_indirect_symbols
,
262 BreakpointLocationSP
Breakpoint::FindLocationByAddress(const Address
&addr
) {
263 return m_locations
.FindByAddress(addr
);
266 break_id_t
Breakpoint::FindLocationIDByAddress(const Address
&addr
) {
267 return m_locations
.FindIDByAddress(addr
);
270 BreakpointLocationSP
Breakpoint::FindLocationByID(break_id_t bp_loc_id
) {
271 return m_locations
.FindByID(bp_loc_id
);
274 BreakpointLocationSP
Breakpoint::GetLocationAtIndex(size_t index
) {
275 return m_locations
.GetByIndex(index
);
278 void Breakpoint::RemoveInvalidLocations(const ArchSpec
&arch
) {
279 m_locations
.RemoveInvalidLocations(arch
);
282 // For each of the overall options we need to decide how they propagate to the
283 // location options. This will determine the precedence of options on the
284 // breakpoint vs. its locations.
286 // Disable at the breakpoint level should override the location settings. That
287 // way you can conveniently turn off a whole breakpoint without messing up the
288 // individual settings.
290 void Breakpoint::SetEnabled(bool enable
) {
291 if (enable
== m_options
.IsEnabled())
294 m_options
.SetEnabled(enable
);
296 m_locations
.ResolveAllBreakpointSites();
298 m_locations
.ClearAllBreakpointSites();
300 SendBreakpointChangedEvent(enable
? eBreakpointEventTypeEnabled
301 : eBreakpointEventTypeDisabled
);
304 bool Breakpoint::IsEnabled() { return m_options
.IsEnabled(); }
306 void Breakpoint::SetIgnoreCount(uint32_t n
) {
307 if (m_options
.GetIgnoreCount() == n
)
310 m_options
.SetIgnoreCount(n
);
311 SendBreakpointChangedEvent(eBreakpointEventTypeIgnoreChanged
);
314 void Breakpoint::DecrementIgnoreCount() {
315 uint32_t ignore
= m_options
.GetIgnoreCount();
317 m_options
.SetIgnoreCount(ignore
- 1);
320 uint32_t Breakpoint::GetIgnoreCount() const {
321 return m_options
.GetIgnoreCount();
324 uint32_t Breakpoint::GetHitCount() const { return m_hit_counter
.GetValue(); }
326 void Breakpoint::ResetHitCount() {
327 m_hit_counter
.Reset();
328 m_locations
.ResetHitCount();
331 bool Breakpoint::IsOneShot() const { return m_options
.IsOneShot(); }
333 void Breakpoint::SetOneShot(bool one_shot
) { m_options
.SetOneShot(one_shot
); }
335 bool Breakpoint::IsAutoContinue() const { return m_options
.IsAutoContinue(); }
337 void Breakpoint::SetAutoContinue(bool auto_continue
) {
338 m_options
.SetAutoContinue(auto_continue
);
341 void Breakpoint::SetThreadID(lldb::tid_t thread_id
) {
342 if (m_options
.GetThreadSpec()->GetTID() == thread_id
)
345 m_options
.GetThreadSpec()->SetTID(thread_id
);
346 SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged
);
349 lldb::tid_t
Breakpoint::GetThreadID() const {
350 if (m_options
.GetThreadSpecNoCreate() == nullptr)
351 return LLDB_INVALID_THREAD_ID
;
353 return m_options
.GetThreadSpecNoCreate()->GetTID();
356 void Breakpoint::SetThreadIndex(uint32_t index
) {
357 if (m_options
.GetThreadSpec()->GetIndex() == index
)
360 m_options
.GetThreadSpec()->SetIndex(index
);
361 SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged
);
364 uint32_t Breakpoint::GetThreadIndex() const {
365 if (m_options
.GetThreadSpecNoCreate() == nullptr)
368 return m_options
.GetThreadSpecNoCreate()->GetIndex();
371 void Breakpoint::SetThreadName(const char *thread_name
) {
372 if (m_options
.GetThreadSpec()->GetName() != nullptr &&
373 ::strcmp(m_options
.GetThreadSpec()->GetName(), thread_name
) == 0)
376 m_options
.GetThreadSpec()->SetName(thread_name
);
377 SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged
);
380 const char *Breakpoint::GetThreadName() const {
381 if (m_options
.GetThreadSpecNoCreate() == nullptr)
384 return m_options
.GetThreadSpecNoCreate()->GetName();
387 void Breakpoint::SetQueueName(const char *queue_name
) {
388 if (m_options
.GetThreadSpec()->GetQueueName() != nullptr &&
389 ::strcmp(m_options
.GetThreadSpec()->GetQueueName(), queue_name
) == 0)
392 m_options
.GetThreadSpec()->SetQueueName(queue_name
);
393 SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged
);
396 const char *Breakpoint::GetQueueName() const {
397 if (m_options
.GetThreadSpecNoCreate() == nullptr)
400 return m_options
.GetThreadSpecNoCreate()->GetQueueName();
403 void Breakpoint::SetCondition(const char *condition
) {
404 m_options
.SetCondition(condition
);
405 SendBreakpointChangedEvent(eBreakpointEventTypeConditionChanged
);
408 const char *Breakpoint::GetConditionText() const {
409 return m_options
.GetConditionText();
412 // This function is used when "baton" doesn't need to be freed
413 void Breakpoint::SetCallback(BreakpointHitCallback callback
, void *baton
,
414 bool is_synchronous
) {
415 // The default "Baton" class will keep a copy of "baton" and won't free or
416 // delete it when it goes out of scope.
417 m_options
.SetCallback(callback
, std::make_shared
<UntypedBaton
>(baton
),
420 SendBreakpointChangedEvent(eBreakpointEventTypeCommandChanged
);
423 // This function is used when a baton needs to be freed and therefore is
424 // contained in a "Baton" subclass.
425 void Breakpoint::SetCallback(BreakpointHitCallback callback
,
426 const BatonSP
&callback_baton_sp
,
427 bool is_synchronous
) {
428 m_options
.SetCallback(callback
, callback_baton_sp
, is_synchronous
);
431 void Breakpoint::ClearCallback() { m_options
.ClearCallback(); }
433 bool Breakpoint::InvokeCallback(StoppointCallbackContext
*context
,
434 break_id_t bp_loc_id
) {
435 return m_options
.InvokeCallback(context
, GetID(), bp_loc_id
);
438 BreakpointOptions
&Breakpoint::GetOptions() { return m_options
; }
440 const BreakpointOptions
&Breakpoint::GetOptions() const { return m_options
; }
442 void Breakpoint::ResolveBreakpoint() {
444 ElapsedTime
elapsed(m_resolve_time
);
445 m_resolver_sp
->ResolveBreakpoint(*m_filter_sp
);
449 void Breakpoint::ResolveBreakpointInModules(
450 ModuleList
&module_list
, BreakpointLocationCollection
&new_locations
) {
451 ElapsedTime
elapsed(m_resolve_time
);
452 m_locations
.StartRecordingNewLocations(new_locations
);
454 m_resolver_sp
->ResolveBreakpointInModules(*m_filter_sp
, module_list
);
456 m_locations
.StopRecordingNewLocations();
459 void Breakpoint::ResolveBreakpointInModules(ModuleList
&module_list
,
462 // If this is not an internal breakpoint, set up to record the new
463 // locations, then dispatch an event with the new locations.
464 if (!IsInternal() && send_event
) {
465 BreakpointEventData
*new_locations_event
= new BreakpointEventData(
466 eBreakpointEventTypeLocationsAdded
, shared_from_this());
468 ResolveBreakpointInModules(
469 module_list
, new_locations_event
->GetBreakpointLocationCollection());
471 if (new_locations_event
->GetBreakpointLocationCollection().GetSize() !=
473 SendBreakpointChangedEvent(new_locations_event
);
475 delete new_locations_event
;
477 ElapsedTime
elapsed(m_resolve_time
);
478 m_resolver_sp
->ResolveBreakpointInModules(*m_filter_sp
, module_list
);
483 void Breakpoint::ClearAllBreakpointSites() {
484 m_locations
.ClearAllBreakpointSites();
487 // ModulesChanged: Pass in a list of new modules, and
489 void Breakpoint::ModulesChanged(ModuleList
&module_list
, bool load
,
490 bool delete_locations
) {
491 Log
*log
= GetLog(LLDBLog::Breakpoints
);
493 "Breakpoint::ModulesChanged: num_modules: %zu load: %i "
494 "delete_locations: %i\n",
495 module_list
.GetSize(), load
, delete_locations
);
498 // The logic for handling new modules is:
499 // 1) If the filter rejects this module, then skip it. 2) Run through the
500 // current location list and if there are any locations
501 // for that module, we mark the module as "seen" and we don't try to
503 // breakpoint locations for that module.
504 // However, we do add breakpoint sites to these locations if needed.
505 // 3) If we don't see this module in our breakpoint location list, call
508 ModuleList new_modules
; // We'll stuff the "unseen" modules in this list,
510 // them after the locations pass. Have to do it this way because resolving
511 // breakpoints will add new locations potentially.
513 for (ModuleSP module_sp
: module_list
.Modules()) {
515 if (!m_filter_sp
->ModulePasses(module_sp
))
518 BreakpointLocationCollection locations_with_no_section
;
519 for (BreakpointLocationSP break_loc_sp
:
520 m_locations
.BreakpointLocations()) {
522 // If the section for this location was deleted, that means it's Module
523 // has gone away but somebody forgot to tell us. Let's clean it up
525 Address
section_addr(break_loc_sp
->GetAddress());
526 if (section_addr
.SectionWasDeleted()) {
527 locations_with_no_section
.Add(break_loc_sp
);
531 if (!break_loc_sp
->IsEnabled())
534 SectionSP
section_sp(section_addr
.GetSection());
536 // If we don't have a Section, that means this location is a raw
537 // address that we haven't resolved to a section yet. So we'll have to
538 // look in all the new modules to resolve this location. Otherwise, if
539 // it was set in this module, re-resolve it here.
540 if (section_sp
&& section_sp
->GetModule() == module_sp
) {
544 if (!break_loc_sp
->ResolveBreakpointSite()) {
546 "Warning: could not set breakpoint site for "
547 "breakpoint location %d of breakpoint %d.\n",
548 break_loc_sp
->GetID(), GetID());
553 size_t num_to_delete
= locations_with_no_section
.GetSize();
555 for (size_t i
= 0; i
< num_to_delete
; i
++)
556 m_locations
.RemoveLocation(locations_with_no_section
.GetByIndex(i
));
559 new_modules
.AppendIfNeeded(module_sp
);
562 if (new_modules
.GetSize() > 0) {
563 ResolveBreakpointInModules(new_modules
);
566 // Go through the currently set locations and if any have breakpoints in
567 // the module list, then remove their breakpoint sites, and their locations
570 BreakpointEventData
*removed_locations_event
;
572 removed_locations_event
= new BreakpointEventData(
573 eBreakpointEventTypeLocationsRemoved
, shared_from_this());
575 removed_locations_event
= nullptr;
577 for (ModuleSP module_sp
: module_list
.Modules()) {
578 if (m_filter_sp
->ModulePasses(module_sp
)) {
580 size_t num_locations
= m_locations
.GetSize();
581 BreakpointLocationCollection locations_to_remove
;
582 for (loc_idx
= 0; loc_idx
< num_locations
; loc_idx
++) {
583 BreakpointLocationSP
break_loc_sp(m_locations
.GetByIndex(loc_idx
));
584 SectionSP
section_sp(break_loc_sp
->GetAddress().GetSection());
585 if (section_sp
&& section_sp
->GetModule() == module_sp
) {
586 // Remove this breakpoint since the shared library is unloaded, but
587 // keep the breakpoint location around so we always get complete
588 // hit count and breakpoint lifetime info
589 break_loc_sp
->ClearBreakpointSite();
590 if (removed_locations_event
) {
591 removed_locations_event
->GetBreakpointLocationCollection().Add(
594 if (delete_locations
)
595 locations_to_remove
.Add(break_loc_sp
);
599 if (delete_locations
) {
600 size_t num_locations_to_remove
= locations_to_remove
.GetSize();
601 for (loc_idx
= 0; loc_idx
< num_locations_to_remove
; loc_idx
++)
602 m_locations
.RemoveLocation(locations_to_remove
.GetByIndex(loc_idx
));
606 SendBreakpointChangedEvent(removed_locations_event
);
610 static bool SymbolContextsMightBeEquivalent(SymbolContext
&old_sc
,
611 SymbolContext
&new_sc
) {
612 bool equivalent_scs
= false;
614 if (old_sc
.module_sp
.get() == new_sc
.module_sp
.get()) {
615 // If these come from the same module, we can directly compare the
617 if (old_sc
.comp_unit
&& new_sc
.comp_unit
&&
618 (old_sc
.comp_unit
== new_sc
.comp_unit
)) {
619 if (old_sc
.function
&& new_sc
.function
&&
620 (old_sc
.function
== new_sc
.function
)) {
621 equivalent_scs
= true;
623 } else if (old_sc
.symbol
&& new_sc
.symbol
&&
624 (old_sc
.symbol
== new_sc
.symbol
)) {
625 equivalent_scs
= true;
628 // Otherwise we will compare by name...
629 if (old_sc
.comp_unit
&& new_sc
.comp_unit
) {
630 if (old_sc
.comp_unit
->GetPrimaryFile() ==
631 new_sc
.comp_unit
->GetPrimaryFile()) {
632 // Now check the functions:
633 if (old_sc
.function
&& new_sc
.function
&&
634 (old_sc
.function
->GetName() == new_sc
.function
->GetName())) {
635 equivalent_scs
= true;
638 } else if (old_sc
.symbol
&& new_sc
.symbol
) {
639 if (Mangled::Compare(old_sc
.symbol
->GetMangled(),
640 new_sc
.symbol
->GetMangled()) == 0) {
641 equivalent_scs
= true;
645 return equivalent_scs
;
648 void Breakpoint::ModuleReplaced(ModuleSP old_module_sp
,
649 ModuleSP new_module_sp
) {
650 Log
*log
= GetLog(LLDBLog::Breakpoints
);
651 LLDB_LOGF(log
, "Breakpoint::ModulesReplaced for %s\n",
652 old_module_sp
->GetSpecificationDescription().c_str());
653 // First find all the locations that are in the old module
655 BreakpointLocationCollection old_break_locs
;
656 for (BreakpointLocationSP break_loc_sp
: m_locations
.BreakpointLocations()) {
657 SectionSP section_sp
= break_loc_sp
->GetAddress().GetSection();
658 if (section_sp
&& section_sp
->GetModule() == old_module_sp
) {
659 old_break_locs
.Add(break_loc_sp
);
663 size_t num_old_locations
= old_break_locs
.GetSize();
665 if (num_old_locations
== 0) {
666 // There were no locations in the old module, so we just need to check if
667 // there were any in the new module.
668 ModuleList temp_list
;
669 temp_list
.Append(new_module_sp
);
670 ResolveBreakpointInModules(temp_list
);
672 // First search the new module for locations. Then compare this with the
673 // old list, copy over locations that "look the same" Then delete the old
674 // locations. Finally remember to post the creation event.
676 // Two locations are the same if they have the same comp unit & function
677 // (by name) and there are the same number of locations in the old function
678 // as in the new one.
680 ModuleList temp_list
;
681 temp_list
.Append(new_module_sp
);
682 BreakpointLocationCollection new_break_locs
;
683 ResolveBreakpointInModules(temp_list
, new_break_locs
);
684 BreakpointLocationCollection locations_to_remove
;
685 BreakpointLocationCollection locations_to_announce
;
687 size_t num_new_locations
= new_break_locs
.GetSize();
689 if (num_new_locations
> 0) {
690 // Break out the case of one location -> one location since that's the
691 // most common one, and there's no need to build up the structures needed
692 // for the merge in that case.
693 if (num_new_locations
== 1 && num_old_locations
== 1) {
694 bool equivalent_locations
= false;
695 SymbolContext old_sc
, new_sc
;
696 // The only way the old and new location can be equivalent is if they
697 // have the same amount of information:
698 BreakpointLocationSP old_loc_sp
= old_break_locs
.GetByIndex(0);
699 BreakpointLocationSP new_loc_sp
= new_break_locs
.GetByIndex(0);
701 if (old_loc_sp
->GetAddress().CalculateSymbolContext(&old_sc
) ==
702 new_loc_sp
->GetAddress().CalculateSymbolContext(&new_sc
)) {
703 equivalent_locations
=
704 SymbolContextsMightBeEquivalent(old_sc
, new_sc
);
707 if (equivalent_locations
) {
708 m_locations
.SwapLocation(old_loc_sp
, new_loc_sp
);
710 locations_to_remove
.Add(old_loc_sp
);
711 locations_to_announce
.Add(new_loc_sp
);
714 // We don't want to have to keep computing the SymbolContexts for these
715 // addresses over and over, so lets get them up front:
717 typedef std::map
<lldb::break_id_t
, SymbolContext
> IDToSCMap
;
718 IDToSCMap old_sc_map
;
719 for (size_t idx
= 0; idx
< num_old_locations
; idx
++) {
721 BreakpointLocationSP bp_loc_sp
= old_break_locs
.GetByIndex(idx
);
722 lldb::break_id_t loc_id
= bp_loc_sp
->GetID();
723 bp_loc_sp
->GetAddress().CalculateSymbolContext(&old_sc_map
[loc_id
]);
726 std::map
<lldb::break_id_t
, SymbolContext
> new_sc_map
;
727 for (size_t idx
= 0; idx
< num_new_locations
; idx
++) {
729 BreakpointLocationSP bp_loc_sp
= new_break_locs
.GetByIndex(idx
);
730 lldb::break_id_t loc_id
= bp_loc_sp
->GetID();
731 bp_loc_sp
->GetAddress().CalculateSymbolContext(&new_sc_map
[loc_id
]);
733 // Take an element from the old Symbol Contexts
734 while (old_sc_map
.size() > 0) {
735 lldb::break_id_t old_id
= old_sc_map
.begin()->first
;
736 SymbolContext
&old_sc
= old_sc_map
.begin()->second
;
738 // Count the number of entries equivalent to this SC for the old
740 std::vector
<lldb::break_id_t
> old_id_vec
;
741 old_id_vec
.push_back(old_id
);
743 IDToSCMap::iterator tmp_iter
;
744 for (tmp_iter
= ++old_sc_map
.begin(); tmp_iter
!= old_sc_map
.end();
746 if (SymbolContextsMightBeEquivalent(old_sc
, tmp_iter
->second
))
747 old_id_vec
.push_back(tmp_iter
->first
);
750 // Now find all the equivalent locations in the new list.
751 std::vector
<lldb::break_id_t
> new_id_vec
;
752 for (tmp_iter
= new_sc_map
.begin(); tmp_iter
!= new_sc_map
.end();
754 if (SymbolContextsMightBeEquivalent(old_sc
, tmp_iter
->second
))
755 new_id_vec
.push_back(tmp_iter
->first
);
758 // Alright, if we have the same number of potentially equivalent
759 // locations in the old and new modules, we'll just map them one to
760 // one in ascending ID order (assuming the resolver's order would
761 // match the equivalent ones. Otherwise, we'll dump all the old ones,
762 // and just take the new ones, erasing the elements from both maps as
765 if (old_id_vec
.size() == new_id_vec
.size()) {
766 llvm::sort(old_id_vec
);
767 llvm::sort(new_id_vec
);
768 size_t num_elements
= old_id_vec
.size();
769 for (size_t idx
= 0; idx
< num_elements
; idx
++) {
770 BreakpointLocationSP old_loc_sp
=
771 old_break_locs
.FindByIDPair(GetID(), old_id_vec
[idx
]);
772 BreakpointLocationSP new_loc_sp
=
773 new_break_locs
.FindByIDPair(GetID(), new_id_vec
[idx
]);
774 m_locations
.SwapLocation(old_loc_sp
, new_loc_sp
);
775 old_sc_map
.erase(old_id_vec
[idx
]);
776 new_sc_map
.erase(new_id_vec
[idx
]);
779 for (lldb::break_id_t old_id
: old_id_vec
) {
780 locations_to_remove
.Add(
781 old_break_locs
.FindByIDPair(GetID(), old_id
));
782 old_sc_map
.erase(old_id
);
784 for (lldb::break_id_t new_id
: new_id_vec
) {
785 locations_to_announce
.Add(
786 new_break_locs
.FindByIDPair(GetID(), new_id
));
787 new_sc_map
.erase(new_id
);
794 // Now remove the remaining old locations, and cons up a removed locations
795 // event. Note, we don't put the new locations that were swapped with an
796 // old location on the locations_to_remove list, so we don't need to worry
797 // about telling the world about removing a location we didn't tell them
800 BreakpointEventData
*locations_event
;
802 locations_event
= new BreakpointEventData(
803 eBreakpointEventTypeLocationsRemoved
, shared_from_this());
805 locations_event
= nullptr;
807 for (BreakpointLocationSP loc_sp
:
808 locations_to_remove
.BreakpointLocations()) {
809 m_locations
.RemoveLocation(loc_sp
);
811 locations_event
->GetBreakpointLocationCollection().Add(loc_sp
);
813 SendBreakpointChangedEvent(locations_event
);
815 // And announce the new ones.
818 locations_event
= new BreakpointEventData(
819 eBreakpointEventTypeLocationsAdded
, shared_from_this());
820 for (BreakpointLocationSP loc_sp
:
821 locations_to_announce
.BreakpointLocations())
822 locations_event
->GetBreakpointLocationCollection().Add(loc_sp
);
824 SendBreakpointChangedEvent(locations_event
);
826 m_locations
.Compact();
830 void Breakpoint::Dump(Stream
*) {}
832 size_t Breakpoint::GetNumResolvedLocations() const {
833 // Return the number of breakpoints that are actually resolved and set down
834 // in the inferior process.
835 return m_locations
.GetNumResolvedLocations();
838 bool Breakpoint::HasResolvedLocations() const {
839 return GetNumResolvedLocations() > 0;
842 size_t Breakpoint::GetNumLocations() const { return m_locations
.GetSize(); }
844 bool Breakpoint::AddName(llvm::StringRef new_name
) {
845 m_name_list
.insert(new_name
.str());
849 void Breakpoint::GetDescription(Stream
*s
, lldb::DescriptionLevel level
,
850 bool show_locations
) {
851 assert(s
!= nullptr);
853 if (!m_kind_description
.empty()) {
854 if (level
== eDescriptionLevelBrief
) {
855 s
->PutCString(GetBreakpointKind());
858 s
->Printf("Kind: %s\n", GetBreakpointKind());
861 const size_t num_locations
= GetNumLocations();
862 const size_t num_resolved_locations
= GetNumResolvedLocations();
864 // They just made the breakpoint, they don't need to be told HOW they made
865 // it... Also, we'll print the breakpoint number differently depending on
866 // whether there is 1 or more locations.
867 if (level
!= eDescriptionLevelInitial
) {
868 s
->Printf("%i: ", GetID());
869 GetResolverDescription(s
);
870 GetFilterDescription(s
);
874 case lldb::eDescriptionLevelBrief
:
875 case lldb::eDescriptionLevelFull
:
876 if (num_locations
> 0) {
877 s
->Printf(", locations = %" PRIu64
, (uint64_t)num_locations
);
878 if (num_resolved_locations
> 0)
879 s
->Printf(", resolved = %" PRIu64
", hit count = %d",
880 (uint64_t)num_resolved_locations
, GetHitCount());
882 // Don't print the pending notification for exception resolvers since we
883 // don't generally know how to set them until the target is run.
884 if (m_resolver_sp
->getResolverID() !=
885 BreakpointResolver::ExceptionResolver
)
886 s
->Printf(", locations = 0 (pending)");
889 m_options
.GetDescription(s
, level
);
891 if (m_precondition_sp
)
892 m_precondition_sp
->GetDescription(*s
, level
);
894 if (level
== lldb::eDescriptionLevelFull
) {
895 if (!m_name_list
.empty()) {
901 for (std::string name
: m_name_list
) {
903 s
->Printf("%s\n", name
.c_str());
912 case lldb::eDescriptionLevelInitial
:
913 s
->Printf("Breakpoint %i: ", GetID());
914 if (num_locations
== 0) {
915 s
->Printf("no locations (pending).");
916 } else if (num_locations
== 1 && !show_locations
) {
917 // There is only one location, so we'll just print that location
919 GetLocationAtIndex(0)->GetDescription(s
, level
);
921 s
->Printf("%" PRIu64
" locations.", static_cast<uint64_t>(num_locations
));
926 case lldb::eDescriptionLevelVerbose
:
927 // Verbose mode does a debug dump of the breakpoint
931 m_options
.GetDescription(s
, level
);
938 // The brief description is just the location name (1.2 or whatever). That's
939 // pointless to show in the breakpoint's description, so suppress it.
940 if (show_locations
&& level
!= lldb::eDescriptionLevelBrief
) {
942 for (size_t i
= 0; i
< num_locations
; ++i
) {
943 BreakpointLocation
*loc
= GetLocationAtIndex(i
).get();
944 loc
->GetDescription(s
, level
);
951 void Breakpoint::GetResolverDescription(Stream
*s
) {
953 m_resolver_sp
->GetDescription(s
);
956 bool Breakpoint::GetMatchingFileLine(ConstString filename
,
957 uint32_t line_number
,
958 BreakpointLocationCollection
&loc_coll
) {
959 // TODO: To be correct, this method needs to fill the breakpoint location
961 // with the location IDs which match the filename and line_number.
965 BreakpointResolverFileLine
*resolverFileLine
=
966 dyn_cast
<BreakpointResolverFileLine
>(m_resolver_sp
.get());
968 // TODO: Handle SourceLocationSpec column information
969 if (resolverFileLine
&&
970 resolverFileLine
->m_location_spec
.GetFileSpec().GetFilename() ==
972 resolverFileLine
->m_location_spec
.GetLine() == line_number
) {
979 void Breakpoint::GetFilterDescription(Stream
*s
) {
980 m_filter_sp
->GetDescription(s
);
983 bool Breakpoint::EvaluatePrecondition(StoppointCallbackContext
&context
) {
984 if (!m_precondition_sp
)
987 return m_precondition_sp
->EvaluatePrecondition(context
);
990 void Breakpoint::SendBreakpointChangedEvent(
991 lldb::BreakpointEventType eventKind
) {
992 if (!m_being_created
&& !IsInternal() &&
993 GetTarget().EventTypeHasListeners(
994 Target::eBroadcastBitBreakpointChanged
)) {
995 BreakpointEventData
*data
=
996 new Breakpoint::BreakpointEventData(eventKind
, shared_from_this());
998 GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged
, data
);
1002 void Breakpoint::SendBreakpointChangedEvent(BreakpointEventData
*data
) {
1003 if (data
== nullptr)
1006 if (!m_being_created
&& !IsInternal() &&
1007 GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged
))
1008 GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged
, data
);
1013 const char *Breakpoint::BreakpointEventTypeAsCString(BreakpointEventType type
) {
1015 case eBreakpointEventTypeInvalidType
: return "invalid";
1016 case eBreakpointEventTypeAdded
: return "breakpoint added";
1017 case eBreakpointEventTypeRemoved
: return "breakpoint removed";
1018 case eBreakpointEventTypeLocationsAdded
: return "locations added";
1019 case eBreakpointEventTypeLocationsRemoved
: return "locations removed";
1020 case eBreakpointEventTypeLocationsResolved
: return "locations resolved";
1021 case eBreakpointEventTypeEnabled
: return "breakpoint enabled";
1022 case eBreakpointEventTypeDisabled
: return "breakpoint disabled";
1023 case eBreakpointEventTypeCommandChanged
: return "command changed";
1024 case eBreakpointEventTypeConditionChanged
: return "condition changed";
1025 case eBreakpointEventTypeIgnoreChanged
: return "ignore count changed";
1026 case eBreakpointEventTypeThreadChanged
: return "thread changed";
1027 case eBreakpointEventTypeAutoContinueChanged
: return "autocontinue changed";
1029 llvm_unreachable("Fully covered switch above!");
1032 Log
*Breakpoint::BreakpointEventData::GetLogChannel() {
1033 return GetLog(LLDBLog::Breakpoints
);
1036 Breakpoint::BreakpointEventData::BreakpointEventData(
1037 BreakpointEventType sub_type
, const BreakpointSP
&new_breakpoint_sp
)
1038 : m_breakpoint_event(sub_type
), m_new_breakpoint_sp(new_breakpoint_sp
) {}
1040 Breakpoint::BreakpointEventData::~BreakpointEventData() = default;
1042 llvm::StringRef
Breakpoint::BreakpointEventData::GetFlavorString() {
1043 return "Breakpoint::BreakpointEventData";
1046 llvm::StringRef
Breakpoint::BreakpointEventData::GetFlavor() const {
1047 return BreakpointEventData::GetFlavorString();
1050 BreakpointSP
Breakpoint::BreakpointEventData::GetBreakpoint() const {
1051 return m_new_breakpoint_sp
;
1055 Breakpoint::BreakpointEventData::GetBreakpointEventType() const {
1056 return m_breakpoint_event
;
1059 void Breakpoint::BreakpointEventData::Dump(Stream
*s
) const {
1062 BreakpointEventType event_type
= GetBreakpointEventType();
1063 break_id_t bkpt_id
= GetBreakpoint()->GetID();
1064 s
->Format("bkpt: {0} type: {1}", bkpt_id
,
1065 BreakpointEventTypeAsCString(event_type
));
1068 const Breakpoint::BreakpointEventData
*
1069 Breakpoint::BreakpointEventData::GetEventDataFromEvent(const Event
*event
) {
1071 const EventData
*event_data
= event
->GetData();
1073 event_data
->GetFlavor() == BreakpointEventData::GetFlavorString())
1074 return static_cast<const BreakpointEventData
*>(event
->GetData());
1080 Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1081 const EventSP
&event_sp
) {
1082 const BreakpointEventData
*data
= GetEventDataFromEvent(event_sp
.get());
1084 if (data
== nullptr)
1085 return eBreakpointEventTypeInvalidType
;
1087 return data
->GetBreakpointEventType();
1090 BreakpointSP
Breakpoint::BreakpointEventData::GetBreakpointFromEvent(
1091 const EventSP
&event_sp
) {
1094 const BreakpointEventData
*data
= GetEventDataFromEvent(event_sp
.get());
1096 bp_sp
= data
->m_new_breakpoint_sp
;
1101 size_t Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1102 const EventSP
&event_sp
) {
1103 const BreakpointEventData
*data
= GetEventDataFromEvent(event_sp
.get());
1105 return data
->m_locations
.GetSize();
1110 lldb::BreakpointLocationSP
1111 Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent(
1112 const lldb::EventSP
&event_sp
, uint32_t bp_loc_idx
) {
1113 lldb::BreakpointLocationSP bp_loc_sp
;
1115 const BreakpointEventData
*data
= GetEventDataFromEvent(event_sp
.get());
1117 bp_loc_sp
= data
->m_locations
.GetByIndex(bp_loc_idx
);
1123 json::Value
Breakpoint::GetStatistics() {
1125 bp
.try_emplace("id", GetID());
1126 bp
.try_emplace("resolveTime", m_resolve_time
.get().count());
1127 bp
.try_emplace("numLocations", (int64_t)GetNumLocations());
1128 bp
.try_emplace("numResolvedLocations", (int64_t)GetNumResolvedLocations());
1129 bp
.try_emplace("hitCount", (int64_t)GetHitCount());
1130 bp
.try_emplace("internal", IsInternal());
1131 if (!m_kind_description
.empty())
1132 bp
.try_emplace("kindDescription", m_kind_description
);
1133 // Put the full structured data for reproducing this breakpoint in a key/value
1134 // pair named "details". This allows the breakpoint's details to be visible
1135 // in the stats in case we need to reproduce a breakpoint that has long
1137 StructuredData::ObjectSP bp_data_sp
= SerializeToStructuredData();
1140 llvm::raw_string_ostream
ss(buffer
);
1141 json::OStream
json_os(ss
);
1142 bp_data_sp
->Serialize(json_os
);
1143 if (auto expected_value
= llvm::json::parse(ss
.str())) {
1144 bp
.try_emplace("details", std::move(*expected_value
));
1146 std::string details_error
= toString(expected_value
.takeError());
1147 json::Object details
;
1148 details
.try_emplace("error", details_error
);
1149 bp
.try_emplace("details", std::move(details
));
1152 return json::Value(std::move(bp
));