1 //===-- Breakpoint.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 
16 #include "lldb/Core/Address.h"
17 #include "lldb/Breakpoint/Breakpoint.h"
18 #include "lldb/Breakpoint/BreakpointLocation.h"
19 #include "lldb/Breakpoint/BreakpointResolver.h"
20 #include "lldb/Core/Log.h"
21 #include "lldb/Core/ModuleList.h"
22 #include "lldb/Core/SearchFilter.h"
23 #include "lldb/Core/Stream.h"
24 #include "lldb/Core/StreamString.h"
25 #include "lldb/Symbol/SymbolContext.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/lldb-private-log.h"
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 const ConstString &
33 Breakpoint::GetEventIdentifier ()
34 {
35     static ConstString g_identifier("event-identifier.breakpoint.changed");
36     return g_identifier;
37 }
38 
39 //----------------------------------------------------------------------
40 // Breakpoint constructor
41 //----------------------------------------------------------------------
42 Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) :
43     m_target (target),
44     m_filter_sp (filter_sp),
45     m_resolver_sp (resolver_sp),
46     m_options (),
47     m_locations ()
48 {
49 }
50 
51 //----------------------------------------------------------------------
52 // Destructor
53 //----------------------------------------------------------------------
54 Breakpoint::~Breakpoint()
55 {
56 }
57 
58 bool
59 Breakpoint::IsInternal () const
60 {
61     return LLDB_BREAK_ID_IS_INTERNAL(m_bid);
62 }
63 
64 
65 
66 Target&
67 Breakpoint::GetTarget ()
68 {
69     return m_target;
70 }
71 
72 const Target&
73 Breakpoint::GetTarget () const
74 {
75     return m_target;
76 }
77 
78 BreakpointLocationSP
79 Breakpoint::AddLocation (Address &addr, bool *new_location)
80 {
81     BreakpointLocationSP bp_loc_sp (m_locations.FindByAddress(addr));
82     if (bp_loc_sp)
83     {
84         if (new_location)
85             *new_location = false;
86         return bp_loc_sp;
87     }
88 
89     bp_loc_sp.reset (new BreakpointLocation (m_locations.GetNextID(), *this, addr));
90     m_locations.Add (bp_loc_sp);
91     bp_loc_sp->ResolveBreakpointSite();
92 
93     if (new_location)
94         *new_location = true;
95     return bp_loc_sp;
96 }
97 
98 BreakpointLocationSP
99 Breakpoint::FindLocationByAddress (Address &addr)
100 {
101     return m_locations.FindByAddress(addr);
102 }
103 
104 break_id_t
105 Breakpoint::FindLocationIDByAddress (Address &addr)
106 {
107     return m_locations.FindIDByAddress(addr);
108 }
109 
110 BreakpointLocationSP
111 Breakpoint::FindLocationByID (break_id_t bp_loc_id)
112 {
113     return m_locations.FindByID(bp_loc_id);
114 }
115 
116 BreakpointLocationSP
117 Breakpoint::GetLocationAtIndex (uint32_t index)
118 {
119     return m_locations.GetByIndex(index);
120 }
121 
122 BreakpointLocationSP
123 Breakpoint::GetLocationSP (BreakpointLocation *bp_loc_ptr)
124 {
125     assert (bp_loc_ptr->GetBreakpoint().GetID() == GetID());
126     return m_locations.FindByID(bp_loc_ptr->GetID());
127 }
128 
129 
130 // For each of the overall options we need to decide how they propagate to
131 // the location options.  This will determine the precedence of options on
132 // the breakpoint vrs. its locations.
133 
134 // Disable at the breakpoint level should override the location settings.
135 // That way you can conveniently turn off a whole breakpoint without messing
136 // up the individual settings.
137 
138 void
139 Breakpoint::SetEnabled (bool enable)
140 {
141     m_options.SetEnabled(enable);
142     if (enable)
143         m_locations.ResolveAllBreakpointSites();
144     else
145         m_locations.ClearAllBreakpointSites();
146 }
147 
148 bool
149 Breakpoint::IsEnabled ()
150 {
151     return m_options.IsEnabled();
152 }
153 
154 void
155 Breakpoint::SetIgnoreCount (int32_t n)
156 {
157     m_options.SetIgnoreCount(n);
158 }
159 
160 int32_t
161 Breakpoint::GetIgnoreCount () const
162 {
163     return m_options.GetIgnoreCount();
164 }
165 
166 void
167 Breakpoint::SetThreadID (lldb::tid_t thread_id)
168 {
169     m_options.SetThreadID(thread_id);
170 }
171 
172 lldb::tid_t
173 Breakpoint::GetThreadID ()
174 {
175     return m_options.GetThreadID();
176 }
177 
178 // This function is used when "baton" doesn't need to be freed
179 void
180 Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous)
181 {
182     // The default "Baton" class will keep a copy of "baton" and won't free
183     // or delete it when it goes goes out of scope.
184     m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
185 }
186 
187 // This function is used when a baton needs to be freed and therefore is
188 // contained in a "Baton" subclass.
189 void
190 Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
191 {
192     m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
193 }
194 
195 void
196 Breakpoint::ClearCallback ()
197 {
198     m_options.ClearCallback ();
199 }
200 
201 bool
202 Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id)
203 {
204     return m_options.InvokeCallback (context, GetID(), bp_loc_id);
205 }
206 
207 BreakpointOptions *
208 Breakpoint::GetOptions ()
209 {
210     return &m_options;
211 }
212 
213 void
214 Breakpoint::ResolveBreakpoint ()
215 {
216     if (m_resolver_sp)
217         m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
218 }
219 
220 void
221 Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
222 {
223     if (m_resolver_sp)
224         m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
225 }
226 
227 void
228 Breakpoint::ClearAllBreakpointSites ()
229 {
230     m_locations.ClearAllBreakpointSites();
231 }
232 
233 //----------------------------------------------------------------------
234 // ModulesChanged: Pass in a list of new modules, and
235 //----------------------------------------------------------------------
236 
237 void
238 Breakpoint::ModulesChanged (ModuleList &module_list, bool load)
239 {
240     if (load)
241     {
242         // The logic for handling new modules is:
243         // 1) If the filter rejects this module, then skip it.
244         // 2) Run through the current location list and if there are any locations
245         //    for that module, we mark the module as "seen" and we don't try to re-resolve
246         //    breakpoint locations for that module.
247         //    However, we do add breakpoint sites to these locations if needed.
248         // 3) If we don't see this module in our breakpoint location list, call ResolveInModules.
249 
250         ModuleList new_modules;  // We'll stuff the "unseen" modules in this list, and then resolve
251                                    // them after the locations pass.  Have to do it this way because
252                                    // resolving breakpoints will add new locations potentially.
253 
254         for (int i = 0; i < module_list.GetSize(); i++)
255         {
256             bool seen = false;
257             ModuleSP module_sp (module_list.GetModuleAtIndex (i));
258             Module *module = module_sp.get();
259             if (!m_filter_sp->ModulePasses (module_sp))
260                 continue;
261 
262             for (int i = 0; i < m_locations.GetSize(); i++)
263             {
264                 BreakpointLocationSP break_loc = m_locations.GetByIndex(i);
265                 const Section *section = break_loc->GetAddress().GetSection();
266                 if (section == NULL || section->GetModule() == module)
267                 {
268                     if (!seen)
269                         seen = true;
270 
271                     if (!break_loc->ResolveBreakpointSite())
272                     {
273                         Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
274                         if (log)
275                             log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n",
276                                          break_loc->GetID(), GetID());
277                     }
278                 }
279             }
280 
281             if (!seen)
282                 new_modules.AppendInNeeded (module_sp);
283 
284         }
285         if (new_modules.GetSize() > 0)
286         {
287             ResolveBreakpointInModules(new_modules);
288         }
289     }
290     else
291     {
292         // Go through the currently set locations and if any have breakpoints in
293         // the module list, then remove their breakpoint sites.
294         // FIXME: Think about this...  Maybe it's better to delete the locations?
295         // Are we sure that on load-unload-reload the module pointer will remain
296         // the same?  Or do we need to do an equality on modules that is an
297         // "equivalence"???
298 
299         for (int i = 0; i < module_list.GetSize(); i++)
300         {
301             ModuleSP module_sp (module_list.GetModuleAtIndex (i));
302             if (!m_filter_sp->ModulePasses (module_sp))
303                 continue;
304 
305             for (int i = 0; i < m_locations.GetSize(); i++)
306             {
307                 BreakpointLocationSP break_loc = m_locations.GetByIndex(i);
308                 const Section *section = break_loc->GetAddress().GetSection();
309                 if (section)
310                 {
311                     if (section->GetModule() == module_sp.get())
312                         break_loc->ClearBreakpointSite();
313                 }
314 //                else
315 //                {
316 //                    Address temp_addr;
317 //                    if (module->ResolveLoadAddress(break_loc->GetLoadAddress(), m_target->GetProcess(), temp_addr))
318 //                        break_loc->ClearBreakpointSite();
319 //                }
320             }
321         }
322     }
323 }
324 
325 void
326 Breakpoint::Dump (Stream *)
327 {
328 }
329 
330 size_t
331 Breakpoint::GetNumResolvedLocations() const
332 {
333     // Return the number of breakpoints that are actually resolved and set
334     // down in the inferior process.
335     return m_locations.GetNumResolvedLocations();
336 }
337 
338 size_t
339 Breakpoint::GetNumLocations() const
340 {
341     return m_locations.GetSize();
342 }
343 
344 void
345 Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
346 {
347     assert (s != NULL);
348     StreamString filter_strm;
349 
350 
351     s->Printf("%i ", GetID());
352     GetResolverDescription (s);
353     GetFilterDescription (&filter_strm);
354     if (filter_strm.GetString().compare ("No Filter") != 0)
355     {
356         s->Printf (", ");
357         GetFilterDescription (s);
358     }
359 
360     const uint32_t num_locations = GetNumLocations ();
361     const uint32_t num_resolved_locations = GetNumResolvedLocations ();
362 
363     switch (level)
364     {
365     case lldb::eDescriptionLevelBrief:
366     case lldb::eDescriptionLevelFull:
367         if (num_locations > 0)
368         {
369             s->Printf(" with %u location%s", num_locations, num_locations > 1 ? "s" : "");
370             if (num_resolved_locations > 0)
371                 s->Printf(" (%u resolved)", num_resolved_locations);
372             s->PutChar(';');
373         }
374         else
375         {
376             s->Printf(" with 0 locations (Pending Breakpoint).");
377         }
378 
379         if (level == lldb::eDescriptionLevelFull)
380         {
381             Baton *baton = GetOptions()->GetBaton();
382             if (baton)
383             {
384                 s->EOL ();
385                 s->Indent();
386                 baton->GetDescription(s, level);
387             }
388         }
389         break;
390 
391     case lldb::eDescriptionLevelVerbose:
392         // Verbose mode does a debug dump of the breakpoint
393         Dump (s);
394         Baton *baton = GetOptions()->GetBaton();
395         if (baton)
396         {
397             s->EOL ();
398             s->Indent();
399             baton->GetDescription(s, level);
400         }
401         break;
402     }
403 
404     if (show_locations)
405     {
406         s->EOL();
407         s->IndentMore();
408         for (int i = 0; i < GetNumLocations(); ++i)
409         {
410             BreakpointLocation *loc = GetLocationAtIndex(i).get();
411             loc->GetDescription(s, level);
412             s->EOL();
413         }
414         s->IndentLess();
415 
416     }
417 }
418 
419 Breakpoint::BreakpointEventData::BreakpointEventData (Breakpoint::BreakpointEventData::EventSubType sub_type, BreakpointSP &new_breakpoint_sp) :
420     EventData (),
421     m_sub_type (sub_type),
422     m_new_breakpoint_sp (new_breakpoint_sp)
423 {
424 }
425 
426 Breakpoint::BreakpointEventData::~BreakpointEventData ()
427 {
428 }
429 
430 const ConstString &
431 Breakpoint::BreakpointEventData::GetFlavorString ()
432 {
433     static ConstString g_flavor ("Breakpoint::BreakpointEventData");
434     return g_flavor;
435 }
436 
437 const ConstString &
438 Breakpoint::BreakpointEventData::GetFlavor () const
439 {
440     return BreakpointEventData::GetFlavorString ();
441 }
442 
443 
444 BreakpointSP &
445 Breakpoint::BreakpointEventData::GetBreakpoint ()
446 {
447     return m_new_breakpoint_sp;
448 }
449 
450 Breakpoint::BreakpointEventData::EventSubType
451 Breakpoint::BreakpointEventData::GetSubType () const
452 {
453     return m_sub_type;
454 }
455 
456 void
457 Breakpoint::BreakpointEventData::Dump (Stream *s) const
458 {
459 }
460 
461 Breakpoint::BreakpointEventData *
462 Breakpoint::BreakpointEventData::GetEventDataFromEvent (const EventSP &event_sp)
463 {
464     if (event_sp)
465     {
466         EventData *event_data = event_sp->GetData();
467         if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
468             return static_cast <BreakpointEventData *> (event_sp->GetData());
469     }
470     return NULL;
471 }
472 
473 Breakpoint::BreakpointEventData::EventSubType
474 Breakpoint::BreakpointEventData::GetSubTypeFromEvent (const EventSP &event_sp)
475 {
476     BreakpointEventData *data = GetEventDataFromEvent (event_sp);
477 
478     if (data == NULL)
479         return eBreakpointInvalidType;
480     else
481         return data->GetSubType();
482 }
483 
484 BreakpointSP
485 Breakpoint::BreakpointEventData::GetBreakpointFromEvent (const EventSP &event_sp)
486 {
487     BreakpointEventData *data = GetEventDataFromEvent (event_sp);
488 
489     if (data == NULL)
490     {
491         BreakpointSP ret_val;
492         return ret_val;
493     }
494     else
495         return data->GetBreakpoint();
496 }
497 
498 
499 void
500 Breakpoint::GetResolverDescription (Stream *s)
501 {
502     if (m_resolver_sp)
503         m_resolver_sp->GetDescription (s);
504 }
505 
506 void
507 Breakpoint::GetFilterDescription (Stream *s)
508 {
509     m_filter_sp->GetDescription (s);
510 }
511 
512 const BreakpointSP
513 Breakpoint::GetSP ()
514 {
515     return m_target.GetBreakpointList().FindBreakpointByID (GetID());
516 }
517