blob: 0c4c54d2f16c7263d49a43dd6c7828fe843553b3 [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"
Greg Claytonb35db632013-11-09 00:03:31 +000016
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "lldb/Breakpoint/BreakpointLocation.h"
Michael Sartainc87e7522013-07-16 21:22:53 +000018#include "lldb/Breakpoint/Breakpoint.h"
Greg Claytonb35db632013-11-09 00:03:31 +000019#include "lldb/Core/ArchSpec.h"
20#include "lldb/Core/Module.h"
Greg Clayton1f746072012-08-29 21:13:06 +000021#include "lldb/Core/Section.h"
Michael Sartainc87e7522013-07-16 21:22:53 +000022#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000023
24using namespace lldb;
25using namespace lldb_private;
26
Jim Inghame6bc6cb2012-02-08 05:23:15 +000027BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) :
Bill Wendlingc9851e22012-04-03 04:14:58 +000028 m_owner (owner),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029 m_locations(),
30 m_address_to_location (),
Jim Inghame6bc6cb2012-02-08 05:23:15 +000031 m_mutex (Mutex::eMutexTypeRecursive),
Bill Wendlingc9851e22012-04-03 04:14:58 +000032 m_next_id (0),
33 m_new_location_recorder (NULL)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034{
35}
36
37BreakpointLocationList::~BreakpointLocationList()
38{
39}
40
Greg Claytonc0d34462011-02-05 00:38:04 +000041BreakpointLocationSP
Jim Inghame6bc6cb2012-02-08 05:23:15 +000042BreakpointLocationList::Create (const Address &addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043{
Greg Claytonc0d34462011-02-05 00:38:04 +000044 Mutex::Locker locker (m_mutex);
45 // The location ID is just the size of the location list + 1
Greg Claytone72dfb32012-02-24 01:59:29 +000046 lldb::break_id_t bp_loc_id = ++m_next_id;
Greg Claytoneb023e72013-10-11 19:48:25 +000047 BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware()));
Greg Claytonc0d34462011-02-05 00:38:04 +000048 m_locations.push_back (bp_loc_sp);
49 m_address_to_location[addr] = bp_loc_sp;
50 return bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000051}
52
53bool
Greg Claytonc982c762010-07-09 20:39:50 +000054BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055{
56 BreakpointLocationSP bp = FindByID (break_id);
57 if (bp)
58 {
59 // Let the BreakpointLocation decide if it should stop here (could not have
60 // reached it's target hit count yet, or it could have a callback
61 // that decided it shouldn't stop (shared library loads/unloads).
62 return bp->ShouldStop (context);
63 }
64 // We should stop here since this BreakpointLocation isn't valid anymore or it
65 // doesn't exist.
66 return true;
67}
68
Greg Claytonc982c762010-07-09 20:39:50 +000069lldb::break_id_t
Greg Claytonc0d34462011-02-05 00:38:04 +000070BreakpointLocationList::FindIDByAddress (const Address &addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000071{
72 BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
73 if (bp_loc_sp)
74 {
75 return bp_loc_sp->GetID();
76 }
77 return LLDB_INVALID_BREAK_ID;
78}
79
Jim Ingham177553e2013-12-03 02:31:17 +000080static bool
81Compare (BreakpointLocationSP lhs, lldb::break_id_t val)
82{
83 return lhs->GetID() < val;
84}
85
Chris Lattner30fdc8d2010-06-08 16:52:24 +000086BreakpointLocationSP
Greg Claytonc982c762010-07-09 20:39:50 +000087BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +000088{
Greg Claytonc0d34462011-02-05 00:38:04 +000089 BreakpointLocationSP bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000090 Mutex::Locker locker (m_mutex);
Jim Ingham177553e2013-12-03 02:31:17 +000091
92 collection::const_iterator begin = m_locations.begin(), end = m_locations.end();
93 collection::const_iterator result;
94 result = std::lower_bound(begin, end, break_id, Compare);
95 if (result == end)
96 return bp_loc_sp;
97 else
98 return *(result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000099}
100
101size_t
102BreakpointLocationList::FindInModule (Module *module,
103 BreakpointLocationCollection& bp_loc_list)
104{
105 Mutex::Locker locker (m_mutex);
106 const size_t orig_size = bp_loc_list.GetSize();
107 collection::iterator pos, end = m_locations.end();
108
109 for (pos = m_locations.begin(); pos != end; ++pos)
110 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111 BreakpointLocationSP break_loc = (*pos);
Greg Claytone72dfb32012-02-24 01:59:29 +0000112 SectionSP section_sp (break_loc->GetAddress().GetSection());
113 if (section_sp && section_sp->GetModule().get() == module)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114 {
Johnny Chen0861be02011-08-11 21:43:13 +0000115 bp_loc_list.Add (break_loc);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116 }
117 }
118 return bp_loc_list.GetSize() - orig_size;
119}
120
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121const BreakpointLocationSP
Greg Claytonc0d34462011-02-05 00:38:04 +0000122BreakpointLocationList::FindByAddress (const Address &addr) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000123{
124 Mutex::Locker locker (m_mutex);
Greg Claytonc0d34462011-02-05 00:38:04 +0000125 BreakpointLocationSP bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000126 if (!m_locations.empty())
127 {
Michael Sartainc87e7522013-07-16 21:22:53 +0000128 Address so_addr;
129
130 if (addr.IsSectionOffset())
131 {
132 so_addr = addr;
133 }
134 else
135 {
136 // Try and resolve as a load address if possible.
137 m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr);
138 if (!so_addr.IsValid())
139 {
140 // The address didn't resolve, so just set to passed in addr.
141 so_addr = addr;
142 }
143 }
144
145 addr_map::const_iterator pos = m_address_to_location.find (so_addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000146 if (pos != m_address_to_location.end())
Greg Claytonc0d34462011-02-05 00:38:04 +0000147 bp_loc_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000148 }
149
Greg Claytonc0d34462011-02-05 00:38:04 +0000150 return bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151}
152
153void
154BreakpointLocationList::Dump (Stream *s) const
155{
Jason Molendafd54b362011-09-20 21:44:10 +0000156 s->Printf("%p: ", this);
Greg Claytonded470d2011-03-19 01:12:21 +0000157 //s->Indent();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158 Mutex::Locker locker (m_mutex);
Daniel Malead01b2952012-11-29 21:49:15 +0000159 s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160 s->IndentMore();
161 collection::const_iterator pos, end = m_locations.end();
162 for (pos = m_locations.begin(); pos != end; ++pos)
163 (*pos).get()->Dump(s);
164 s->IndentLess();
165}
166
167
168BreakpointLocationSP
Greg Claytonc7bece562013-01-25 18:06:21 +0000169BreakpointLocationList::GetByIndex (size_t i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170{
171 Mutex::Locker locker (m_mutex);
Greg Claytonc0d34462011-02-05 00:38:04 +0000172 BreakpointLocationSP bp_loc_sp;
Greg Claytonc982c762010-07-09 20:39:50 +0000173 if (i < m_locations.size())
Greg Claytonc0d34462011-02-05 00:38:04 +0000174 bp_loc_sp = m_locations[i];
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000175
Greg Claytonc0d34462011-02-05 00:38:04 +0000176 return bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000177}
178
179const BreakpointLocationSP
Greg Claytonc7bece562013-01-25 18:06:21 +0000180BreakpointLocationList::GetByIndex (size_t i) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000181{
182 Mutex::Locker locker (m_mutex);
Greg Claytonc0d34462011-02-05 00:38:04 +0000183 BreakpointLocationSP bp_loc_sp;
Greg Claytonc982c762010-07-09 20:39:50 +0000184 if (i < m_locations.size())
Greg Claytonc0d34462011-02-05 00:38:04 +0000185 bp_loc_sp = m_locations[i];
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000186
Greg Claytonc0d34462011-02-05 00:38:04 +0000187 return bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188}
189
190void
191BreakpointLocationList::ClearAllBreakpointSites ()
192{
193 Mutex::Locker locker (m_mutex);
194 collection::iterator pos, end = m_locations.end();
195 for (pos = m_locations.begin(); pos != end; ++pos)
196 (*pos)->ClearBreakpointSite();
197}
198
199void
200BreakpointLocationList::ResolveAllBreakpointSites ()
201{
202 Mutex::Locker locker (m_mutex);
203 collection::iterator pos, end = m_locations.end();
204
205 for (pos = m_locations.begin(); pos != end; ++pos)
Jim Inghamd4ce0a12010-10-20 03:36:33 +0000206 {
207 if ((*pos)->IsEnabled())
208 (*pos)->ResolveBreakpointSite();
209 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000210}
211
Greg Clayton9fed0d82010-07-23 23:33:17 +0000212uint32_t
213BreakpointLocationList::GetHitCount () const
214{
215 uint32_t hit_count = 0;
216 Mutex::Locker locker (m_mutex);
217 collection::const_iterator pos, end = m_locations.end();
218 for (pos = m_locations.begin(); pos != end; ++pos)
219 hit_count += (*pos)->GetHitCount();
220 return hit_count;
221}
222
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000223size_t
224BreakpointLocationList::GetNumResolvedLocations() const
225{
226 Mutex::Locker locker (m_mutex);
227 size_t resolve_count = 0;
228 collection::const_iterator pos, end = m_locations.end();
229 for (pos = m_locations.begin(); pos != end; ++pos)
230 {
231 if ((*pos)->IsResolved())
232 ++resolve_count;
233 }
234 return resolve_count;
235}
236
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237void
238BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
239{
240 Mutex::Locker locker (m_mutex);
241 collection::iterator pos, end = m_locations.end();
242
243 for (pos = m_locations.begin(); pos != end; ++pos)
244 {
245 s->Printf(" ");
246 (*pos)->GetDescription(s, level);
247 }
248}
249
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000250BreakpointLocationSP
251BreakpointLocationList::AddLocation (const Address &addr, bool *new_location)
252{
253 Mutex::Locker locker (m_mutex);
254
255 if (new_location)
256 *new_location = false;
257 BreakpointLocationSP bp_loc_sp (FindByAddress(addr));
258 if (!bp_loc_sp)
259 {
260 bp_loc_sp = Create (addr);
261 if (bp_loc_sp)
262 {
263 bp_loc_sp->ResolveBreakpointSite();
264
265 if (new_location)
266 *new_location = true;
267 if(m_new_location_recorder)
268 {
269 m_new_location_recorder->Add(bp_loc_sp);
270 }
271 }
272 }
273 return bp_loc_sp;
274}
275
Greg Claytone72dfb32012-02-24 01:59:29 +0000276bool
277BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
278{
279 if (bp_loc_sp)
280 {
281 Mutex::Locker locker (m_mutex);
282
283 m_address_to_location.erase (bp_loc_sp->GetAddress());
284
285 collection::iterator pos, end = m_locations.end();
286 for (pos = m_locations.begin(); pos != end; ++pos)
287 {
288 if ((*pos).get() == bp_loc_sp.get())
289 {
290 m_locations.erase (pos);
291 return true;
292 }
293 }
294 }
295 return false;
296}
297
Greg Claytonb35db632013-11-09 00:03:31 +0000298void
299BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch)
300{
301 Mutex::Locker locker (m_mutex);
302 size_t idx = 0;
303 // Don't cache m_location.size() as it will change since we might
304 // remove locations from our vector...
305 while (idx < m_locations.size())
306 {
307 BreakpointLocation *bp_loc = m_locations[idx].get();
308 if (bp_loc->GetAddress().SectionWasDeleted())
309 {
310 // Section was deleted which means this breakpoint comes from a module
311 // that is no longer valid, so we should remove it.
312 m_locations.erase(m_locations.begin() + idx);
313 continue;
314 }
315 if (arch.IsValid())
316 {
317 ModuleSP module_sp (bp_loc->GetAddress().GetModule());
318 if (module_sp)
319 {
320 if (!arch.IsCompatibleMatch(module_sp->GetArchitecture()))
321 {
322 // The breakpoint was in a module whose architecture is no longer
323 // compatible with "arch", so we need to remove it
324 m_locations.erase(m_locations.begin() + idx);
325 continue;
326 }
327 }
328 }
329 // Only increment the index if we didn't remove the locations at index "idx"
330 ++idx;
331 }
332}
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000333
334void
335BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
336{
337 Mutex::Locker locker (m_mutex);
338 assert (m_new_location_recorder == NULL);
339 m_new_location_recorder = &new_locations;
340}
341
342void
343BreakpointLocationList::StopRecordingNewLocations ()
344{
345 Mutex::Locker locker (m_mutex);
346 m_new_location_recorder = NULL;
347}
348