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