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