WatchpointList.cpp revision 516f0849819d094d4eab39a1f27b770259103ff8
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
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_watchpoints (),
23    m_mutex (Mutex::eMutexTypeRecursive),
24    m_next_wp_id (0)
25{
26}
27
28WatchpointList::~WatchpointList()
29{
30}
31
32// Add a watchpoint to the list.
33lldb::watch_id_t
34WatchpointList::Add (const WatchpointSP &wp_sp)
35{
36    Mutex::Locker locker (m_mutex);
37    wp_sp->SetID(++m_next_wp_id);
38    m_watchpoints.push_back(wp_sp);
39    return wp_sp->GetID();
40}
41
42void
43WatchpointList::Dump (Stream *s) const
44{
45    DumpWithLevel(s, lldb::eDescriptionLevelBrief);
46}
47
48void
49WatchpointList::DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const
50{
51    Mutex::Locker locker (m_mutex);
52    s->Printf("%p: ", this);
53    //s->Indent();
54    s->Printf("WatchpointList with %zu Watchpoints:\n",
55              m_watchpoints.size());
56    s->IndentMore();
57    wp_collection::const_iterator pos, end = m_watchpoints.end();
58    for (pos = m_watchpoints.begin(); pos != end; ++pos)
59        (*pos)->DumpWithLevel(s, description_level);
60    s->IndentLess();
61}
62
63const WatchpointSP
64WatchpointList::FindByAddress (lldb::addr_t addr) const
65{
66    WatchpointSP wp_sp;
67    Mutex::Locker locker (m_mutex);
68    if (!m_watchpoints.empty())
69    {
70        wp_collection::const_iterator pos, end = m_watchpoints.end();
71        for (pos = m_watchpoints.begin(); pos != end; ++pos)
72            if ((*pos)->GetLoadAddress() == addr) {
73                wp_sp = *pos;
74                break;
75            }
76    }
77
78    return wp_sp;
79}
80
81const WatchpointSP
82WatchpointList::FindBySpec (std::string spec) const
83{
84    WatchpointSP wp_sp;
85    Mutex::Locker locker (m_mutex);
86    if (!m_watchpoints.empty())
87    {
88        wp_collection::const_iterator pos, end = m_watchpoints.end();
89        for (pos = m_watchpoints.begin(); pos != end; ++pos)
90            if ((*pos)->GetWatchSpec() == spec) {
91                wp_sp = *pos;
92                break;
93            }
94    }
95
96    return wp_sp;
97}
98
99class WatchpointIDMatches
100{
101public:
102    WatchpointIDMatches (lldb::watch_id_t watch_id) :
103        m_watch_id(watch_id)
104    {
105    }
106
107    bool operator() (const WatchpointSP &wp) const
108    {
109        return m_watch_id == wp->GetID();
110    }
111
112private:
113   const lldb::watch_id_t m_watch_id;
114};
115
116WatchpointList::wp_collection::iterator
117WatchpointList::GetIDIterator (lldb::watch_id_t watch_id)
118{
119    return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range
120                        WatchpointIDMatches(watch_id));             // Predicate
121}
122
123WatchpointList::wp_collection::const_iterator
124WatchpointList::GetIDConstIterator (lldb::watch_id_t watch_id) const
125{
126    return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range
127                        WatchpointIDMatches(watch_id));             // Predicate
128}
129
130WatchpointSP
131WatchpointList::FindByID (lldb::watch_id_t watch_id) const
132{
133    WatchpointSP wp_sp;
134    Mutex::Locker locker (m_mutex);
135    wp_collection::const_iterator pos = GetIDConstIterator(watch_id);
136    if (pos != m_watchpoints.end())
137        wp_sp = *pos;
138
139    return wp_sp;
140}
141
142lldb::watch_id_t
143WatchpointList::FindIDByAddress (lldb::addr_t addr)
144{
145    WatchpointSP wp_sp = FindByAddress (addr);
146    if (wp_sp)
147    {
148        return wp_sp->GetID();
149    }
150    return LLDB_INVALID_WATCH_ID;
151}
152
153lldb::watch_id_t
154WatchpointList::FindIDBySpec (std::string spec)
155{
156    WatchpointSP wp_sp = FindBySpec (spec);
157    if (wp_sp)
158    {
159        return wp_sp->GetID();
160    }
161    return LLDB_INVALID_WATCH_ID;
162}
163
164WatchpointSP
165WatchpointList::GetByIndex (uint32_t i)
166{
167    Mutex::Locker locker (m_mutex);
168    WatchpointSP wp_sp;
169    if (i < m_watchpoints.size())
170    {
171        wp_collection::const_iterator pos = m_watchpoints.begin();
172        std::advance(pos, i);
173        wp_sp = *pos;
174    }
175    return wp_sp;
176}
177
178const WatchpointSP
179WatchpointList::GetByIndex (uint32_t i) const
180{
181    Mutex::Locker locker (m_mutex);
182    WatchpointSP wp_sp;
183    if (i < m_watchpoints.size())
184    {
185        wp_collection::const_iterator pos = m_watchpoints.begin();
186        std::advance(pos, i);
187        wp_sp = *pos;
188    }
189    return wp_sp;
190}
191
192std::vector<lldb::watch_id_t>
193WatchpointList::GetWatchpointIDs() const
194{
195    std::vector<lldb::watch_id_t> IDs;
196    wp_collection::const_iterator pos, end = m_watchpoints.end();
197    for (pos = m_watchpoints.begin(); pos != end; ++pos)
198        IDs.push_back((*pos)->GetID());
199    return IDs;
200}
201
202bool
203WatchpointList::Remove (lldb::watch_id_t watch_id)
204{
205    Mutex::Locker locker (m_mutex);
206    wp_collection::iterator pos = GetIDIterator(watch_id);
207    if (pos != m_watchpoints.end())
208    {
209        m_watchpoints.erase(pos);
210        return true;
211    }
212    return false;
213}
214
215uint32_t
216WatchpointList::GetHitCount () const
217{
218    uint32_t hit_count = 0;
219    Mutex::Locker locker (m_mutex);
220    wp_collection::const_iterator pos, end = m_watchpoints.end();
221    for (pos = m_watchpoints.begin(); pos != end; ++pos)
222        hit_count += (*pos)->GetHitCount();
223    return hit_count;
224}
225
226bool
227WatchpointList::ShouldStop (StoppointCallbackContext *context, lldb::watch_id_t watch_id)
228{
229
230    WatchpointSP wp_sp = FindByID (watch_id);
231    if (wp_sp)
232    {
233        // Let the Watchpoint decide if it should stop here (could not have
234        // reached it's target hit count yet, or it could have a callback
235        // that decided it shouldn't stop.
236        return wp_sp->ShouldStop (context);
237    }
238    // We should stop here since this Watchpoint isn't valid anymore or it
239    // doesn't exist.
240    return true;
241}
242
243void
244WatchpointList::GetDescription (Stream *s, lldb::DescriptionLevel level)
245{
246    Mutex::Locker locker (m_mutex);
247    wp_collection::iterator pos, end = m_watchpoints.end();
248
249    for (pos = m_watchpoints.begin(); pos != end; ++pos)
250    {
251        s->Printf(" ");
252        (*pos)->Dump(s);
253    }
254}
255
256void
257WatchpointList::SetEnabledAll (bool enabled)
258{
259    Mutex::Locker locker(m_mutex);
260
261    wp_collection::iterator pos, end = m_watchpoints.end();
262    for (pos = m_watchpoints.begin(); pos != end; ++pos)
263        (*pos)->SetEnabled (enabled);
264}
265
266void
267WatchpointList::RemoveAll ()
268{
269    Mutex::Locker locker(m_mutex);
270    m_watchpoints.clear();
271}
272
273void
274WatchpointList::GetListMutex (Mutex::Locker &locker)
275{
276    return locker.Lock (m_mutex.GetMutex());
277}
278