1 //===-- WatchpointList.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_WATCHPOINTLIST_H
10 #define LLDB_BREAKPOINT_WATCHPOINTLIST_H
11 
12 #include <list>
13 #include <mutex>
14 #include <vector>
15 
16 #include "lldb/Core/Address.h"
17 #include "lldb/Utility/Iterable.h"
18 #include "lldb/lldb-private.h"
19 
20 namespace lldb_private {
21 
22 /// \class WatchpointList WatchpointList.h "lldb/Breakpoint/WatchpointList.h"
23 /// This class is used by Watchpoint to manage a list of watchpoints,
24 //  each watchpoint in the list has a unique ID, and is unique by Address as
25 //  well.
26 
27 class WatchpointList {
28   // Only Target can make the watchpoint list, or add elements to it. This is
29   // not just some random collection of watchpoints.  Rather, the act of adding
30   // the watchpoint to this list sets its ID.
31   friend class Watchpoint;
32   friend class Target;
33 
34 public:
35   /// Default constructor makes an empty list.
36   WatchpointList();
37 
38   /// Destructor, currently does nothing.
39   ~WatchpointList();
40 
41   typedef std::list<lldb::WatchpointSP> wp_collection;
42   typedef LockingAdaptedIterable<wp_collection, lldb::WatchpointSP,
43                                  vector_adapter, std::recursive_mutex>
44       WatchpointIterable;
45 
46   /// Add a Watchpoint to the list.
47   ///
48   /// \param[in] wp_sp
49   ///    A shared pointer to a watchpoint being added to the list.
50   ///
51   /// \return
52   ///    The ID of the Watchpoint in the list.
53   lldb::watch_id_t Add(const lldb::WatchpointSP &wp_sp, bool notify);
54 
55   /// Standard "Dump" method.
56   void Dump(Stream *s) const;
57 
58   /// Dump with lldb::DescriptionLevel.
59   void DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const;
60 
61   /// Returns a shared pointer to the watchpoint at address \a addr - const
62   /// version.
63   ///
64   /// \param[in] addr
65   ///     The address to look for.
66   ///
67   /// \result
68   ///     A shared pointer to the watchpoint.  May contain a NULL
69   ///     pointer if the watchpoint doesn't exist.
70   const lldb::WatchpointSP FindByAddress(lldb::addr_t addr) const;
71 
72   /// Returns a shared pointer to the watchpoint with watchpoint spec \a spec
73   /// - const version.
74   ///
75   /// \param[in] spec
76   ///     The watchpoint spec to look for.
77   ///
78   /// \result
79   ///     A shared pointer to the watchpoint.  May contain a NULL
80   ///     pointer if the watchpoint doesn't exist.
81   const lldb::WatchpointSP FindBySpec(std::string spec) const;
82 
83   /// Returns a shared pointer to the watchpoint with id \a watchID, const
84   /// version.
85   ///
86   /// \param[in] watchID
87   ///     The watchpoint location ID to seek for.
88   ///
89   /// \result
90   ///     A shared pointer to the watchpoint.  May contain a NULL
91   ///     pointer if the watchpoint doesn't exist.
92   lldb::WatchpointSP FindByID(lldb::watch_id_t watchID) const;
93 
94   /// Returns the watchpoint id to the watchpoint at address \a addr.
95   ///
96   /// \param[in] addr
97   ///     The address to match.
98   ///
99   /// \result
100   ///     The ID of the watchpoint, or LLDB_INVALID_WATCH_ID.
101   lldb::watch_id_t FindIDByAddress(lldb::addr_t addr);
102 
103   /// Returns the watchpoint id to the watchpoint with watchpoint spec \a
104   /// spec.
105   ///
106   /// \param[in] spec
107   ///     The watchpoint spec to match.
108   ///
109   /// \result
110   ///     The ID of the watchpoint, or LLDB_INVALID_WATCH_ID.
111   lldb::watch_id_t FindIDBySpec(std::string spec);
112 
113   /// Returns a shared pointer to the watchpoint with index \a i.
114   ///
115   /// \param[in] i
116   ///     The watchpoint index to seek for.
117   ///
118   /// \result
119   ///     A shared pointer to the watchpoint.  May contain a NULL pointer if
120   ///     the watchpoint doesn't exist.
121   lldb::WatchpointSP GetByIndex(uint32_t i);
122 
123   /// Returns a shared pointer to the watchpoint with index \a i, const
124   /// version.
125   ///
126   /// \param[in] i
127   ///     The watchpoint index to seek for.
128   ///
129   /// \result
130   ///     A shared pointer to the watchpoint.  May contain a NULL pointer if
131   ///     the watchpoint location doesn't exist.
132   const lldb::WatchpointSP GetByIndex(uint32_t i) const;
133 
134   /// Removes the watchpoint given by \b watchID from this list.
135   ///
136   /// \param[in] watchID
137   ///   The watchpoint ID to remove.
138   ///
139   /// \result
140   ///   \b true if the watchpoint \a watchID was in the list.
141   bool Remove(lldb::watch_id_t watchID, bool notify);
142 
143   /// Returns the number hit count of all watchpoints in this list.
144   ///
145   /// \result
146   ///     Hit count of all watchpoints in this list.
147   uint32_t GetHitCount() const;
148 
149   /// Enquires of the watchpoint in this list with ID \a watchID whether we
150   /// should stop.
151   ///
152   /// \param[in] context
153   ///     This contains the information about this stop.
154   ///
155   /// \param[in] watchID
156   ///     This watch ID that we hit.
157   ///
158   /// \return
159   ///     \b true if we should stop, \b false otherwise.
160   bool ShouldStop(StoppointCallbackContext *context, lldb::watch_id_t watchID);
161 
162   /// Returns the number of elements in this watchpoint list.
163   ///
164   /// \result
165   ///     The number of elements.
166   size_t GetSize() const {
167     std::lock_guard<std::recursive_mutex> guard(m_mutex);
168     return m_watchpoints.size();
169   }
170 
171   /// Print a description of the watchpoints in this list to the stream \a s.
172   ///
173   /// \param[in] s
174   ///     The stream to which to print the description.
175   ///
176   /// \param[in] level
177   ///     The description level that indicates the detail level to
178   ///     provide.
179   ///
180   /// \see lldb::DescriptionLevel
181   void GetDescription(Stream *s, lldb::DescriptionLevel level);
182 
183   void SetEnabledAll(bool enabled);
184 
185   void RemoveAll(bool notify);
186 
187   /// Sets the passed in Locker to hold the Watchpoint List mutex.
188   ///
189   /// \param[in] lock
190   ///   The locker object that is set.
191   void GetListMutex(std::unique_lock<std::recursive_mutex> &lock);
192 
193   WatchpointIterable Watchpoints() const {
194     return WatchpointIterable(m_watchpoints, m_mutex);
195   }
196 
197 protected:
198   typedef std::vector<lldb::watch_id_t> id_vector;
199 
200   id_vector GetWatchpointIDs() const;
201 
202   wp_collection::iterator GetIDIterator(lldb::watch_id_t watchID);
203 
204   wp_collection::const_iterator
205   GetIDConstIterator(lldb::watch_id_t watchID) const;
206 
207   wp_collection m_watchpoints;
208   mutable std::recursive_mutex m_mutex;
209 
210   lldb::watch_id_t m_next_wp_id = 0;
211 };
212 
213 } // namespace lldb_private
214 
215 #endif // LLDB_BREAKPOINT_WATCHPOINTLIST_H
216