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/Breakpoint/Breakpoint.h"
18 #include "lldb/Core/Section.h"
19 #include "lldb/Target/Target.h"
20
21 using namespace lldb;
22 using namespace lldb_private;
23
BreakpointLocationList(Breakpoint & owner)24 BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) :
25 m_owner (owner),
26 m_locations(),
27 m_address_to_location (),
28 m_mutex (Mutex::eMutexTypeRecursive),
29 m_next_id (0),
30 m_new_location_recorder (NULL)
31 {
32 }
33
~BreakpointLocationList()34 BreakpointLocationList::~BreakpointLocationList()
35 {
36 }
37
38 BreakpointLocationSP
Create(const Address & addr)39 BreakpointLocationList::Create (const Address &addr)
40 {
41 Mutex::Locker locker (m_mutex);
42 // The location ID is just the size of the location list + 1
43 lldb::break_id_t bp_loc_id = ++m_next_id;
44 BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr));
45 m_locations.push_back (bp_loc_sp);
46 m_address_to_location[addr] = bp_loc_sp;
47 return bp_loc_sp;
48 }
49
50 bool
ShouldStop(StoppointCallbackContext * context,lldb::break_id_t break_id)51 BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
52 {
53 BreakpointLocationSP bp = FindByID (break_id);
54 if (bp)
55 {
56 // Let the BreakpointLocation decide if it should stop here (could not have
57 // reached it's target hit count yet, or it could have a callback
58 // that decided it shouldn't stop (shared library loads/unloads).
59 return bp->ShouldStop (context);
60 }
61 // We should stop here since this BreakpointLocation isn't valid anymore or it
62 // doesn't exist.
63 return true;
64 }
65
66 lldb::break_id_t
FindIDByAddress(const Address & addr)67 BreakpointLocationList::FindIDByAddress (const Address &addr)
68 {
69 BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
70 if (bp_loc_sp)
71 {
72 return bp_loc_sp->GetID();
73 }
74 return LLDB_INVALID_BREAK_ID;
75 }
76
77 BreakpointLocationSP
FindByID(lldb::break_id_t break_id) const78 BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
79 {
80 BreakpointLocationSP bp_loc_sp;
81 Mutex::Locker locker (m_mutex);
82 // We never remove a breakpoint locations, so the ID can be translated into
83 // the location index by subtracting 1
84 uint32_t idx = break_id - 1;
85 if (idx <= m_locations.size())
86 {
87 bp_loc_sp = m_locations[idx];
88 }
89 return bp_loc_sp;
90 }
91
92 size_t
FindInModule(Module * module,BreakpointLocationCollection & bp_loc_list)93 BreakpointLocationList::FindInModule (Module *module,
94 BreakpointLocationCollection& bp_loc_list)
95 {
96 Mutex::Locker locker (m_mutex);
97 const size_t orig_size = bp_loc_list.GetSize();
98 collection::iterator pos, end = m_locations.end();
99
100 for (pos = m_locations.begin(); pos != end; ++pos)
101 {
102 BreakpointLocationSP break_loc = (*pos);
103 SectionSP section_sp (break_loc->GetAddress().GetSection());
104 if (section_sp && section_sp->GetModule().get() == module)
105 {
106 bp_loc_list.Add (break_loc);
107 }
108 }
109 return bp_loc_list.GetSize() - orig_size;
110 }
111
112 const BreakpointLocationSP
FindByAddress(const Address & addr) const113 BreakpointLocationList::FindByAddress (const Address &addr) const
114 {
115 Mutex::Locker locker (m_mutex);
116 BreakpointLocationSP bp_loc_sp;
117 if (!m_locations.empty())
118 {
119 Address so_addr;
120
121 if (addr.IsSectionOffset())
122 {
123 so_addr = addr;
124 }
125 else
126 {
127 // Try and resolve as a load address if possible.
128 m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr);
129 if (!so_addr.IsValid())
130 {
131 // The address didn't resolve, so just set to passed in addr.
132 so_addr = addr;
133 }
134 }
135
136 addr_map::const_iterator pos = m_address_to_location.find (so_addr);
137 if (pos != m_address_to_location.end())
138 bp_loc_sp = pos->second;
139 }
140
141 return bp_loc_sp;
142 }
143
144 void
Dump(Stream * s) const145 BreakpointLocationList::Dump (Stream *s) const
146 {
147 s->Printf("%p: ", this);
148 //s->Indent();
149 Mutex::Locker locker (m_mutex);
150 s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size());
151 s->IndentMore();
152 collection::const_iterator pos, end = m_locations.end();
153 for (pos = m_locations.begin(); pos != end; ++pos)
154 (*pos).get()->Dump(s);
155 s->IndentLess();
156 }
157
158
159 BreakpointLocationSP
GetByIndex(size_t i)160 BreakpointLocationList::GetByIndex (size_t i)
161 {
162 Mutex::Locker locker (m_mutex);
163 BreakpointLocationSP bp_loc_sp;
164 if (i < m_locations.size())
165 bp_loc_sp = m_locations[i];
166
167 return bp_loc_sp;
168 }
169
170 const BreakpointLocationSP
GetByIndex(size_t i) const171 BreakpointLocationList::GetByIndex (size_t i) const
172 {
173 Mutex::Locker locker (m_mutex);
174 BreakpointLocationSP bp_loc_sp;
175 if (i < m_locations.size())
176 bp_loc_sp = m_locations[i];
177
178 return bp_loc_sp;
179 }
180
181 void
ClearAllBreakpointSites()182 BreakpointLocationList::ClearAllBreakpointSites ()
183 {
184 Mutex::Locker locker (m_mutex);
185 collection::iterator pos, end = m_locations.end();
186 for (pos = m_locations.begin(); pos != end; ++pos)
187 (*pos)->ClearBreakpointSite();
188 }
189
190 void
ResolveAllBreakpointSites()191 BreakpointLocationList::ResolveAllBreakpointSites ()
192 {
193 Mutex::Locker locker (m_mutex);
194 collection::iterator pos, end = m_locations.end();
195
196 for (pos = m_locations.begin(); pos != end; ++pos)
197 {
198 if ((*pos)->IsEnabled())
199 (*pos)->ResolveBreakpointSite();
200 }
201 }
202
203 uint32_t
GetHitCount() const204 BreakpointLocationList::GetHitCount () const
205 {
206 uint32_t hit_count = 0;
207 Mutex::Locker locker (m_mutex);
208 collection::const_iterator pos, end = m_locations.end();
209 for (pos = m_locations.begin(); pos != end; ++pos)
210 hit_count += (*pos)->GetHitCount();
211 return hit_count;
212 }
213
214 size_t
GetNumResolvedLocations() const215 BreakpointLocationList::GetNumResolvedLocations() const
216 {
217 Mutex::Locker locker (m_mutex);
218 size_t resolve_count = 0;
219 collection::const_iterator pos, end = m_locations.end();
220 for (pos = m_locations.begin(); pos != end; ++pos)
221 {
222 if ((*pos)->IsResolved())
223 ++resolve_count;
224 }
225 return resolve_count;
226 }
227
228 void
GetDescription(Stream * s,lldb::DescriptionLevel level)229 BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
230 {
231 Mutex::Locker locker (m_mutex);
232 collection::iterator pos, end = m_locations.end();
233
234 for (pos = m_locations.begin(); pos != end; ++pos)
235 {
236 s->Printf(" ");
237 (*pos)->GetDescription(s, level);
238 }
239 }
240
241 BreakpointLocationSP
AddLocation(const Address & addr,bool * new_location)242 BreakpointLocationList::AddLocation (const Address &addr, bool *new_location)
243 {
244 Mutex::Locker locker (m_mutex);
245
246 if (new_location)
247 *new_location = false;
248 BreakpointLocationSP bp_loc_sp (FindByAddress(addr));
249 if (!bp_loc_sp)
250 {
251 bp_loc_sp = Create (addr);
252 if (bp_loc_sp)
253 {
254 bp_loc_sp->ResolveBreakpointSite();
255
256 if (new_location)
257 *new_location = true;
258 if(m_new_location_recorder)
259 {
260 m_new_location_recorder->Add(bp_loc_sp);
261 }
262 }
263 }
264 return bp_loc_sp;
265 }
266
267 bool
RemoveLocation(const lldb::BreakpointLocationSP & bp_loc_sp)268 BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
269 {
270 if (bp_loc_sp)
271 {
272 Mutex::Locker locker (m_mutex);
273
274 m_address_to_location.erase (bp_loc_sp->GetAddress());
275
276 collection::iterator pos, end = m_locations.end();
277 for (pos = m_locations.begin(); pos != end; ++pos)
278 {
279 if ((*pos).get() == bp_loc_sp.get())
280 {
281 m_locations.erase (pos);
282 return true;
283 }
284 }
285 }
286 return false;
287 }
288
289
290
291 void
StartRecordingNewLocations(BreakpointLocationCollection & new_locations)292 BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
293 {
294 Mutex::Locker locker (m_mutex);
295 assert (m_new_location_recorder == NULL);
296 m_new_location_recorder = &new_locations;
297 }
298
299 void
StopRecordingNewLocations()300 BreakpointLocationList::StopRecordingNewLocations ()
301 {
302 Mutex::Locker locker (m_mutex);
303 m_new_location_recorder = NULL;
304 }
305
306