1 //===-- BreakpointSiteList.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 "lldb/Breakpoint/BreakpointSiteList.h"
11 #include "lldb/Utility/Stream.h"
15 using namespace lldb_private
;
17 BreakpointSiteList::BreakpointSiteList() = default;
19 BreakpointSiteList::~BreakpointSiteList() = default;
21 // Add breakpoint site to the list. However, if the element already exists in
22 // the list, then we don't add it, and return LLDB_INVALID_BREAK_ID.
24 lldb::break_id_t
BreakpointSiteList::Add(const BreakpointSiteSP
&bp
) {
25 lldb::addr_t bp_site_load_addr
= bp
->GetLoadAddress();
26 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
27 collection::iterator iter
= m_bp_site_list
.find(bp_site_load_addr
);
29 if (iter
== m_bp_site_list
.end()) {
30 m_bp_site_list
.insert(iter
, collection::value_type(bp_site_load_addr
, bp
));
33 return LLDB_INVALID_BREAK_ID
;
37 bool BreakpointSiteList::ShouldStop(StoppointCallbackContext
*context
,
38 lldb::break_id_t site_id
) {
39 BreakpointSiteSP
site_sp(FindByID(site_id
));
41 // Let the BreakpointSite decide if it should stop here (could not have
42 // reached it's target hit count yet, or it could have a callback that
43 // decided it shouldn't stop (shared library loads/unloads).
44 return site_sp
->ShouldStop(context
);
46 // We should stop here since this BreakpointSite isn't valid anymore or it
50 lldb::break_id_t
BreakpointSiteList::FindIDByAddress(lldb::addr_t addr
) {
51 if (BreakpointSiteSP bp
= FindByAddress(addr
))
52 return bp
.get()->GetID();
53 return LLDB_INVALID_BREAK_ID
;
56 bool BreakpointSiteList::Remove(lldb::break_id_t break_id
) {
57 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
58 collection::iterator pos
= GetIDIterator(break_id
); // Predicate
59 if (pos
!= m_bp_site_list
.end()) {
60 m_bp_site_list
.erase(pos
);
66 bool BreakpointSiteList::RemoveByAddress(lldb::addr_t address
) {
67 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
68 collection::iterator pos
= m_bp_site_list
.find(address
);
69 if (pos
!= m_bp_site_list
.end()) {
70 m_bp_site_list
.erase(pos
);
76 class BreakpointSiteIDMatches
{
78 BreakpointSiteIDMatches(lldb::break_id_t break_id
) : m_break_id(break_id
) {}
80 bool operator()(std::pair
<lldb::addr_t
, BreakpointSiteSP
> val_pair
) const {
81 return m_break_id
== val_pair
.second
->GetID();
85 const lldb::break_id_t m_break_id
;
88 BreakpointSiteList::collection::iterator
89 BreakpointSiteList::GetIDIterator(lldb::break_id_t break_id
) {
90 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
91 return std::find_if(m_bp_site_list
.begin(),
92 m_bp_site_list
.end(), // Search full range
93 BreakpointSiteIDMatches(break_id
)); // Predicate
96 BreakpointSiteList::collection::const_iterator
97 BreakpointSiteList::GetIDConstIterator(lldb::break_id_t break_id
) const {
98 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
99 return std::find_if(m_bp_site_list
.begin(),
100 m_bp_site_list
.end(), // Search full range
101 BreakpointSiteIDMatches(break_id
)); // Predicate
104 BreakpointSiteSP
BreakpointSiteList::FindByID(lldb::break_id_t break_id
) {
105 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
106 BreakpointSiteSP stop_sp
;
107 collection::iterator pos
= GetIDIterator(break_id
);
108 if (pos
!= m_bp_site_list
.end())
109 stop_sp
= pos
->second
;
114 const BreakpointSiteSP
115 BreakpointSiteList::FindByID(lldb::break_id_t break_id
) const {
116 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
117 BreakpointSiteSP stop_sp
;
118 collection::const_iterator pos
= GetIDConstIterator(break_id
);
119 if (pos
!= m_bp_site_list
.end())
120 stop_sp
= pos
->second
;
125 BreakpointSiteSP
BreakpointSiteList::FindByAddress(lldb::addr_t addr
) {
126 BreakpointSiteSP found_sp
;
127 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
128 collection::iterator iter
= m_bp_site_list
.find(addr
);
129 if (iter
!= m_bp_site_list
.end())
130 found_sp
= iter
->second
;
134 bool BreakpointSiteList::BreakpointSiteContainsBreakpoint(
135 lldb::break_id_t bp_site_id
, lldb::break_id_t bp_id
) {
136 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
137 collection::const_iterator pos
= GetIDConstIterator(bp_site_id
);
138 if (pos
!= m_bp_site_list
.end())
139 return pos
->second
->IsBreakpointAtThisSite(bp_id
);
144 void BreakpointSiteList::Dump(Stream
*s
) const {
145 s
->Printf("%p: ", static_cast<const void *>(this));
147 s
->Printf("BreakpointSiteList with %u BreakpointSites:\n",
148 (uint32_t)m_bp_site_list
.size());
150 collection::const_iterator pos
;
151 collection::const_iterator end
= m_bp_site_list
.end();
152 for (pos
= m_bp_site_list
.begin(); pos
!= end
; ++pos
)
153 pos
->second
->Dump(s
);
157 void BreakpointSiteList::ForEach(
158 std::function
<void(BreakpointSite
*)> const &callback
) {
159 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
160 for (auto pair
: m_bp_site_list
)
161 callback(pair
.second
.get());
164 bool BreakpointSiteList::FindInRange(lldb::addr_t lower_bound
,
165 lldb::addr_t upper_bound
,
166 BreakpointSiteList
&bp_site_list
) const {
167 if (lower_bound
> upper_bound
)
170 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
171 collection::const_iterator lower
, upper
, pos
;
172 lower
= m_bp_site_list
.lower_bound(lower_bound
);
173 if (lower
== m_bp_site_list
.end() || (*lower
).first
>= upper_bound
)
176 // This is one tricky bit. The breakpoint might overlap the bottom end of
177 // the range. So we grab the breakpoint prior to the lower bound, and check
178 // that that + its byte size isn't in our range.
179 if (lower
!= m_bp_site_list
.begin()) {
180 collection::const_iterator prev_pos
= lower
;
182 const BreakpointSiteSP
&prev_bp
= (*prev_pos
).second
;
183 if (prev_bp
->GetLoadAddress() + prev_bp
->GetByteSize() > lower_bound
)
184 bp_site_list
.Add(prev_bp
);
187 upper
= m_bp_site_list
.upper_bound(upper_bound
);
189 for (pos
= lower
; pos
!= upper
; pos
++) {
190 bp_site_list
.Add((*pos
).second
);