]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Breakpoint/WatchpointList.cpp
Merge ACPICA 20170929 (take 2).
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Breakpoint / WatchpointList.cpp
1 //===-- WatchpointList.cpp --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Breakpoint/WatchpointList.h"
15 #include "lldb/Breakpoint/Watchpoint.h"
16
17 using namespace lldb;
18 using namespace lldb_private;
19
20 WatchpointList::WatchpointList()
21     : m_watchpoints(), m_mutex(), m_next_wp_id(0) {}
22
23 WatchpointList::~WatchpointList() {}
24
25 // Add a watchpoint to the list.
26 lldb::watch_id_t WatchpointList::Add(const WatchpointSP &wp_sp, bool notify) {
27   std::lock_guard<std::recursive_mutex> guard(m_mutex);
28   wp_sp->SetID(++m_next_wp_id);
29   m_watchpoints.push_back(wp_sp);
30   if (notify) {
31     if (wp_sp->GetTarget().EventTypeHasListeners(
32             Target::eBroadcastBitWatchpointChanged))
33       wp_sp->GetTarget().BroadcastEvent(Target::eBroadcastBitWatchpointChanged,
34                                         new Watchpoint::WatchpointEventData(
35                                             eWatchpointEventTypeAdded, wp_sp));
36   }
37   return wp_sp->GetID();
38 }
39
40 void WatchpointList::Dump(Stream *s) const {
41   DumpWithLevel(s, lldb::eDescriptionLevelBrief);
42 }
43
44 void WatchpointList::DumpWithLevel(
45     Stream *s, lldb::DescriptionLevel description_level) const {
46   std::lock_guard<std::recursive_mutex> guard(m_mutex);
47   s->Printf("%p: ", static_cast<const void *>(this));
48   // s->Indent();
49   s->Printf("WatchpointList with %" PRIu64 " Watchpoints:\n",
50             (uint64_t)m_watchpoints.size());
51   s->IndentMore();
52   wp_collection::const_iterator pos, end = m_watchpoints.end();
53   for (pos = m_watchpoints.begin(); pos != end; ++pos)
54     (*pos)->DumpWithLevel(s, description_level);
55   s->IndentLess();
56 }
57
58 const WatchpointSP WatchpointList::FindByAddress(lldb::addr_t addr) const {
59   WatchpointSP wp_sp;
60   std::lock_guard<std::recursive_mutex> guard(m_mutex);
61   if (!m_watchpoints.empty()) {
62     wp_collection::const_iterator pos, end = m_watchpoints.end();
63     for (pos = m_watchpoints.begin(); pos != end; ++pos) {
64       lldb::addr_t wp_addr = (*pos)->GetLoadAddress();
65       uint32_t wp_bytesize = (*pos)->GetByteSize();
66       if ((wp_addr <= addr) && ((wp_addr + wp_bytesize) > addr)) {
67         wp_sp = *pos;
68         break;
69       }
70     }
71   }
72
73   return wp_sp;
74 }
75
76 const WatchpointSP WatchpointList::FindBySpec(std::string spec) const {
77   WatchpointSP wp_sp;
78   std::lock_guard<std::recursive_mutex> guard(m_mutex);
79   if (!m_watchpoints.empty()) {
80     wp_collection::const_iterator pos, end = m_watchpoints.end();
81     for (pos = m_watchpoints.begin(); pos != end; ++pos)
82       if ((*pos)->GetWatchSpec() == spec) {
83         wp_sp = *pos;
84         break;
85       }
86   }
87
88   return wp_sp;
89 }
90
91 class WatchpointIDMatches {
92 public:
93   WatchpointIDMatches(lldb::watch_id_t watch_id) : m_watch_id(watch_id) {}
94
95   bool operator()(const WatchpointSP &wp) const {
96     return m_watch_id == wp->GetID();
97   }
98
99 private:
100   const lldb::watch_id_t m_watch_id;
101 };
102
103 WatchpointList::wp_collection::iterator
104 WatchpointList::GetIDIterator(lldb::watch_id_t watch_id) {
105   return std::find_if(m_watchpoints.begin(),
106                       m_watchpoints.end(),            // Search full range
107                       WatchpointIDMatches(watch_id)); // Predicate
108 }
109
110 WatchpointList::wp_collection::const_iterator
111 WatchpointList::GetIDConstIterator(lldb::watch_id_t watch_id) const {
112   return std::find_if(m_watchpoints.begin(),
113                       m_watchpoints.end(),            // Search full range
114                       WatchpointIDMatches(watch_id)); // Predicate
115 }
116
117 WatchpointSP WatchpointList::FindByID(lldb::watch_id_t watch_id) const {
118   WatchpointSP wp_sp;
119   std::lock_guard<std::recursive_mutex> guard(m_mutex);
120   wp_collection::const_iterator pos = GetIDConstIterator(watch_id);
121   if (pos != m_watchpoints.end())
122     wp_sp = *pos;
123
124   return wp_sp;
125 }
126
127 lldb::watch_id_t WatchpointList::FindIDByAddress(lldb::addr_t addr) {
128   WatchpointSP wp_sp = FindByAddress(addr);
129   if (wp_sp) {
130     return wp_sp->GetID();
131   }
132   return LLDB_INVALID_WATCH_ID;
133 }
134
135 lldb::watch_id_t WatchpointList::FindIDBySpec(std::string spec) {
136   WatchpointSP wp_sp = FindBySpec(spec);
137   if (wp_sp) {
138     return wp_sp->GetID();
139   }
140   return LLDB_INVALID_WATCH_ID;
141 }
142
143 WatchpointSP WatchpointList::GetByIndex(uint32_t i) {
144   std::lock_guard<std::recursive_mutex> guard(m_mutex);
145   WatchpointSP wp_sp;
146   if (i < m_watchpoints.size()) {
147     wp_collection::const_iterator pos = m_watchpoints.begin();
148     std::advance(pos, i);
149     wp_sp = *pos;
150   }
151   return wp_sp;
152 }
153
154 const WatchpointSP WatchpointList::GetByIndex(uint32_t i) const {
155   std::lock_guard<std::recursive_mutex> guard(m_mutex);
156   WatchpointSP wp_sp;
157   if (i < m_watchpoints.size()) {
158     wp_collection::const_iterator pos = m_watchpoints.begin();
159     std::advance(pos, i);
160     wp_sp = *pos;
161   }
162   return wp_sp;
163 }
164
165 std::vector<lldb::watch_id_t> WatchpointList::GetWatchpointIDs() const {
166   std::vector<lldb::watch_id_t> IDs;
167   wp_collection::const_iterator pos, end = m_watchpoints.end();
168   for (pos = m_watchpoints.begin(); pos != end; ++pos)
169     IDs.push_back((*pos)->GetID());
170   return IDs;
171 }
172
173 bool WatchpointList::Remove(lldb::watch_id_t watch_id, bool notify) {
174   std::lock_guard<std::recursive_mutex> guard(m_mutex);
175   wp_collection::iterator pos = GetIDIterator(watch_id);
176   if (pos != m_watchpoints.end()) {
177     WatchpointSP wp_sp = *pos;
178     if (notify) {
179       if (wp_sp->GetTarget().EventTypeHasListeners(
180               Target::eBroadcastBitWatchpointChanged))
181         wp_sp->GetTarget().BroadcastEvent(
182             Target::eBroadcastBitWatchpointChanged,
183             new Watchpoint::WatchpointEventData(eWatchpointEventTypeRemoved,
184                                                 wp_sp));
185     }
186     m_watchpoints.erase(pos);
187     return true;
188   }
189   return false;
190 }
191
192 uint32_t WatchpointList::GetHitCount() const {
193   uint32_t hit_count = 0;
194   std::lock_guard<std::recursive_mutex> guard(m_mutex);
195   wp_collection::const_iterator pos, end = m_watchpoints.end();
196   for (pos = m_watchpoints.begin(); pos != end; ++pos)
197     hit_count += (*pos)->GetHitCount();
198   return hit_count;
199 }
200
201 bool WatchpointList::ShouldStop(StoppointCallbackContext *context,
202                                 lldb::watch_id_t watch_id) {
203
204   WatchpointSP wp_sp = FindByID(watch_id);
205   if (wp_sp) {
206     // Let the Watchpoint decide if it should stop here (could not have
207     // reached it's target hit count yet, or it could have a callback
208     // that decided it shouldn't stop.
209     return wp_sp->ShouldStop(context);
210   }
211   // We should stop here since this Watchpoint isn't valid anymore or it
212   // doesn't exist.
213   return true;
214 }
215
216 void WatchpointList::GetDescription(Stream *s, lldb::DescriptionLevel level) {
217   std::lock_guard<std::recursive_mutex> guard(m_mutex);
218   wp_collection::iterator pos, end = m_watchpoints.end();
219
220   for (pos = m_watchpoints.begin(); pos != end; ++pos) {
221     s->Printf(" ");
222     (*pos)->Dump(s);
223   }
224 }
225
226 void WatchpointList::SetEnabledAll(bool enabled) {
227   std::lock_guard<std::recursive_mutex> guard(m_mutex);
228
229   wp_collection::iterator pos, end = m_watchpoints.end();
230   for (pos = m_watchpoints.begin(); pos != end; ++pos)
231     (*pos)->SetEnabled(enabled);
232 }
233
234 void WatchpointList::RemoveAll(bool notify) {
235   std::lock_guard<std::recursive_mutex> guard(m_mutex);
236   if (notify) {
237
238     {
239       wp_collection::iterator pos, end = m_watchpoints.end();
240       for (pos = m_watchpoints.begin(); pos != end; ++pos) {
241         if ((*pos)->GetTarget().EventTypeHasListeners(
242                 Target::eBroadcastBitBreakpointChanged)) {
243           (*pos)->GetTarget().BroadcastEvent(
244               Target::eBroadcastBitWatchpointChanged,
245               new Watchpoint::WatchpointEventData(eWatchpointEventTypeRemoved,
246                                                   *pos));
247         }
248       }
249     }
250   }
251   m_watchpoints.clear();
252 }
253
254 void WatchpointList::GetListMutex(
255     std::unique_lock<std::recursive_mutex> &lock) {
256   lock = std::unique_lock<std::recursive_mutex>(m_mutex);
257 }