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