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 /// Enquires of the site on in this list with ID \a site_id
217 /// whether we should stop for the constituent or not.
218 ///
219 /// \param[in] context
220 /// This contains the information about this stop.
221 ///
222 /// \param[in] site_id
223 /// This site ID that we hit.
224 ///
225 /// \return
226 /// \b true if we should stop, \b false otherwise.
228 typename StopPointSite::SiteID site_id) {
229 if (StopPointSiteSP site_sp = FindByID(site_id)) {
230 // Let the site decide if it should stop here (could not have
231 // reached it's target hit count yet, or it could have a callback that
232 // decided it shouldn't stop (shared library loads/unloads).
233 return site_sp->ShouldStop(context);
234 }
235 // We should stop here since this site isn't valid anymore or it
236 // doesn't exist.
237 return true;
238 }
239
240 /// Returns the number of elements in the list.
241 ///
242 /// \result
243 /// The number of elements.
244 size_t GetSize() const {
245 std::lock_guard<std::recursive_mutex> guard(m_mutex);
246 return m_site_list.size();
247 }
248
249 bool IsEmpty() const {
250 std::lock_guard<std::recursive_mutex> guard(m_mutex);
251 return m_site_list.empty();
252 }
253
254 std::vector<StopPointSiteSP> Sites() {
255 std::vector<StopPointSiteSP> sites;
256 std::lock_guard<std::recursive_mutex> guard(m_mutex);
257 typename collection::iterator iter = m_site_list.begin();
258 while (iter != m_site_list.end()) {
259 sites.push_back(iter->second);
260 ++iter;
261 }
262
263 return sites;
264 }
265
266 void Clear() {
267 std::lock_guard<std::recursive_mutex> guard(m_mutex);
268 m_site_list.clear();
269 }
270
271protected:
272 typedef std::map<lldb::addr_t, StopPointSiteSP> collection;
273
274 typename collection::iterator
275 GetIDIterator(typename StopPointSite::SiteID site_id) {
276 std::lock_guard<std::recursive_mutex> guard(m_mutex);
277 auto id_matches =
278 [site_id](const std::pair<lldb::addr_t, StopPointSiteSP> s) {
279 return site_id == s.second->GetID();
280 };
281 return std::find_if(m_site_list.begin(),
282 m_site_list.end(), // Search full range
283 id_matches);
284 }
285
286 typename collection::const_iterator
287 GetIDConstIterator(typename StopPointSite::SiteID site_id) const {
288 std::lock_guard<std::recursive_mutex> guard(m_mutex);
289 auto id_matches =
290 [site_id](const std::pair<lldb::addr_t, StopPointSiteSP> s) {
291 return site_id == s.second->GetID();
292 };
293 return std::find_if(m_site_list.begin(),
294 m_site_list.end(), // Search full range
295 id_matches);
296 }
297
298 mutable std::recursive_mutex m_mutex;
299 collection m_site_list; // The site list.
300};
301
302} // namespace lldb_private
303
304#endif // LLDB_BREAKPOINT_STOPPOINTSITELIST_H
A plug-in interface definition class for debugging a process.
Definition: Process.h:343
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 ShouldStop(StoppointCallbackContext *context, typename StopPointSite::SiteID site_id)
Enquires of the site on in this list with ID site_id whether we should stop for the constituent or no...
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
General Outline: When we hit a breakpoint we need to package up whatever information is needed to eva...
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
Definition: lldb-defines.h:19
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