]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / lldb / source / Breakpoint / BreakpointLocationList.cpp
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
17 #include "lldb/Breakpoint/BreakpointLocation.h"
18 #include "lldb/Breakpoint/Breakpoint.h"
19 #include "lldb/Core/ArchSpec.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/Section.h"
22 #include "lldb/Target/SectionLoadList.h"
23 #include "lldb/Target/Target.h"
24
25
26 using namespace lldb;
27 using namespace lldb_private;
28
29 BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) :
30     m_owner (owner),
31     m_locations(),
32     m_address_to_location (),
33     m_mutex (Mutex::eMutexTypeRecursive),
34     m_next_id (0),
35     m_new_location_recorder (NULL)
36 {
37 }
38
39 BreakpointLocationList::~BreakpointLocationList()
40 {
41 }
42
43 BreakpointLocationSP
44 BreakpointLocationList::Create (const Address &addr, bool resolve_indirect_symbols)
45 {
46     Mutex::Locker locker (m_mutex);
47     // The location ID is just the size of the location list + 1
48     lldb::break_id_t bp_loc_id = ++m_next_id;
49     BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware(), resolve_indirect_symbols));
50     m_locations.push_back (bp_loc_sp);
51     m_address_to_location[addr] = bp_loc_sp;
52     return bp_loc_sp;
53 }
54
55 bool
56 BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
57 {
58     BreakpointLocationSP bp = FindByID (break_id);
59     if (bp)
60     {
61         // Let the BreakpointLocation decide if it should stop here (could not have
62         // reached it's target hit count yet, or it could have a callback
63         // that decided it shouldn't stop (shared library loads/unloads).
64         return bp->ShouldStop (context);
65     }
66     // We should stop here since this BreakpointLocation isn't valid anymore or it
67     // doesn't exist.
68     return true;
69 }
70
71 lldb::break_id_t
72 BreakpointLocationList::FindIDByAddress (const Address &addr)
73 {
74     BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
75     if (bp_loc_sp)
76     {
77         return bp_loc_sp->GetID();
78     }
79     return LLDB_INVALID_BREAK_ID;
80 }
81
82 static bool
83 Compare (BreakpointLocationSP lhs, lldb::break_id_t val)
84 {
85     return lhs->GetID() < val;
86 }
87
88 BreakpointLocationSP
89 BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
90 {
91     Mutex::Locker locker (m_mutex);
92     collection::const_iterator end = m_locations.end();
93     collection::const_iterator pos = std::lower_bound(m_locations.begin(), end, break_id, Compare);
94     if (pos != end && (*pos)->GetID() == break_id)
95         return *(pos);
96     else
97         return BreakpointLocationSP();
98 }
99
100 size_t
101 BreakpointLocationList::FindInModule (Module *module,
102                                       BreakpointLocationCollection& bp_loc_list)
103 {
104     Mutex::Locker locker (m_mutex);
105     const size_t orig_size = bp_loc_list.GetSize();
106     collection::iterator pos, end = m_locations.end();
107
108     for (pos = m_locations.begin(); pos != end; ++pos)
109     {
110         BreakpointLocationSP break_loc = (*pos);
111         SectionSP section_sp (break_loc->GetAddress().GetSection());
112         if (section_sp && section_sp->GetModule().get() == module)
113         {
114             bp_loc_list.Add (break_loc);
115         }
116     }
117     return bp_loc_list.GetSize() - orig_size;
118 }
119
120 const BreakpointLocationSP
121 BreakpointLocationList::FindByAddress (const Address &addr) const
122 {
123     Mutex::Locker locker (m_mutex);
124     BreakpointLocationSP bp_loc_sp;
125     if (!m_locations.empty())
126     {
127         Address so_addr;
128
129         if (addr.IsSectionOffset())
130         {
131             so_addr = addr;
132         }
133         else
134         {
135             // Try and resolve as a load address if possible.
136             m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr);
137             if (!so_addr.IsValid())
138             {    
139                 // The address didn't resolve, so just set to passed in addr.
140                 so_addr = addr;
141             }
142         }
143
144         addr_map::const_iterator pos = m_address_to_location.find (so_addr);
145         if (pos != m_address_to_location.end())
146             bp_loc_sp = pos->second;
147     }
148
149     return bp_loc_sp;
150 }
151
152 void
153 BreakpointLocationList::Dump (Stream *s) const
154 {
155     s->Printf("%p: ", this);
156     //s->Indent();
157     Mutex::Locker locker (m_mutex);
158     s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size());
159     s->IndentMore();
160     collection::const_iterator pos, end = m_locations.end();
161     for (pos = m_locations.begin(); pos != end; ++pos)
162         (*pos).get()->Dump(s);
163     s->IndentLess();
164 }
165
166
167 BreakpointLocationSP
168 BreakpointLocationList::GetByIndex (size_t i)
169 {
170     Mutex::Locker locker (m_mutex);
171     BreakpointLocationSP bp_loc_sp;
172     if (i < m_locations.size())
173         bp_loc_sp = m_locations[i];
174
175     return bp_loc_sp;
176 }
177
178 const BreakpointLocationSP
179 BreakpointLocationList::GetByIndex (size_t i) const
180 {
181     Mutex::Locker locker (m_mutex);
182     BreakpointLocationSP bp_loc_sp;
183     if (i < m_locations.size())
184         bp_loc_sp = m_locations[i];
185
186     return bp_loc_sp;
187 }
188
189 void
190 BreakpointLocationList::ClearAllBreakpointSites ()
191 {
192     Mutex::Locker locker (m_mutex);
193     collection::iterator pos, end = m_locations.end();
194     for (pos = m_locations.begin(); pos != end; ++pos)
195         (*pos)->ClearBreakpointSite();
196 }
197
198 void
199 BreakpointLocationList::ResolveAllBreakpointSites ()
200 {
201     Mutex::Locker locker (m_mutex);
202     collection::iterator pos, end = m_locations.end();
203
204     for (pos = m_locations.begin(); pos != end; ++pos)
205     {
206         if ((*pos)->IsEnabled())
207             (*pos)->ResolveBreakpointSite();
208     }
209 }
210
211 uint32_t
212 BreakpointLocationList::GetHitCount () const
213 {
214     uint32_t hit_count = 0;
215     Mutex::Locker locker (m_mutex);
216     collection::const_iterator pos, end = m_locations.end();
217     for (pos = m_locations.begin(); pos != end; ++pos)
218         hit_count += (*pos)->GetHitCount();
219     return hit_count;
220 }
221
222 size_t
223 BreakpointLocationList::GetNumResolvedLocations() const
224 {
225     Mutex::Locker locker (m_mutex);
226     size_t resolve_count = 0;
227     collection::const_iterator pos, end = m_locations.end();
228     for (pos = m_locations.begin(); pos != end; ++pos)
229     {
230         if ((*pos)->IsResolved())
231             ++resolve_count;
232     }
233     return resolve_count;
234 }
235
236 void
237 BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
238 {
239     Mutex::Locker locker (m_mutex);
240     collection::iterator pos, end = m_locations.end();
241
242     for (pos = m_locations.begin(); pos != end; ++pos)
243     {
244         s->Printf(" ");
245         (*pos)->GetDescription(s, level);
246     }
247 }
248
249 BreakpointLocationSP
250 BreakpointLocationList::AddLocation (const Address &addr, bool resolve_indirect_symbols, bool *new_location)
251 {
252     Mutex::Locker locker (m_mutex);
253
254     if (new_location)
255         *new_location = false;
256     BreakpointLocationSP bp_loc_sp (FindByAddress(addr));
257     if (!bp_loc_sp)
258         {
259                 bp_loc_sp = Create (addr, resolve_indirect_symbols);
260                 if (bp_loc_sp)
261                 {
262                 bp_loc_sp->ResolveBreakpointSite();
263
264                     if (new_location)
265                     *new_location = true;
266             if(m_new_location_recorder)
267             {
268                 m_new_location_recorder->Add(bp_loc_sp);
269             }
270                 }
271         }
272     return bp_loc_sp;
273 }
274
275 bool
276 BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
277 {
278     if (bp_loc_sp)
279     {
280         Mutex::Locker locker (m_mutex);
281         
282         m_address_to_location.erase (bp_loc_sp->GetAddress());
283
284         collection::iterator pos, end = m_locations.end();
285         for (pos = m_locations.begin(); pos != end; ++pos)
286         {
287             if ((*pos).get() == bp_loc_sp.get())
288             {
289                 m_locations.erase (pos);
290                 return true;
291             }
292         }
293         }
294     return false;
295 }
296
297 void
298 BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch)
299 {
300     Mutex::Locker locker (m_mutex);
301     size_t idx = 0;
302     // Don't cache m_location.size() as it will change since we might
303     // remove locations from our vector...
304     while (idx < m_locations.size())
305     {
306         BreakpointLocation *bp_loc = m_locations[idx].get();
307         if (bp_loc->GetAddress().SectionWasDeleted())
308         {
309             // Section was deleted which means this breakpoint comes from a module
310             // that is no longer valid, so we should remove it.
311             m_locations.erase(m_locations.begin() + idx);
312             continue;
313         }
314         if (arch.IsValid())
315         {
316             ModuleSP module_sp (bp_loc->GetAddress().GetModule());
317             if (module_sp)
318             {
319                 if (!arch.IsCompatibleMatch(module_sp->GetArchitecture()))
320                 {
321                     // The breakpoint was in a module whose architecture is no longer
322                     // compatible with "arch", so we need to remove it
323                     m_locations.erase(m_locations.begin() + idx);
324                     continue;
325                 }
326             }
327         }
328         // Only increment the index if we didn't remove the locations at index "idx"
329         ++idx;
330     }
331 }
332
333 void
334 BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
335 {
336     Mutex::Locker locker (m_mutex);
337     assert (m_new_location_recorder == NULL);
338     m_new_location_recorder = &new_locations;
339 }
340
341 void
342 BreakpointLocationList::StopRecordingNewLocations ()
343 {
344     Mutex::Locker locker (m_mutex);
345     m_new_location_recorder = NULL;
346 }
347