LLDB  mainline
WatchpointList.cpp
Go to the documentation of this file.
1 //===-- WatchpointList.cpp --------------------------------------*- 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 
11 
12 using namespace lldb;
13 using namespace lldb_private;
14 
15 WatchpointList::WatchpointList()
16  : m_watchpoints(), m_mutex(), m_next_wp_id(0) {}
17 
19 
20 // Add a watchpoint to the list.
21 lldb::watch_id_t WatchpointList::Add(const WatchpointSP &wp_sp, bool notify) {
22  std::lock_guard<std::recursive_mutex> guard(m_mutex);
23  wp_sp->SetID(++m_next_wp_id);
24  m_watchpoints.push_back(wp_sp);
25  if (notify) {
26  if (wp_sp->GetTarget().EventTypeHasListeners(
28  wp_sp->GetTarget().BroadcastEvent(Target::eBroadcastBitWatchpointChanged,
30  eWatchpointEventTypeAdded, wp_sp));
31  }
32  return wp_sp->GetID();
33 }
34 
35 void WatchpointList::Dump(Stream *s) const {
37 }
38 
40  Stream *s, lldb::DescriptionLevel description_level) const {
41  std::lock_guard<std::recursive_mutex> guard(m_mutex);
42  s->Printf("%p: ", static_cast<const void *>(this));
43  // s->Indent();
44  s->Printf("WatchpointList with %" PRIu64 " Watchpoints:\n",
45  (uint64_t)m_watchpoints.size());
46  s->IndentMore();
47  wp_collection::const_iterator pos, end = m_watchpoints.end();
48  for (pos = m_watchpoints.begin(); pos != end; ++pos)
49  (*pos)->DumpWithLevel(s, description_level);
50  s->IndentLess();
51 }
52 
53 const WatchpointSP WatchpointList::FindByAddress(lldb::addr_t addr) const {
54  WatchpointSP wp_sp;
55  std::lock_guard<std::recursive_mutex> guard(m_mutex);
56  if (!m_watchpoints.empty()) {
57  wp_collection::const_iterator pos, end = m_watchpoints.end();
58  for (pos = m_watchpoints.begin(); pos != end; ++pos) {
59  lldb::addr_t wp_addr = (*pos)->GetLoadAddress();
60  uint32_t wp_bytesize = (*pos)->GetByteSize();
61  if ((wp_addr <= addr) && ((wp_addr + wp_bytesize) > addr)) {
62  wp_sp = *pos;
63  break;
64  }
65  }
66  }
67 
68  return wp_sp;
69 }
70 
71 const WatchpointSP WatchpointList::FindBySpec(std::string spec) const {
72  WatchpointSP wp_sp;
73  std::lock_guard<std::recursive_mutex> guard(m_mutex);
74  if (!m_watchpoints.empty()) {
75  wp_collection::const_iterator pos, end = m_watchpoints.end();
76  for (pos = m_watchpoints.begin(); pos != end; ++pos)
77  if ((*pos)->GetWatchSpec() == spec) {
78  wp_sp = *pos;
79  break;
80  }
81  }
82 
83  return wp_sp;
84 }
85 
87 public:
88  WatchpointIDMatches(lldb::watch_id_t watch_id) : m_watch_id(watch_id) {}
89 
90  bool operator()(const WatchpointSP &wp) const {
91  return m_watch_id == wp->GetID();
92  }
93 
94 private:
95  const lldb::watch_id_t m_watch_id;
96 };
97 
98 WatchpointList::wp_collection::iterator
100  return std::find_if(m_watchpoints.begin(),
101  m_watchpoints.end(), // Search full range
102  WatchpointIDMatches(watch_id)); // Predicate
103 }
104 
105 WatchpointList::wp_collection::const_iterator
107  return std::find_if(m_watchpoints.begin(),
108  m_watchpoints.end(), // Search full range
109  WatchpointIDMatches(watch_id)); // Predicate
110 }
111 
112 WatchpointSP WatchpointList::FindByID(lldb::watch_id_t watch_id) const {
113  WatchpointSP wp_sp;
114  std::lock_guard<std::recursive_mutex> guard(m_mutex);
115  wp_collection::const_iterator pos = GetIDConstIterator(watch_id);
116  if (pos != m_watchpoints.end())
117  wp_sp = *pos;
118 
119  return wp_sp;
120 }
121 
123  WatchpointSP wp_sp = FindByAddress(addr);
124  if (wp_sp) {
125  return wp_sp->GetID();
126  }
127  return LLDB_INVALID_WATCH_ID;
128 }
129 
131  WatchpointSP wp_sp = FindBySpec(spec);
132  if (wp_sp) {
133  return wp_sp->GetID();
134  }
135  return LLDB_INVALID_WATCH_ID;
136 }
137 
139  std::lock_guard<std::recursive_mutex> guard(m_mutex);
140  WatchpointSP wp_sp;
141  if (i < m_watchpoints.size()) {
142  wp_collection::const_iterator pos = m_watchpoints.begin();
143  std::advance(pos, i);
144  wp_sp = *pos;
145  }
146  return wp_sp;
147 }
148 
149 const WatchpointSP WatchpointList::GetByIndex(uint32_t i) const {
150  std::lock_guard<std::recursive_mutex> guard(m_mutex);
151  WatchpointSP wp_sp;
152  if (i < m_watchpoints.size()) {
153  wp_collection::const_iterator pos = m_watchpoints.begin();
154  std::advance(pos, i);
155  wp_sp = *pos;
156  }
157  return wp_sp;
158 }
159 
160 std::vector<lldb::watch_id_t> WatchpointList::GetWatchpointIDs() const {
161  std::vector<lldb::watch_id_t> IDs;
162  wp_collection::const_iterator pos, end = m_watchpoints.end();
163  for (pos = m_watchpoints.begin(); pos != end; ++pos)
164  IDs.push_back((*pos)->GetID());
165  return IDs;
166 }
167 
168 bool WatchpointList::Remove(lldb::watch_id_t watch_id, bool notify) {
169  std::lock_guard<std::recursive_mutex> guard(m_mutex);
170  wp_collection::iterator pos = GetIDIterator(watch_id);
171  if (pos != m_watchpoints.end()) {
172  WatchpointSP wp_sp = *pos;
173  if (notify) {
174  if (wp_sp->GetTarget().EventTypeHasListeners(
176  wp_sp->GetTarget().BroadcastEvent(
178  new Watchpoint::WatchpointEventData(eWatchpointEventTypeRemoved,
179  wp_sp));
180  }
181  m_watchpoints.erase(pos);
182  return true;
183  }
184  return false;
185 }
186 
188  uint32_t hit_count = 0;
189  std::lock_guard<std::recursive_mutex> guard(m_mutex);
190  wp_collection::const_iterator pos, end = m_watchpoints.end();
191  for (pos = m_watchpoints.begin(); pos != end; ++pos)
192  hit_count += (*pos)->GetHitCount();
193  return hit_count;
194 }
195 
197  lldb::watch_id_t watch_id) {
198 
199  WatchpointSP wp_sp = FindByID(watch_id);
200  if (wp_sp) {
201  // Let the Watchpoint decide if it should stop here (could not have reached
202  // it's target hit count yet, or it could have a callback that decided it
203  // shouldn't stop.
204  return wp_sp->ShouldStop(context);
205  }
206  // We should stop here since this Watchpoint isn't valid anymore or it
207  // doesn't exist.
208  return true;
209 }
210 
212  std::lock_guard<std::recursive_mutex> guard(m_mutex);
213  wp_collection::iterator pos, end = m_watchpoints.end();
214 
215  for (pos = m_watchpoints.begin(); pos != end; ++pos) {
216  s->Printf(" ");
217  (*pos)->Dump(s);
218  }
219 }
220 
221 void WatchpointList::SetEnabledAll(bool enabled) {
222  std::lock_guard<std::recursive_mutex> guard(m_mutex);
223 
224  wp_collection::iterator pos, end = m_watchpoints.end();
225  for (pos = m_watchpoints.begin(); pos != end; ++pos)
226  (*pos)->SetEnabled(enabled);
227 }
228 
229 void WatchpointList::RemoveAll(bool notify) {
230  std::lock_guard<std::recursive_mutex> guard(m_mutex);
231  if (notify) {
232 
233  {
234  wp_collection::iterator pos, end = m_watchpoints.end();
235  for (pos = m_watchpoints.begin(); pos != end; ++pos) {
236  if ((*pos)->GetTarget().EventTypeHasListeners(
238  (*pos)->GetTarget().BroadcastEvent(
240  new Watchpoint::WatchpointEventData(eWatchpointEventTypeRemoved,
241  *pos));
242  }
243  }
244  }
245  }
246  m_watchpoints.clear();
247 }
248 
250  std::unique_lock<std::recursive_mutex> &lock) {
251  lock = std::unique_lock<std::recursive_mutex>(m_mutex);
252 }
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
void GetDescription(Stream *s, lldb::DescriptionLevel level)
Print a description of the watchpoints in this list to the stream s.
id_vector GetWatchpointIDs() const
lldb::WatchpointSP FindByID(lldb::watch_id_t watchID) const
Returns a shared pointer to the watchpoint with id watchID, const version.
int32_t watch_id_t
Definition: lldb-types.h:89
lldb::watch_id_t FindIDByAddress(lldb::addr_t addr)
Returns the watchpoint id to the watchpoint at address addr.
std::recursive_mutex m_mutex
const lldb::WatchpointSP FindByAddress(lldb::addr_t addr) const
Returns a shared pointer to the watchpoint at address addr - const version.
~WatchpointList()
Destructor, currently does nothing.
lldb::watch_id_t FindIDBySpec(std::string spec)
Returns the watchpoint id to the watchpoint with watchpoint spec spec.
void IndentLess(int amount=2)
Decrement the current indentation level.
Definition: Stream.cpp:221
lldb::watch_id_t Add(const lldb::WatchpointSP &wp_sp, bool notify)
Add a Watchpoint to the list.
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
void GetListMutex(std::unique_lock< std::recursive_mutex > &lock)
Sets the passed in Locker to hold the Watchpoint List mutex.
void Dump(Stream *s) const
Standard "Dump" method.
WatchpointIDMatches(lldb::watch_id_t watch_id)
void SetEnabledAll(bool enabled)
uint32_t GetHitCount() const
Returns the number hit count of all watchpoints in this list.
uint64_t addr_t
Definition: lldb-types.h:83
#define LLDB_INVALID_WATCH_ID
Definition: lldb-defines.h:55
Definition: SBAddress.h:15
bool ShouldStop(StoppointCallbackContext *context, lldb::watch_id_t watchID)
Enquires of the watchpoint in this list with ID watchID whether we should stop.
lldb::WatchpointSP GetByIndex(uint32_t i)
Returns a shared pointer to the watchpoint with index i.
bool operator()(const WatchpointSP &wp) const
General Outline: When we hit a breakpoint we need to package up whatever information is needed to eva...
void IndentMore(int amount=2)
Increment the current indentation level.
Definition: Stream.cpp:218
const lldb::WatchpointSP FindBySpec(std::string spec) const
Returns a shared pointer to the watchpoint with watchpoint spec spec.
void DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) const
Dump with lldb::DescriptionLevel.
wp_collection::iterator GetIDIterator(lldb::watch_id_t watchID)
bool Remove(lldb::watch_id_t watchID, bool notify)
Removes the watchpoint given by watchID from this list.
wp_collection::const_iterator GetIDConstIterator(lldb::watch_id_t watchID) const