blob: d86a8cf4c473317d8c804510dab544606f51a831 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- BreakpointLocationList.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/BreakpointLocationList.h"
16#include "lldb/Breakpoint/BreakpointLocation.h"
17#include "lldb/Core/ModuleList.h"
18#include "lldb/Target/Target.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23BreakpointLocationList::BreakpointLocationList() :
24 m_locations(),
25 m_address_to_location (),
26 m_mutex (Mutex::eMutexTypeRecursive),
27 m_next_id (0)
28{
29}
30
31BreakpointLocationList::~BreakpointLocationList()
32{
33}
34
35lldb::user_id_t
36BreakpointLocationList::Add (BreakpointLocationSP &bp_loc_sp)
37{
38 if (bp_loc_sp)
39 {
40 Mutex::Locker locker (m_mutex);
41 m_locations.push_back (bp_loc_sp);
42 m_address_to_location[bp_loc_sp->GetAddress()] = bp_loc_sp;
43 return bp_loc_sp->GetID();
44 }
45 return LLDB_INVALID_BREAK_ID;
46}
47
48bool
49BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::user_id_t break_id)
50{
51 BreakpointLocationSP bp = FindByID (break_id);
52 if (bp)
53 {
54 // Let the BreakpointLocation decide if it should stop here (could not have
55 // reached it's target hit count yet, or it could have a callback
56 // that decided it shouldn't stop (shared library loads/unloads).
57 return bp->ShouldStop (context);
58 }
59 // We should stop here since this BreakpointLocation isn't valid anymore or it
60 // doesn't exist.
61 return true;
62}
63
64lldb::user_id_t
65BreakpointLocationList::FindIDByAddress (Address &addr)
66{
67 BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
68 if (bp_loc_sp)
69 {
70 return bp_loc_sp->GetID();
71 }
72 return LLDB_INVALID_BREAK_ID;
73}
74
75bool
76BreakpointLocationList::Remove (lldb::user_id_t break_id)
77{
78 Mutex::Locker locker (m_mutex);
79 collection::iterator pos = GetIDIterator(break_id); // Predicate
80 if (pos != m_locations.end())
81 {
82 m_address_to_location.erase ((*pos)->GetAddress());
83 m_locations.erase(pos);
84 return true;
85 }
86 return false;
87}
88
89
90class BreakpointLocationIDMatches
91{
92public:
93 BreakpointLocationIDMatches (lldb::user_id_t break_id) :
94 m_break_id(break_id)
95 {
96 }
97
98 bool operator() (const BreakpointLocationSP &bp_loc_sp) const
99 {
100 return m_break_id == bp_loc_sp->GetID();
101 }
102
103private:
104 const lldb::user_id_t m_break_id;
105};
106
107class BreakpointLocationAddressMatches
108{
109public:
110 BreakpointLocationAddressMatches (Address& addr) :
111 m_addr(addr)
112 {
113 }
114
115 bool operator() (const BreakpointLocationSP& bp_loc_sp) const
116 {
117 return Address::CompareFileAddress(m_addr, bp_loc_sp->GetAddress()) == 0;
118 }
119
120private:
121 const Address &m_addr;
122};
123
124BreakpointLocationList::collection::iterator
125BreakpointLocationList::GetIDIterator (lldb::user_id_t break_id)
126{
127 Mutex::Locker locker (m_mutex);
128 return std::find_if (m_locations.begin(),
129 m_locations.end(),
130 BreakpointLocationIDMatches(break_id));
131}
132
133BreakpointLocationList::collection::const_iterator
134BreakpointLocationList::GetIDConstIterator (lldb::user_id_t break_id) const
135{
136 Mutex::Locker locker (m_mutex);
137 return std::find_if (m_locations.begin(),
138 m_locations.end(),
139 BreakpointLocationIDMatches(break_id));
140}
141
142BreakpointLocationSP
143BreakpointLocationList::FindByID (lldb::user_id_t break_id)
144{
145 Mutex::Locker locker (m_mutex);
146 BreakpointLocationSP stop_sp;
147 collection::iterator pos = GetIDIterator(break_id);
148 if (pos != m_locations.end())
149 stop_sp = *pos;
150
151 return stop_sp;
152}
153
154const BreakpointLocationSP
155BreakpointLocationList::FindByID (lldb::user_id_t break_id) const
156{
157 Mutex::Locker locker (m_mutex);
158 BreakpointLocationSP stop_sp;
159 collection::const_iterator pos = GetIDConstIterator(break_id);
160 if (pos != m_locations.end())
161 stop_sp = *pos;
162
163 return stop_sp;
164}
165
166size_t
167BreakpointLocationList::FindInModule (Module *module,
168 BreakpointLocationCollection& bp_loc_list)
169{
170 Mutex::Locker locker (m_mutex);
171 const size_t orig_size = bp_loc_list.GetSize();
172 collection::iterator pos, end = m_locations.end();
173
174 for (pos = m_locations.begin(); pos != end; ++pos)
175 {
176 bool seen = false;
177 BreakpointLocationSP break_loc = (*pos);
178 const Section *section = break_loc->GetAddress().GetSection();
179 if (section)
180 {
181 if (section->GetModule() == module)
182 {
183 if (!seen)
184 {
185 seen = true;
186 bp_loc_list.Add (break_loc);
187 }
188
189 }
190 }
191 }
192 return bp_loc_list.GetSize() - orig_size;
193}
194
195
196static int
197FindLocationByAddress (Address *addr_ptr, const BreakpointLocationSP *bp_loc_sp_ptr)
198{
199 return Address::CompareModulePointerAndOffset(*addr_ptr, (*bp_loc_sp_ptr)->GetAddress());
200}
201
202const BreakpointLocationSP
203BreakpointLocationList::FindByAddress (Address &addr) const
204{
205 Mutex::Locker locker (m_mutex);
206 BreakpointLocationSP stop_sp;
207 if (!m_locations.empty())
208 {
209 addr_map::const_iterator pos = m_address_to_location.find (addr);
210 if (pos != m_address_to_location.end())
211 stop_sp = pos->second;
212 }
213
214 return stop_sp;
215}
216
217void
218BreakpointLocationList::Dump (Stream *s) const
219{
220 s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
221 s->Indent();
222 Mutex::Locker locker (m_mutex);
223 s->Printf("BreakpointLocationList with %zu BreakpointLocations:\n", m_locations.size());
224 s->IndentMore();
225 collection::const_iterator pos, end = m_locations.end();
226 for (pos = m_locations.begin(); pos != end; ++pos)
227 (*pos).get()->Dump(s);
228 s->IndentLess();
229}
230
231
232BreakpointLocationSP
233BreakpointLocationList::GetByIndex (uint32_t i)
234{
235 Mutex::Locker locker (m_mutex);
236 BreakpointLocationSP stop_sp;
237 if (i >= 0 && i < m_locations.size())
238 stop_sp = m_locations[i];
239
240 return stop_sp;
241}
242
243const BreakpointLocationSP
244BreakpointLocationList::GetByIndex (uint32_t i) const
245{
246 Mutex::Locker locker (m_mutex);
247 BreakpointLocationSP stop_sp;
248 if (i >= 0 && i < m_locations.size())
249 stop_sp = m_locations[i];
250
251 return stop_sp;
252}
253
254void
255BreakpointLocationList::ClearAllBreakpointSites ()
256{
257 Mutex::Locker locker (m_mutex);
258 collection::iterator pos, end = m_locations.end();
259 for (pos = m_locations.begin(); pos != end; ++pos)
260 (*pos)->ClearBreakpointSite();
261}
262
263void
264BreakpointLocationList::ResolveAllBreakpointSites ()
265{
266 Mutex::Locker locker (m_mutex);
267 collection::iterator pos, end = m_locations.end();
268
269 for (pos = m_locations.begin(); pos != end; ++pos)
270 (*pos)->ResolveBreakpointSite();
271}
272
273size_t
274BreakpointLocationList::GetNumResolvedLocations() const
275{
276 Mutex::Locker locker (m_mutex);
277 size_t resolve_count = 0;
278 collection::const_iterator pos, end = m_locations.end();
279 for (pos = m_locations.begin(); pos != end; ++pos)
280 {
281 if ((*pos)->IsResolved())
282 ++resolve_count;
283 }
284 return resolve_count;
285}
286
287break_id_t
288BreakpointLocationList::GetNextID()
289{
290 return ++m_next_id;
291}
292
293void
294BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
295{
296 Mutex::Locker locker (m_mutex);
297 collection::iterator pos, end = m_locations.end();
298
299 for (pos = m_locations.begin(); pos != end; ++pos)
300 {
301 s->Printf(" ");
302 (*pos)->GetDescription(s, level);
303 }
304}
305