blob: 5e56299bfe78db88f071206fbd4efb4b31b93ad0 [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
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
14#include "lldb/Breakpoint/BreakpointLocationList.h"
Greg Claytonb35db632013-11-09 00:03:31 +000015
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Breakpoint/BreakpointLocation.h"
Michael Sartainc87e7522013-07-16 21:22:53 +000017#include "lldb/Breakpoint/Breakpoint.h"
Greg Claytonb35db632013-11-09 00:03:31 +000018#include "lldb/Core/ArchSpec.h"
19#include "lldb/Core/Module.h"
Greg Clayton1f746072012-08-29 21:13:06 +000020#include "lldb/Core/Section.h"
Greg Claytond5944cd2013-12-06 01:12:00 +000021#include "lldb/Target/SectionLoadList.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
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000027BreakpointLocationList::BreakpointLocationList(Breakpoint &owner)
28 : m_owner(owner), m_locations(), m_address_to_location(), m_mutex(), m_next_id(0), m_new_location_recorder(nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029{
30}
31
Eugene Zelenko16fd7512015-10-30 18:50:12 +000032BreakpointLocationList::~BreakpointLocationList() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033
Greg Claytonc0d34462011-02-05 00:38:04 +000034BreakpointLocationSP
Jim Ingham1460e4b2014-01-10 23:46:59 +000035BreakpointLocationList::Create (const Address &addr, bool resolve_indirect_symbols)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000037 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Greg Claytonc0d34462011-02-05 00:38:04 +000038 // The location ID is just the size of the location list + 1
Greg Claytone72dfb32012-02-24 01:59:29 +000039 lldb::break_id_t bp_loc_id = ++m_next_id;
Jim Ingham1460e4b2014-01-10 23:46:59 +000040 BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware(), resolve_indirect_symbols));
Greg Claytonc0d34462011-02-05 00:38:04 +000041 m_locations.push_back (bp_loc_sp);
42 m_address_to_location[addr] = bp_loc_sp;
43 return bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044}
45
46bool
Greg Claytonc982c762010-07-09 20:39:50 +000047BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000048{
49 BreakpointLocationSP bp = FindByID (break_id);
50 if (bp)
51 {
52 // Let the BreakpointLocation decide if it should stop here (could not have
53 // reached it's target hit count yet, or it could have a callback
54 // that decided it shouldn't stop (shared library loads/unloads).
55 return bp->ShouldStop (context);
56 }
57 // We should stop here since this BreakpointLocation isn't valid anymore or it
58 // doesn't exist.
59 return true;
60}
61
Greg Claytonc982c762010-07-09 20:39:50 +000062lldb::break_id_t
Greg Claytonc0d34462011-02-05 00:38:04 +000063BreakpointLocationList::FindIDByAddress (const Address &addr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064{
65 BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
66 if (bp_loc_sp)
67 {
68 return bp_loc_sp->GetID();
69 }
70 return LLDB_INVALID_BREAK_ID;
71}
72
Jim Ingham177553e2013-12-03 02:31:17 +000073static bool
74Compare (BreakpointLocationSP lhs, lldb::break_id_t val)
75{
76 return lhs->GetID() < val;
77}
78
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079BreakpointLocationSP
Greg Claytonc982c762010-07-09 20:39:50 +000080BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000082 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Greg Claytonc6b26f02013-12-03 17:50:20 +000083 collection::const_iterator end = m_locations.end();
84 collection::const_iterator pos = std::lower_bound(m_locations.begin(), end, break_id, Compare);
85 if (pos != end && (*pos)->GetID() == break_id)
86 return *(pos);
Jim Ingham177553e2013-12-03 02:31:17 +000087 else
Greg Claytonc6b26f02013-12-03 17:50:20 +000088 return BreakpointLocationSP();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089}
90
91size_t
92BreakpointLocationList::FindInModule (Module *module,
93 BreakpointLocationCollection& bp_loc_list)
94{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +000095 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096 const size_t orig_size = bp_loc_list.GetSize();
97 collection::iterator pos, end = m_locations.end();
98
99 for (pos = m_locations.begin(); pos != end; ++pos)
100 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101 BreakpointLocationSP break_loc = (*pos);
Greg Claytone72dfb32012-02-24 01:59:29 +0000102 SectionSP section_sp (break_loc->GetAddress().GetSection());
103 if (section_sp && section_sp->GetModule().get() == module)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104 {
Johnny Chen0861be02011-08-11 21:43:13 +0000105 bp_loc_list.Add (break_loc);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 }
107 }
108 return bp_loc_list.GetSize() - orig_size;
109}
110
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111const BreakpointLocationSP
Greg Claytonc0d34462011-02-05 00:38:04 +0000112BreakpointLocationList::FindByAddress (const Address &addr) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000114 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Greg Claytonc0d34462011-02-05 00:38:04 +0000115 BreakpointLocationSP bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116 if (!m_locations.empty())
117 {
Michael Sartainc87e7522013-07-16 21:22:53 +0000118 Address so_addr;
119
120 if (addr.IsSectionOffset())
121 {
122 so_addr = addr;
123 }
124 else
125 {
126 // Try and resolve as a load address if possible.
127 m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr);
128 if (!so_addr.IsValid())
129 {
130 // The address didn't resolve, so just set to passed in addr.
131 so_addr = addr;
132 }
133 }
134
135 addr_map::const_iterator pos = m_address_to_location.find (so_addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000136 if (pos != m_address_to_location.end())
Greg Claytonc0d34462011-02-05 00:38:04 +0000137 bp_loc_sp = pos->second;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138 }
139
Greg Claytonc0d34462011-02-05 00:38:04 +0000140 return bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141}
142
143void
144BreakpointLocationList::Dump (Stream *s) const
145{
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000146 s->Printf("%p: ", static_cast<const void*>(this));
Greg Claytonded470d2011-03-19 01:12:21 +0000147 //s->Indent();
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000148 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Daniel Malead01b2952012-11-29 21:49:15 +0000149 s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150 s->IndentMore();
151 collection::const_iterator pos, end = m_locations.end();
152 for (pos = m_locations.begin(); pos != end; ++pos)
153 (*pos).get()->Dump(s);
154 s->IndentLess();
155}
156
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000157BreakpointLocationSP
Greg Claytonc7bece562013-01-25 18:06:21 +0000158BreakpointLocationList::GetByIndex (size_t i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000159{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000160 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Greg Claytonc0d34462011-02-05 00:38:04 +0000161 BreakpointLocationSP bp_loc_sp;
Greg Claytonc982c762010-07-09 20:39:50 +0000162 if (i < m_locations.size())
Greg Claytonc0d34462011-02-05 00:38:04 +0000163 bp_loc_sp = m_locations[i];
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164
Greg Claytonc0d34462011-02-05 00:38:04 +0000165 return bp_loc_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000166}
167
168const BreakpointLocationSP
Greg Claytonc7bece562013-01-25 18:06:21 +0000169BreakpointLocationList::GetByIndex (size_t i) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000171 std::lock_guard<std::recursive_mutex> guard(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
179void
180BreakpointLocationList::ClearAllBreakpointSites ()
181{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000182 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000183 collection::iterator pos, end = m_locations.end();
184 for (pos = m_locations.begin(); pos != end; ++pos)
185 (*pos)->ClearBreakpointSite();
186}
187
188void
189BreakpointLocationList::ResolveAllBreakpointSites ()
190{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000191 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000192 collection::iterator pos, end = m_locations.end();
193
194 for (pos = m_locations.begin(); pos != end; ++pos)
Jim Inghamd4ce0a12010-10-20 03:36:33 +0000195 {
196 if ((*pos)->IsEnabled())
197 (*pos)->ResolveBreakpointSite();
198 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000199}
200
Greg Clayton9fed0d82010-07-23 23:33:17 +0000201uint32_t
202BreakpointLocationList::GetHitCount () const
203{
204 uint32_t hit_count = 0;
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000205 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Greg Clayton9fed0d82010-07-23 23:33:17 +0000206 collection::const_iterator pos, end = m_locations.end();
207 for (pos = m_locations.begin(); pos != end; ++pos)
208 hit_count += (*pos)->GetHitCount();
209 return hit_count;
210}
211
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000212size_t
213BreakpointLocationList::GetNumResolvedLocations() const
214{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000215 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000216 size_t resolve_count = 0;
217 collection::const_iterator pos, end = m_locations.end();
218 for (pos = m_locations.begin(); pos != end; ++pos)
219 {
220 if ((*pos)->IsResolved())
221 ++resolve_count;
222 }
223 return resolve_count;
224}
225
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226void
227BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
228{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000229 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000230 collection::iterator pos, end = m_locations.end();
231
232 for (pos = m_locations.begin(); pos != end; ++pos)
233 {
234 s->Printf(" ");
235 (*pos)->GetDescription(s, level);
236 }
237}
238
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000239BreakpointLocationSP
Jim Ingham1460e4b2014-01-10 23:46:59 +0000240BreakpointLocationList::AddLocation (const Address &addr, bool resolve_indirect_symbols, bool *new_location)
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000241{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000242 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000243
244 if (new_location)
245 *new_location = false;
246 BreakpointLocationSP bp_loc_sp (FindByAddress(addr));
247 if (!bp_loc_sp)
248 {
Jim Ingham1460e4b2014-01-10 23:46:59 +0000249 bp_loc_sp = Create (addr, resolve_indirect_symbols);
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000250 if (bp_loc_sp)
251 {
252 bp_loc_sp->ResolveBreakpointSite();
253
254 if (new_location)
255 *new_location = true;
256 if(m_new_location_recorder)
257 {
258 m_new_location_recorder->Add(bp_loc_sp);
259 }
260 }
261 }
262 return bp_loc_sp;
263}
264
Jim Ingham77fd7382014-09-10 21:40:47 +0000265void
266BreakpointLocationList::SwapLocation (BreakpointLocationSP to_location_sp, BreakpointLocationSP from_location_sp)
267{
268 if (!from_location_sp || !to_location_sp)
269 return;
270
271 m_address_to_location.erase(to_location_sp->GetAddress());
272 to_location_sp->SwapLocation(from_location_sp);
273 RemoveLocation(from_location_sp);
274 m_address_to_location[to_location_sp->GetAddress()] = to_location_sp;
275 to_location_sp->ResolveBreakpointSite();
276}
277
Greg Claytone72dfb32012-02-24 01:59:29 +0000278bool
279BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
280{
281 if (bp_loc_sp)
282 {
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000283 std::lock_guard<std::recursive_mutex> guard(m_mutex);
284
Greg Claytone72dfb32012-02-24 01:59:29 +0000285 m_address_to_location.erase (bp_loc_sp->GetAddress());
286
287 collection::iterator pos, end = m_locations.end();
288 for (pos = m_locations.begin(); pos != end; ++pos)
289 {
290 if ((*pos).get() == bp_loc_sp.get())
291 {
292 m_locations.erase (pos);
293 return true;
294 }
295 }
Eugene Zelenko16fd7512015-10-30 18:50:12 +0000296 }
Greg Claytone72dfb32012-02-24 01:59:29 +0000297 return false;
298}
299
Greg Claytonb35db632013-11-09 00:03:31 +0000300void
301BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch)
302{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000303 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Greg Claytonb35db632013-11-09 00:03:31 +0000304 size_t idx = 0;
305 // Don't cache m_location.size() as it will change since we might
306 // remove locations from our vector...
307 while (idx < m_locations.size())
308 {
309 BreakpointLocation *bp_loc = m_locations[idx].get();
310 if (bp_loc->GetAddress().SectionWasDeleted())
311 {
312 // Section was deleted which means this breakpoint comes from a module
313 // that is no longer valid, so we should remove it.
314 m_locations.erase(m_locations.begin() + idx);
315 continue;
316 }
317 if (arch.IsValid())
318 {
319 ModuleSP module_sp (bp_loc->GetAddress().GetModule());
320 if (module_sp)
321 {
322 if (!arch.IsCompatibleMatch(module_sp->GetArchitecture()))
323 {
324 // The breakpoint was in a module whose architecture is no longer
325 // compatible with "arch", so we need to remove it
326 m_locations.erase(m_locations.begin() + idx);
327 continue;
328 }
329 }
330 }
331 // Only increment the index if we didn't remove the locations at index "idx"
332 ++idx;
333 }
334}
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000335
336void
337BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
338{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000339 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Eugene Zelenko16fd7512015-10-30 18:50:12 +0000340 assert(m_new_location_recorder == nullptr);
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000341 m_new_location_recorder = &new_locations;
342}
343
344void
345BreakpointLocationList::StopRecordingNewLocations ()
346{
Saleem Abdulrasool16ff8602016-05-18 01:59:10 +0000347 std::lock_guard<std::recursive_mutex> guard(m_mutex);
Eugene Zelenko16fd7512015-10-30 18:50:12 +0000348 m_new_location_recorder = nullptr;
Jim Inghame6bc6cb2012-02-08 05:23:15 +0000349}
350
Jim Ingham77fd7382014-09-10 21:40:47 +0000351void
352BreakpointLocationList::Compact()
353{
354 lldb::break_id_t highest_id = 0;
355
356 for (BreakpointLocationSP loc_sp : m_locations)
357 {
358 lldb::break_id_t cur_id = loc_sp->GetID();
359 if (cur_id > highest_id)
360 highest_id = cur_id;
361 }
362 m_next_id = highest_id;
363}