1 //===-- 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 
20 using namespace lldb;
21 using namespace lldb_private;
22 
23 BreakpointLocationList::BreakpointLocationList() :
24     m_locations(),
25     m_address_to_location (),
26     m_mutex (Mutex::eMutexTypeRecursive),
27     m_next_id (0)
28 {
29 }
30 
31 BreakpointLocationList::~BreakpointLocationList()
32 {
33 }
34 
35 lldb::break_id_t
36 BreakpointLocationList::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 
48 bool
49 BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_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 
64 lldb::break_id_t
65 BreakpointLocationList::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 
75 bool
76 BreakpointLocationList::Remove (lldb::break_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 
90 class BreakpointLocationIDMatches
91 {
92 public:
93     BreakpointLocationIDMatches (lldb::break_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 
103 private:
104    const lldb::break_id_t m_break_id;
105 };
106 
107 class BreakpointLocationAddressMatches
108 {
109 public:
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 
120 private:
121    const Address &m_addr;
122 };
123 
124 BreakpointLocationList::collection::iterator
125 BreakpointLocationList::GetIDIterator (lldb::break_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 
133 BreakpointLocationList::collection::const_iterator
134 BreakpointLocationList::GetIDConstIterator (lldb::break_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 
142 BreakpointLocationSP
143 BreakpointLocationList::FindByID (lldb::break_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 
154 const BreakpointLocationSP
155 BreakpointLocationList::FindByID (lldb::break_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 
166 size_t
167 BreakpointLocationList::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 const BreakpointLocationSP
196 BreakpointLocationList::FindByAddress (Address &addr) const
197 {
198     Mutex::Locker locker (m_mutex);
199     BreakpointLocationSP stop_sp;
200     if (!m_locations.empty())
201     {
202         addr_map::const_iterator pos = m_address_to_location.find (addr);
203         if (pos != m_address_to_location.end())
204             stop_sp = pos->second;
205     }
206 
207     return stop_sp;
208 }
209 
210 void
211 BreakpointLocationList::Dump (Stream *s) const
212 {
213     s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
214     s->Indent();
215     Mutex::Locker locker (m_mutex);
216     s->Printf("BreakpointLocationList with %zu BreakpointLocations:\n", m_locations.size());
217     s->IndentMore();
218     collection::const_iterator pos, end = m_locations.end();
219     for (pos = m_locations.begin(); pos != end; ++pos)
220         (*pos).get()->Dump(s);
221     s->IndentLess();
222 }
223 
224 
225 BreakpointLocationSP
226 BreakpointLocationList::GetByIndex (uint32_t i)
227 {
228     Mutex::Locker locker (m_mutex);
229     BreakpointLocationSP stop_sp;
230     if (i < m_locations.size())
231         stop_sp = m_locations[i];
232 
233     return stop_sp;
234 }
235 
236 const BreakpointLocationSP
237 BreakpointLocationList::GetByIndex (uint32_t i) const
238 {
239     Mutex::Locker locker (m_mutex);
240     BreakpointLocationSP stop_sp;
241     if (i < m_locations.size())
242         stop_sp = m_locations[i];
243 
244     return stop_sp;
245 }
246 
247 void
248 BreakpointLocationList::ClearAllBreakpointSites ()
249 {
250     Mutex::Locker locker (m_mutex);
251     collection::iterator pos, end = m_locations.end();
252     for (pos = m_locations.begin(); pos != end; ++pos)
253         (*pos)->ClearBreakpointSite();
254 }
255 
256 void
257 BreakpointLocationList::ResolveAllBreakpointSites ()
258 {
259     Mutex::Locker locker (m_mutex);
260     collection::iterator pos, end = m_locations.end();
261 
262     for (pos = m_locations.begin(); pos != end; ++pos)
263     {
264         if ((*pos)->IsEnabled())
265             (*pos)->ResolveBreakpointSite();
266     }
267 }
268 
269 uint32_t
270 BreakpointLocationList::GetHitCount () const
271 {
272     uint32_t hit_count = 0;
273     Mutex::Locker locker (m_mutex);
274     collection::const_iterator pos, end = m_locations.end();
275     for (pos = m_locations.begin(); pos != end; ++pos)
276         hit_count += (*pos)->GetHitCount();
277     return hit_count;
278 }
279 
280 size_t
281 BreakpointLocationList::GetNumResolvedLocations() const
282 {
283     Mutex::Locker locker (m_mutex);
284     size_t resolve_count = 0;
285     collection::const_iterator pos, end = m_locations.end();
286     for (pos = m_locations.begin(); pos != end; ++pos)
287     {
288         if ((*pos)->IsResolved())
289             ++resolve_count;
290     }
291     return resolve_count;
292 }
293 
294 break_id_t
295 BreakpointLocationList::GetNextID()
296 {
297     return ++m_next_id;
298 }
299 
300 void
301 BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
302 {
303     Mutex::Locker locker (m_mutex);
304     collection::iterator pos, end = m_locations.end();
305 
306     for (pos = m_locations.begin(); pos != end; ++pos)
307     {
308         s->Printf(" ");
309         (*pos)->GetDescription(s, level);
310     }
311 }
312 
313