blob: 9721b085e2e7a1a03da9d546a883e8c9200bbb9d [file] [log] [blame]
Johnny Chen01a67862011-10-14 00:42:25 +00001//===-- 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
11// C Includes
12// C++ Includes
13// Other libraries and framework includes
14// Project includes
15#include "lldb/Breakpoint/WatchpointList.h"
16#include "lldb/Breakpoint/Watchpoint.h"
17
18using namespace lldb;
19using namespace lldb_private;
20
21WatchpointList::WatchpointList() :
22 m_address_to_watchpoint (),
23 m_mutex (Mutex::eMutexTypeRecursive)
24{
25}
26
27WatchpointList::~WatchpointList()
28{
29}
30
31// Add watchpoint loc to the list. However, if the element already exists in the
32// list, then replace it with the input one.
33
34lldb::watch_id_t
35WatchpointList::Add (const WatchpointSP &wp_sp)
36{
37 Mutex::Locker locker (m_mutex);
38 lldb::addr_t wp_addr = wp_sp->GetLoadAddress();
39 addr_map::iterator iter = m_address_to_watchpoint.find(wp_addr);
40
41 if (iter == m_address_to_watchpoint.end())
42 m_address_to_watchpoint.insert(iter, addr_map::value_type(wp_addr, wp_sp));
43 else
44 m_address_to_watchpoint[wp_addr] = wp_sp;
45
46 return wp_sp->GetID();
47}
48
49void
50WatchpointList::Dump (Stream *s) const
51{
52 DumpWithLevel(s, lldb::eDescriptionLevelBrief);
53}
54
55void
56WatchpointList::DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const
57{
58 Mutex::Locker locker (m_mutex);
59 s->Printf("%p: ", this);
60 //s->Indent();
61 s->Printf("WatchpointList with %zu Watchpoints:\n",
62 m_address_to_watchpoint.size());
63 s->IndentMore();
64 addr_map::const_iterator pos, end = m_address_to_watchpoint.end();
65 for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos)
66 pos->second->DumpWithLevel(s, description_level);
67 s->IndentLess();
68}
69
70const WatchpointSP
71WatchpointList::FindByAddress (lldb::addr_t addr) const
72{
73 WatchpointSP wp_sp;
74 Mutex::Locker locker (m_mutex);
75 if (!m_address_to_watchpoint.empty())
76 {
77 addr_map::const_iterator pos = m_address_to_watchpoint.find (addr);
78 if (pos != m_address_to_watchpoint.end())
79 wp_sp = pos->second;
80 }
81
82 return wp_sp;
83}
84
85class WatchpointIDMatches
86{
87public:
88 WatchpointIDMatches (lldb::watch_id_t watch_id) :
89 m_watch_id(watch_id)
90 {
91 }
92
93 bool operator() (std::pair <lldb::addr_t, WatchpointSP> val_pair) const
94 {
95 return m_watch_id == val_pair.second.get()->GetID();
96 }
97
98private:
99 const lldb::watch_id_t m_watch_id;
100};
101
102WatchpointList::addr_map::iterator
103WatchpointList::GetIDIterator (lldb::watch_id_t watch_id)
104{
105 return std::find_if(m_address_to_watchpoint.begin(), m_address_to_watchpoint.end(), // Search full range
106 WatchpointIDMatches(watch_id)); // Predicate
107}
108
109WatchpointList::addr_map::const_iterator
110WatchpointList::GetIDConstIterator (lldb::watch_id_t watch_id) const
111{
112 return std::find_if(m_address_to_watchpoint.begin(), m_address_to_watchpoint.end(), // Search full range
113 WatchpointIDMatches(watch_id)); // Predicate
114}
115
116WatchpointSP
117WatchpointList::FindByID (lldb::watch_id_t watch_id) const
118{
119 WatchpointSP wp_sp;
120 Mutex::Locker locker (m_mutex);
121 addr_map::const_iterator pos = GetIDConstIterator(watch_id);
122 if (pos != m_address_to_watchpoint.end())
123 wp_sp = pos->second;
124
125 return wp_sp;
126}
127
128lldb::watch_id_t
129WatchpointList::FindIDByAddress (lldb::addr_t addr)
130{
131 WatchpointSP wp_sp = FindByAddress (addr);
132 if (wp_sp)
133 {
134 return wp_sp->GetID();
135 }
136 return LLDB_INVALID_WATCH_ID;
137}
138
139WatchpointSP
140WatchpointList::GetByIndex (uint32_t i)
141{
142 Mutex::Locker locker (m_mutex);
143 WatchpointSP wp_sp;
144 if (i < m_address_to_watchpoint.size())
145 {
146 addr_map::const_iterator pos = m_address_to_watchpoint.begin();
147 std::advance(pos, i);
148 wp_sp = pos->second;
149 }
150 return wp_sp;
151}
152
153const WatchpointSP
154WatchpointList::GetByIndex (uint32_t i) const
155{
156 Mutex::Locker locker (m_mutex);
157 WatchpointSP wp_sp;
158 if (i < m_address_to_watchpoint.size())
159 {
160 addr_map::const_iterator pos = m_address_to_watchpoint.begin();
161 std::advance(pos, i);
162 wp_sp = pos->second;
163 }
164 return wp_sp;
165}
166
167bool
168WatchpointList::Remove (lldb::watch_id_t watch_id)
169{
170 Mutex::Locker locker (m_mutex);
171 addr_map::iterator pos = GetIDIterator(watch_id);
172 if (pos != m_address_to_watchpoint.end())
173 {
174 m_address_to_watchpoint.erase(pos);
175 return true;
176 }
177 return false;
178}
179
180uint32_t
181WatchpointList::GetHitCount () const
182{
183 uint32_t hit_count = 0;
184 Mutex::Locker locker (m_mutex);
185 addr_map::const_iterator pos, end = m_address_to_watchpoint.end();
186 for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos)
187 hit_count += pos->second->GetHitCount();
188 return hit_count;
189}
190
191bool
192WatchpointList::ShouldStop (StoppointCallbackContext *context, lldb::watch_id_t watch_id)
193{
194
195 WatchpointSP wp_sp = FindByID (watch_id);
196 if (wp_sp)
197 {
198 // Let the Watchpoint decide if it should stop here (could not have
199 // reached it's target hit count yet, or it could have a callback
200 // that decided it shouldn't stop.
201 return wp_sp->ShouldStop (context);
202 }
203 // We should stop here since this Watchpoint isn't valid anymore or it
204 // doesn't exist.
205 return true;
206}
207
208void
209WatchpointList::GetDescription (Stream *s, lldb::DescriptionLevel level)
210{
211 Mutex::Locker locker (m_mutex);
212 addr_map::iterator pos, end = m_address_to_watchpoint.end();
213
214 for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos)
215 {
216 s->Printf(" ");
217 pos->second->Dump(s);
218 }
219}
220
221void
222WatchpointList::SetEnabledAll (bool enabled)
223{
224 Mutex::Locker locker(m_mutex);
225
226 addr_map::iterator pos, end = m_address_to_watchpoint.end();
227 for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos)
228 pos->second->SetEnabled (enabled);
229}
230
231void
232WatchpointList::RemoveAll ()
233{
234 Mutex::Locker locker(m_mutex);
235 m_address_to_watchpoint.clear();
236}
237
238void
239WatchpointList::GetListMutex (Mutex::Locker &locker)
240{
241 return locker.Reset (m_mutex.GetMutex());
242}