1 //===-- BreakpointList.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 #include "lldb/Breakpoint/BreakpointList.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Target/Target.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 BreakpointList::BreakpointList(bool is_internal)
22     : m_mutex(), m_breakpoints(), m_next_break_id(0), m_is_internal(is_internal)
23 {
24 }
25 
26 BreakpointList::~BreakpointList()
27 {
28 }
29 
30 
31 break_id_t
32 BreakpointList::Add (BreakpointSP &bp_sp, bool notify)
33 {
34     std::lock_guard<std::recursive_mutex> guard(m_mutex);
35     // Internal breakpoint IDs are negative, normal ones are positive
36     bp_sp->SetID (m_is_internal ? --m_next_break_id : ++m_next_break_id);
37 
38     m_breakpoints.push_back(bp_sp);
39     if (notify)
40     {
41         if (bp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
42             bp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged,
43                                                new Breakpoint::BreakpointEventData (eBreakpointEventTypeAdded, bp_sp));
44     }
45     return bp_sp->GetID();
46 }
47 
48 bool
49 BreakpointList::Remove (break_id_t break_id, bool notify)
50 {
51     std::lock_guard<std::recursive_mutex> guard(m_mutex);
52     bp_collection::iterator pos = GetBreakpointIDIterator(break_id);    // Predicate
53     if (pos != m_breakpoints.end())
54     {
55         BreakpointSP bp_sp (*pos);
56         m_breakpoints.erase(pos);
57         if (notify)
58         {
59             if (bp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
60                 bp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged,
61                                                    new Breakpoint::BreakpointEventData (eBreakpointEventTypeRemoved, bp_sp));
62         }
63         return true;
64     }
65     return false;
66 }
67 
68 void
69 BreakpointList::RemoveInvalidLocations (const ArchSpec &arch)
70 {
71     std::lock_guard<std::recursive_mutex> guard(m_mutex);
72     for (const auto &bp_sp : m_breakpoints)
73         bp_sp->RemoveInvalidLocations(arch);
74 }
75 
76 
77 void
78 BreakpointList::SetEnabledAll (bool enabled)
79 {
80     std::lock_guard<std::recursive_mutex> guard(m_mutex);
81     for (const auto &bp_sp : m_breakpoints)
82         bp_sp->SetEnabled (enabled);
83 }
84 
85 
86 void
87 BreakpointList::RemoveAll (bool notify)
88 {
89     std::lock_guard<std::recursive_mutex> guard(m_mutex);
90     ClearAllBreakpointSites ();
91 
92     if (notify)
93     {
94         bp_collection::iterator pos, end = m_breakpoints.end();
95         for (pos = m_breakpoints.begin(); pos != end; ++pos)
96         {
97             if ((*pos)->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
98             {
99                 (*pos)->GetTarget().BroadcastEvent (Target::eBroadcastBitBreakpointChanged,
100                                                     new Breakpoint::BreakpointEventData (eBreakpointEventTypeRemoved,
101                                                                                          *pos));
102             }
103         }
104     }
105     m_breakpoints.erase (m_breakpoints.begin(), m_breakpoints.end());
106 }
107 
108 class BreakpointIDMatches
109 {
110 public:
111     BreakpointIDMatches (break_id_t break_id) :
112         m_break_id(break_id)
113     {
114     }
115 
116     bool operator() (const BreakpointSP &bp) const
117     {
118         return m_break_id == bp->GetID();
119     }
120 
121 private:
122    const break_id_t m_break_id;
123 };
124 
125 BreakpointList::bp_collection::iterator
126 BreakpointList::GetBreakpointIDIterator (break_id_t break_id)
127 {
128     return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
129                         BreakpointIDMatches(break_id));             // Predicate
130 }
131 
132 BreakpointList::bp_collection::const_iterator
133 BreakpointList::GetBreakpointIDConstIterator (break_id_t break_id) const
134 {
135     return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
136                         BreakpointIDMatches(break_id));             // Predicate
137 }
138 
139 BreakpointSP
140 BreakpointList::FindBreakpointByID (break_id_t break_id)
141 {
142     std::lock_guard<std::recursive_mutex> guard(m_mutex);
143     BreakpointSP stop_sp;
144     bp_collection::iterator pos = GetBreakpointIDIterator(break_id);
145     if (pos != m_breakpoints.end())
146         stop_sp = *pos;
147 
148     return stop_sp;
149 }
150 
151 const BreakpointSP
152 BreakpointList::FindBreakpointByID (break_id_t break_id) const
153 {
154     std::lock_guard<std::recursive_mutex> guard(m_mutex);
155     BreakpointSP stop_sp;
156     bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id);
157     if (pos != m_breakpoints.end())
158         stop_sp = *pos;
159 
160     return stop_sp;
161 }
162 
163 void
164 BreakpointList::Dump (Stream *s) const
165 {
166     std::lock_guard<std::recursive_mutex> guard(m_mutex);
167     s->Printf("%p: ", static_cast<const void*>(this));
168     s->Indent();
169     s->Printf("BreakpointList with %u Breakpoints:\n", (uint32_t)m_breakpoints.size());
170     s->IndentMore();
171     for (const auto &bp_sp : m_breakpoints)
172         bp_sp->Dump(s);
173     s->IndentLess();
174 }
175 
176 
177 BreakpointSP
178 BreakpointList::GetBreakpointAtIndex (size_t i)
179 {
180     std::lock_guard<std::recursive_mutex> guard(m_mutex);
181     BreakpointSP stop_sp;
182     bp_collection::iterator end = m_breakpoints.end();
183     bp_collection::iterator pos;
184     size_t curr_i = 0;
185     for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
186     {
187         if (curr_i == i)
188             stop_sp = *pos;
189     }
190     return stop_sp;
191 }
192 
193 const BreakpointSP
194 BreakpointList::GetBreakpointAtIndex (size_t i) const
195 {
196     std::lock_guard<std::recursive_mutex> guard(m_mutex);
197     BreakpointSP stop_sp;
198     bp_collection::const_iterator end = m_breakpoints.end();
199     bp_collection::const_iterator pos;
200     size_t curr_i = 0;
201     for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
202     {
203         if (curr_i == i)
204             stop_sp = *pos;
205     }
206     return stop_sp;
207 }
208 
209 void
210 BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added, bool delete_locations)
211 {
212     std::lock_guard<std::recursive_mutex> guard(m_mutex);
213     for (const auto &bp_sp : m_breakpoints)
214         bp_sp->ModulesChanged (module_list, added, delete_locations);
215 
216 }
217 
218 void
219 BreakpointList::UpdateBreakpointsWhenModuleIsReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp)
220 {
221     std::lock_guard<std::recursive_mutex> guard(m_mutex);
222     for (const auto &bp_sp : m_breakpoints)
223         bp_sp->ModuleReplaced (old_module_sp, new_module_sp);
224 
225 }
226 
227 void
228 BreakpointList::ClearAllBreakpointSites ()
229 {
230     std::lock_guard<std::recursive_mutex> guard(m_mutex);
231     for (const auto &bp_sp : m_breakpoints)
232         bp_sp->ClearAllBreakpointSites ();
233 
234 }
235 
236 void
237 BreakpointList::GetListMutex(std::unique_lock<std::recursive_mutex> &lock)
238 {
239     lock = std::unique_lock<std::recursive_mutex>(m_mutex);
240 }
241