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::user_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::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 
64 lldb::user_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::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 
90 class BreakpointLocationIDMatches
91 {
92 public:
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 
103 private:
104    const lldb::user_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::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 
133 BreakpointLocationList::collection::const_iterator
134 BreakpointLocationList::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 
142 BreakpointLocationSP
143 BreakpointLocationList::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 
154 const BreakpointLocationSP
155 BreakpointLocationList::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 
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 
196 static int
197 FindLocationByAddress (Address *addr_ptr, const BreakpointLocationSP *bp_loc_sp_ptr)
198 {
199     return Address::CompareModulePointerAndOffset(*addr_ptr, (*bp_loc_sp_ptr)->GetAddress());
200 }
201 
202 const BreakpointLocationSP
203 BreakpointLocationList::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 
217 void
218 BreakpointLocationList::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 
232 BreakpointLocationSP
233 BreakpointLocationList::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 
243 const BreakpointLocationSP
244 BreakpointLocationList::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 
254 void
255 BreakpointLocationList::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 
263 void
264 BreakpointLocationList::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 
273 size_t
274 BreakpointLocationList::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 
287 break_id_t
288 BreakpointLocationList::GetNextID()
289 {
290     return ++m_next_id;
291 }
292 
293 void
294 BreakpointLocationList::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 
306