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