LLDB mainline
StopPointSiteList.h
Go to the documentation of this file.
1//===-- StopPointSiteList.h -------------------------------------*- C++ -*-===//
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#ifndef LLDB_BREAKPOINT_STOPPOINTSITELIST_H
10#define LLDB_BREAKPOINT_STOPPOINTSITELIST_H
11
12#include <functional>
13#include <map>
14#include <mutex>
15
18#include <lldb/Utility/Stream.h>
19
20namespace lldb_private {
21
22template <typename StopPointSite> class StopPointSiteList {
23 // At present Process directly accesses the map of StopPointSites so it can
24 // do quick lookups into the map (using GetMap).
25 // FIXME: Find a better interface for this.
26 friend class Process;
27
28public:
29 using StopPointSiteSP = std::shared_ptr<StopPointSite>;
30
31 /// Add a site to the list.
32 ///
33 /// \param[in] site_sp
34 /// A shared pointer to a site being added to the list.
35 ///
36 /// \return
37 /// The ID of the site in the list.
38 typename StopPointSite::SiteID Add(const StopPointSiteSP &site_sp) {
39 lldb::addr_t site_load_addr = site_sp->GetLoadAddress();
40 std::lock_guard<std::recursive_mutex> guard(m_mutex);
41 // Add site to the list. However, if the element already exists in
42 // the list, then we don't add it, and return InvalidSiteID.
43 bool inserted = m_site_list.try_emplace(site_load_addr, site_sp).second;
44 return inserted ? site_sp->GetID() : UINT32_MAX;
45 }
46
47 /// Standard Dump routine, doesn't do anything at present.
48 /// \param[in] s
49 /// Stream into which to dump the description.
50 void Dump(Stream *s) const {
51 s->Printf("%p: ", static_cast<const void *>(this));
52 s->Printf("StopPointSiteList with %u ConstituentSites:\n",
53 (uint32_t)m_site_list.size());
54 s->IndentMore();
55 typename collection::const_iterator pos;
56 typename collection::const_iterator end = m_site_list.end();
57 for (pos = m_site_list.begin(); pos != end; ++pos)
58 pos->second->Dump(s);
59 s->IndentLess();
60 }
61
62 /// Returns a shared pointer to the site at address \a addr.
63 ///
64 /// \param[in] addr
65 /// The address to look for.
66 ///
67 /// \result
68 /// A shared pointer to the site. Nullptr if no site contains
69 /// the address.
71 StopPointSiteSP found_sp;
72 std::lock_guard<std::recursive_mutex> guard(m_mutex);
73 typename collection::iterator iter = m_site_list.find(addr);
74 if (iter != m_site_list.end())
75 found_sp = iter->second;
76 return found_sp;
77 }
78
79 /// Returns a shared pointer to the site with id \a site_id.
80 ///
81 /// \param[in] site_id
82 /// The site ID to seek for.
83 ///
84 /// \result
85 /// A shared pointer to the site. Nullptr if no matching site.
86 StopPointSiteSP FindByID(typename StopPointSite::SiteID site_id) {
87 std::lock_guard<std::recursive_mutex> guard(m_mutex);
88 StopPointSiteSP stop_sp;
89 typename collection::iterator pos = GetIDIterator(site_id);
90 if (pos != m_site_list.end())
91 stop_sp = pos->second;
92
93 return stop_sp;
94 }
95
96 /// Returns a shared pointer to the site with id \a site_id -
97 /// const version.
98 ///
99 /// \param[in] site_id
100 /// The site ID to seek for.
101 ///
102 /// \result
103 /// A shared pointer to the site. Nullptr if no matching site.
104 const StopPointSiteSP FindByID(typename StopPointSite::SiteID site_id) const {
105 std::lock_guard<std::recursive_mutex> guard(m_mutex);
106 StopPointSiteSP stop_sp;
107 typename collection::const_iterator pos = GetIDConstIterator(site_id);
108 if (pos != m_site_list.end())
109 stop_sp = pos->second;
110
111 return stop_sp;
112 }
113
114 /// Returns the site id to the site at address \a addr.
115 ///
116 /// \param[in] addr
117 /// The address to match.
118 ///
119 /// \result
120 /// The ID of the site, or LLDB_INVALID_SITE_ID.
121 typename StopPointSite::SiteID FindIDByAddress(lldb::addr_t addr) {
122 if (StopPointSiteSP site = FindByAddress(addr))
123 return site->GetID();
124 return UINT32_MAX;
125 }
126
127 /// Returns whether the BreakpointSite \a site_id has a BreakpointLocation
128 /// that is part of Breakpoint \a bp_id.
129 ///
130 /// NB this is only defined when StopPointSiteList is specialized for
131 /// BreakpointSite's.
132 ///
133 /// \param[in] site_id
134 /// The site id to query.
135 ///
136 /// \param[in] bp_id
137 /// The breakpoint id to look for in \a site_id's BreakpointLocations.
138 ///
139 /// \result
140 /// True if \a site_id exists in the site list AND \a bp_id
141 /// is the breakpoint for one of the BreakpointLocations.
142 bool StopPointSiteContainsBreakpoint(typename StopPointSite::SiteID,
143 lldb::break_id_t bp_id);
144
145 void ForEach(std::function<void(StopPointSite *)> const &callback) {
146 std::lock_guard<std::recursive_mutex> guard(m_mutex);
147 for (auto pair : m_site_list)
148 callback(pair.second.get());
149 }
150
151 /// Removes the site given by \a site_id from this list.
152 ///
153 /// \param[in] site_id
154 /// The site ID to remove.
155 ///
156 /// \result
157 /// \b true if the site \a site_id was in the list.
158 bool Remove(typename StopPointSite::SiteID site_id) {
159 std::lock_guard<std::recursive_mutex> guard(m_mutex);
160 typename collection::iterator pos = GetIDIterator(site_id); // Predicate
161 if (pos != m_site_list.end()) {
162 m_site_list.erase(pos);
163 return true;
164 }
165 return false;
166 }
167
168 /// Removes the site at address \a addr from this list.
169 ///
170 /// \param[in] addr
171 /// The address from which to remove a site.
172 ///
173 /// \result
174 /// \b true if \a addr had a site to remove from the list.
176 std::lock_guard<std::recursive_mutex> guard(m_mutex);
177 typename collection::iterator pos = m_site_list.find(addr);
178 if (pos != m_site_list.end()) {
179 m_site_list.erase(pos);
180 return true;
181 }
182 return false;
183 }
184
185 bool FindInRange(lldb::addr_t lower_bound, lldb::addr_t upper_bound,
186 StopPointSiteList &bp_site_list) const {
187 if (lower_bound > upper_bound)
188 return false;
189
190 std::lock_guard<std::recursive_mutex> guard(m_mutex);
191 typename collection::const_iterator lower, upper, pos;
192 lower = m_site_list.lower_bound(lower_bound);
193 if (lower == m_site_list.end() || (*lower).first >= upper_bound)
194 return false;
195
196 // This is one tricky bit. The site might overlap the bottom end of
197 // the range. So we grab the site prior to the lower bound, and check
198 // that that + its byte size isn't in our range.
199 if (lower != m_site_list.begin()) {
200 typename collection::const_iterator prev_pos = lower;
201 prev_pos--;
202 const StopPointSiteSP &prev_site = (*prev_pos).second;
203 if (prev_site->GetLoadAddress() + prev_site->GetByteSize() > lower_bound)
204 bp_site_list.Add(prev_site);
205 }
206
207 upper = m_site_list.upper_bound(upper_bound);
208
209 for (pos = lower; pos != upper; pos++)
210 bp_site_list.Add((*pos).second);
211 return true;
212 }
213
214 typedef void (*StopPointSiteSPMapFunc)(StopPointSite &site, void *baton);
215
216 /// Returns the number of elements in the list.
217 ///
218 /// \result
219 /// The number of elements.
220 size_t GetSize() const {
221 std::lock_guard<std::recursive_mutex> guard(m_mutex);
222 return m_site_list.size();
223 }
224
225 bool IsEmpty() const {
226 std::lock_guard<std::recursive_mutex> guard(m_mutex);
227 return m_site_list.empty();
228 }
229
230 std::vector<StopPointSiteSP> Sites() {
231 std::vector<StopPointSiteSP> sites;
232 std::lock_guard<std::recursive_mutex> guard(m_mutex);
233 typename collection::iterator iter = m_site_list.begin();
234 while (iter != m_site_list.end()) {
235 sites.push_back(iter->second);
236 ++iter;
237 }
238
239 return sites;
240 }
241
242 void Clear() {
243 std::lock_guard<std::recursive_mutex> guard(m_mutex);
244 m_site_list.clear();
245 }
246
247protected:
248 typedef std::map<lldb::addr_t, StopPointSiteSP> collection;
249
250 typename collection::iterator
251 GetIDIterator(typename StopPointSite::SiteID site_id) {
252 std::lock_guard<std::recursive_mutex> guard(m_mutex);
253 auto id_matches =
254 [site_id](const std::pair<lldb::addr_t, StopPointSiteSP> s) {
255 return site_id == s.second->GetID();
256 };
257 return llvm::find_if(m_site_list, // Search full range
258 id_matches);
259 }
260
261 typename collection::const_iterator
262 GetIDConstIterator(typename StopPointSite::SiteID site_id) const {
263 std::lock_guard<std::recursive_mutex> guard(m_mutex);
264 auto id_matches =
265 [site_id](const std::pair<lldb::addr_t, StopPointSiteSP> s) {
266 return site_id == s.second->GetID();
267 };
268 return llvm::find_if(m_site_list, // Search full range
269 id_matches);
270 }
271
272 mutable std::recursive_mutex m_mutex;
273 collection m_site_list; // The site list.
274};
275
276} // namespace lldb_private
277
278#endif // LLDB_BREAKPOINT_STOPPOINTSITELIST_H
collection::const_iterator GetIDConstIterator(typename StopPointSite::SiteID site_id) const
void Dump(Stream *s) const
Standard Dump routine, doesn't do anything at present.
StopPointSite::SiteID Add(const StopPointSiteSP &site_sp)
Add a site to the list.
void ForEach(std::function< void(StopPointSite *)> const &callback)
bool FindInRange(lldb::addr_t lower_bound, lldb::addr_t upper_bound, StopPointSiteList &bp_site_list) const
StopPointSiteSP FindByID(typename StopPointSite::SiteID site_id)
Returns a shared pointer to the site with id site_id.
void(* StopPointSiteSPMapFunc)(StopPointSite &site, void *baton)
bool Remove(typename StopPointSite::SiteID site_id)
Removes the site given by site_id from this list.
StopPointSiteSP FindByAddress(lldb::addr_t addr)
Returns a shared pointer to the site at address addr.
collection::iterator GetIDIterator(typename StopPointSite::SiteID site_id)
std::vector< StopPointSiteSP > Sites()
const StopPointSiteSP FindByID(typename StopPointSite::SiteID site_id) const
Returns a shared pointer to the site with id site_id - const version.
bool RemoveByAddress(lldb::addr_t addr)
Removes the site at address addr from this list.
bool StopPointSiteContainsBreakpoint(typename StopPointSite::SiteID, lldb::break_id_t bp_id)
Returns whether the BreakpointSite site_id has a BreakpointLocation that is part of Breakpoint bp_id.
StopPointSite::SiteID FindIDByAddress(lldb::addr_t addr)
Returns the site id to the site at address addr.
size_t GetSize() const
Returns the number of elements in the list.
std::map< lldb::addr_t, StopPointSiteSP > collection
std::shared_ptr< StopPointSite > StopPointSiteSP
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition Stream.cpp:198
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition Stream.cpp:195
#define UINT32_MAX
A class that represents a running process on the host machine.
int32_t break_id_t
Definition lldb-types.h:86
uint64_t addr_t
Definition lldb-types.h:80