1254721Semaste//===-- WatchpointList.cpp --------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste
11254721Semaste// C Includes
12254721Semaste// C++ Includes
13254721Semaste// Other libraries and framework includes
14254721Semaste// Project includes
15254721Semaste#include "lldb/Breakpoint/WatchpointList.h"
16254721Semaste#include "lldb/Breakpoint/Watchpoint.h"
17254721Semaste
18254721Semasteusing namespace lldb;
19254721Semasteusing namespace lldb_private;
20254721Semaste
21254721SemasteWatchpointList::WatchpointList() :
22254721Semaste    m_watchpoints (),
23254721Semaste    m_mutex (Mutex::eMutexTypeRecursive),
24254721Semaste    m_next_wp_id (0)
25254721Semaste{
26254721Semaste}
27254721Semaste
28254721SemasteWatchpointList::~WatchpointList()
29254721Semaste{
30254721Semaste}
31254721Semaste
32254721Semaste// Add a watchpoint to the list.
33254721Semastelldb::watch_id_t
34254721SemasteWatchpointList::Add (const WatchpointSP &wp_sp, bool notify)
35254721Semaste{
36254721Semaste    Mutex::Locker locker (m_mutex);
37254721Semaste    wp_sp->SetID(++m_next_wp_id);
38254721Semaste    m_watchpoints.push_back(wp_sp);
39254721Semaste    if (notify)
40254721Semaste    {
41254721Semaste        if (wp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged))
42254721Semaste            wp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged,
43254721Semaste                                               new Watchpoint::WatchpointEventData (eWatchpointEventTypeAdded, wp_sp));
44254721Semaste    }
45254721Semaste    return wp_sp->GetID();
46254721Semaste}
47254721Semaste
48254721Semastevoid
49254721SemasteWatchpointList::Dump (Stream *s) const
50254721Semaste{
51254721Semaste    DumpWithLevel(s, lldb::eDescriptionLevelBrief);
52254721Semaste}
53254721Semaste
54254721Semastevoid
55254721SemasteWatchpointList::DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const
56254721Semaste{
57254721Semaste    Mutex::Locker locker (m_mutex);
58254721Semaste    s->Printf("%p: ", this);
59254721Semaste    //s->Indent();
60254721Semaste    s->Printf("WatchpointList with %" PRIu64 " Watchpoints:\n",
61254721Semaste              (uint64_t)m_watchpoints.size());
62254721Semaste    s->IndentMore();
63254721Semaste    wp_collection::const_iterator pos, end = m_watchpoints.end();
64254721Semaste    for (pos = m_watchpoints.begin(); pos != end; ++pos)
65254721Semaste        (*pos)->DumpWithLevel(s, description_level);
66254721Semaste    s->IndentLess();
67254721Semaste}
68254721Semaste
69254721Semasteconst WatchpointSP
70254721SemasteWatchpointList::FindByAddress (lldb::addr_t addr) const
71254721Semaste{
72254721Semaste    WatchpointSP wp_sp;
73254721Semaste    Mutex::Locker locker (m_mutex);
74254721Semaste    if (!m_watchpoints.empty())
75254721Semaste    {
76254721Semaste        wp_collection::const_iterator pos, end = m_watchpoints.end();
77254721Semaste        for (pos = m_watchpoints.begin(); pos != end; ++pos)
78254721Semaste            if ((*pos)->GetLoadAddress() == addr) {
79254721Semaste                wp_sp = *pos;
80254721Semaste                break;
81254721Semaste            }
82254721Semaste    }
83254721Semaste
84254721Semaste    return wp_sp;
85254721Semaste}
86254721Semaste
87254721Semasteconst WatchpointSP
88254721SemasteWatchpointList::FindBySpec (std::string spec) const
89254721Semaste{
90254721Semaste    WatchpointSP wp_sp;
91254721Semaste    Mutex::Locker locker (m_mutex);
92254721Semaste    if (!m_watchpoints.empty())
93254721Semaste    {
94254721Semaste        wp_collection::const_iterator pos, end = m_watchpoints.end();
95254721Semaste        for (pos = m_watchpoints.begin(); pos != end; ++pos)
96254721Semaste            if ((*pos)->GetWatchSpec() == spec) {
97254721Semaste                wp_sp = *pos;
98254721Semaste                break;
99254721Semaste            }
100254721Semaste    }
101254721Semaste
102254721Semaste    return wp_sp;
103254721Semaste}
104254721Semaste
105254721Semasteclass WatchpointIDMatches
106254721Semaste{
107254721Semastepublic:
108254721Semaste    WatchpointIDMatches (lldb::watch_id_t watch_id) :
109254721Semaste        m_watch_id(watch_id)
110254721Semaste    {
111254721Semaste    }
112254721Semaste
113254721Semaste    bool operator() (const WatchpointSP &wp) const
114254721Semaste    {
115254721Semaste        return m_watch_id == wp->GetID();
116254721Semaste    }
117254721Semaste
118254721Semasteprivate:
119254721Semaste   const lldb::watch_id_t m_watch_id;
120254721Semaste};
121254721Semaste
122254721SemasteWatchpointList::wp_collection::iterator
123254721SemasteWatchpointList::GetIDIterator (lldb::watch_id_t watch_id)
124254721Semaste{
125254721Semaste    return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range
126254721Semaste                        WatchpointIDMatches(watch_id));             // Predicate
127254721Semaste}
128254721Semaste
129254721SemasteWatchpointList::wp_collection::const_iterator
130254721SemasteWatchpointList::GetIDConstIterator (lldb::watch_id_t watch_id) const
131254721Semaste{
132254721Semaste    return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range
133254721Semaste                        WatchpointIDMatches(watch_id));             // Predicate
134254721Semaste}
135254721Semaste
136254721SemasteWatchpointSP
137254721SemasteWatchpointList::FindByID (lldb::watch_id_t watch_id) const
138254721Semaste{
139254721Semaste    WatchpointSP wp_sp;
140254721Semaste    Mutex::Locker locker (m_mutex);
141254721Semaste    wp_collection::const_iterator pos = GetIDConstIterator(watch_id);
142254721Semaste    if (pos != m_watchpoints.end())
143254721Semaste        wp_sp = *pos;
144254721Semaste
145254721Semaste    return wp_sp;
146254721Semaste}
147254721Semaste
148254721Semastelldb::watch_id_t
149254721SemasteWatchpointList::FindIDByAddress (lldb::addr_t addr)
150254721Semaste{
151254721Semaste    WatchpointSP wp_sp = FindByAddress (addr);
152254721Semaste    if (wp_sp)
153254721Semaste    {
154254721Semaste        return wp_sp->GetID();
155254721Semaste    }
156254721Semaste    return LLDB_INVALID_WATCH_ID;
157254721Semaste}
158254721Semaste
159254721Semastelldb::watch_id_t
160254721SemasteWatchpointList::FindIDBySpec (std::string spec)
161254721Semaste{
162254721Semaste    WatchpointSP wp_sp = FindBySpec (spec);
163254721Semaste    if (wp_sp)
164254721Semaste    {
165254721Semaste        return wp_sp->GetID();
166254721Semaste    }
167254721Semaste    return LLDB_INVALID_WATCH_ID;
168254721Semaste}
169254721Semaste
170254721SemasteWatchpointSP
171254721SemasteWatchpointList::GetByIndex (uint32_t i)
172254721Semaste{
173254721Semaste    Mutex::Locker locker (m_mutex);
174254721Semaste    WatchpointSP wp_sp;
175254721Semaste    if (i < m_watchpoints.size())
176254721Semaste    {
177254721Semaste        wp_collection::const_iterator pos = m_watchpoints.begin();
178254721Semaste        std::advance(pos, i);
179254721Semaste        wp_sp = *pos;
180254721Semaste    }
181254721Semaste    return wp_sp;
182254721Semaste}
183254721Semaste
184254721Semasteconst WatchpointSP
185254721SemasteWatchpointList::GetByIndex (uint32_t i) const
186254721Semaste{
187254721Semaste    Mutex::Locker locker (m_mutex);
188254721Semaste    WatchpointSP wp_sp;
189254721Semaste    if (i < m_watchpoints.size())
190254721Semaste    {
191254721Semaste        wp_collection::const_iterator pos = m_watchpoints.begin();
192254721Semaste        std::advance(pos, i);
193254721Semaste        wp_sp = *pos;
194254721Semaste    }
195254721Semaste    return wp_sp;
196254721Semaste}
197254721Semaste
198254721Semastestd::vector<lldb::watch_id_t>
199254721SemasteWatchpointList::GetWatchpointIDs() const
200254721Semaste{
201254721Semaste    std::vector<lldb::watch_id_t> IDs;
202254721Semaste    wp_collection::const_iterator pos, end = m_watchpoints.end();
203254721Semaste    for (pos = m_watchpoints.begin(); pos != end; ++pos)
204254721Semaste        IDs.push_back((*pos)->GetID());
205254721Semaste    return IDs;
206254721Semaste}
207254721Semaste
208254721Semastebool
209254721SemasteWatchpointList::Remove (lldb::watch_id_t watch_id, bool notify)
210254721Semaste{
211254721Semaste    Mutex::Locker locker (m_mutex);
212254721Semaste    wp_collection::iterator pos = GetIDIterator(watch_id);
213254721Semaste    if (pos != m_watchpoints.end())
214254721Semaste    {
215254721Semaste        WatchpointSP wp_sp = *pos;
216254721Semaste        if (notify)
217254721Semaste        {
218254721Semaste            if (wp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged))
219254721Semaste                wp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged,
220254721Semaste                                                   new Watchpoint::WatchpointEventData (eWatchpointEventTypeRemoved, wp_sp));
221254721Semaste        }
222254721Semaste        m_watchpoints.erase(pos);
223254721Semaste        return true;
224254721Semaste    }
225254721Semaste    return false;
226254721Semaste}
227254721Semaste
228254721Semasteuint32_t
229254721SemasteWatchpointList::GetHitCount () const
230254721Semaste{
231254721Semaste    uint32_t hit_count = 0;
232254721Semaste    Mutex::Locker locker (m_mutex);
233254721Semaste    wp_collection::const_iterator pos, end = m_watchpoints.end();
234254721Semaste    for (pos = m_watchpoints.begin(); pos != end; ++pos)
235254721Semaste        hit_count += (*pos)->GetHitCount();
236254721Semaste    return hit_count;
237254721Semaste}
238254721Semaste
239254721Semastebool
240254721SemasteWatchpointList::ShouldStop (StoppointCallbackContext *context, lldb::watch_id_t watch_id)
241254721Semaste{
242254721Semaste
243254721Semaste    WatchpointSP wp_sp = FindByID (watch_id);
244254721Semaste    if (wp_sp)
245254721Semaste    {
246254721Semaste        // Let the Watchpoint decide if it should stop here (could not have
247254721Semaste        // reached it's target hit count yet, or it could have a callback
248254721Semaste        // that decided it shouldn't stop.
249254721Semaste        return wp_sp->ShouldStop (context);
250254721Semaste    }
251254721Semaste    // We should stop here since this Watchpoint isn't valid anymore or it
252254721Semaste    // doesn't exist.
253254721Semaste    return true;
254254721Semaste}
255254721Semaste
256254721Semastevoid
257254721SemasteWatchpointList::GetDescription (Stream *s, lldb::DescriptionLevel level)
258254721Semaste{
259254721Semaste    Mutex::Locker locker (m_mutex);
260254721Semaste    wp_collection::iterator pos, end = m_watchpoints.end();
261254721Semaste
262254721Semaste    for (pos = m_watchpoints.begin(); pos != end; ++pos)
263254721Semaste    {
264254721Semaste        s->Printf(" ");
265254721Semaste        (*pos)->Dump(s);
266254721Semaste    }
267254721Semaste}
268254721Semaste
269254721Semastevoid
270254721SemasteWatchpointList::SetEnabledAll (bool enabled)
271254721Semaste{
272254721Semaste    Mutex::Locker locker(m_mutex);
273254721Semaste
274254721Semaste    wp_collection::iterator pos, end = m_watchpoints.end();
275254721Semaste    for (pos = m_watchpoints.begin(); pos != end; ++pos)
276254721Semaste        (*pos)->SetEnabled (enabled);
277254721Semaste}
278254721Semaste
279254721Semastevoid
280254721SemasteWatchpointList::RemoveAll (bool notify)
281254721Semaste{
282254721Semaste    Mutex::Locker locker(m_mutex);
283254721Semaste    if (notify)
284254721Semaste    {
285254721Semaste
286254721Semaste        {
287254721Semaste            wp_collection::iterator pos, end = m_watchpoints.end();
288254721Semaste            for (pos = m_watchpoints.begin(); pos != end; ++pos)
289254721Semaste            {
290254721Semaste                if ((*pos)->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
291254721Semaste                {
292254721Semaste                    (*pos)->GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged,
293254721Semaste                                                        new Watchpoint::WatchpointEventData (eWatchpointEventTypeRemoved,
294254721Semaste                                                                                             *pos));
295254721Semaste                }
296254721Semaste            }
297254721Semaste        }
298254721Semaste    }
299254721Semaste    m_watchpoints.clear();
300254721Semaste}
301254721Semaste
302254721Semastevoid
303254721SemasteWatchpointList::GetListMutex (Mutex::Locker &locker)
304254721Semaste{
305254721Semaste    return locker.Lock (m_mutex);
306254721Semaste}
307