blob: c475cf0f0d798976dfa920532a8dc364b246cead [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
29using namespace lldb;
30using namespace lldb_private;
31
32const ConstString &
33Breakpoint::GetEventIdentifier ()
34{
35 static ConstString g_identifier("event-identifier.breakpoint.changed");
36 return g_identifier;
37}
38
39//----------------------------------------------------------------------
40// Breakpoint constructor
41//----------------------------------------------------------------------
42Breakpoint::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//----------------------------------------------------------------------
54Breakpoint::~Breakpoint()
55{
56}
57
58bool
59Breakpoint::IsInternal () const
60{
61 return LLDB_BREAK_ID_IS_INTERNAL(m_bid);
62}
63
64
65
66Target&
67Breakpoint::GetTarget ()
68{
69 return m_target;
70}
71
72const Target&
73Breakpoint::GetTarget () const
74{
75 return m_target;
76}
77
78BreakpointLocationSP
79Breakpoint::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
98BreakpointLocationSP
99Breakpoint::FindLocationByAddress (Address &addr)
100{
101 return m_locations.FindByAddress(addr);
102}
103
104break_id_t
105Breakpoint::FindLocationIDByAddress (Address &addr)
106{
107 return m_locations.FindIDByAddress(addr);
108}
109
110BreakpointLocationSP
111Breakpoint::FindLocationByID (break_id_t bp_loc_id)
112{
113 return m_locations.FindByID(bp_loc_id);
114}
115
116BreakpointLocationSP
117Breakpoint::GetLocationAtIndex (uint32_t index)
118{
119 return m_locations.GetByIndex(index);
120}
121
122BreakpointLocationSP
123Breakpoint::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
138void
139Breakpoint::SetEnabled (bool enable)
140{
141 m_options.SetEnabled(enable);
142 if (enable)
143 m_locations.ResolveAllBreakpointSites();
144 else
145 m_locations.ClearAllBreakpointSites();
146}
147
148bool
149Breakpoint::IsEnabled ()
150{
151 return m_options.IsEnabled();
152}
153
154void
155Breakpoint::SetIgnoreCount (int32_t n)
156{
157 m_options.SetIgnoreCount(n);
158}
159
160int32_t
161Breakpoint::GetIgnoreCount () const
162{
163 return m_options.GetIgnoreCount();
164}
165
166void
167Breakpoint::SetThreadID (lldb::tid_t thread_id)
168{
169 m_options.SetThreadID(thread_id);
170}
171
172lldb::tid_t
173Breakpoint::GetThreadID ()
174{
175 return m_options.GetThreadID();
176}
177
178// This function is used when "baton" doesn't need to be freed
179void
180Breakpoint::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.
189void
190Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
191{
192 m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
193}
194
195void
196Breakpoint::ClearCallback ()
197{
198 m_options.ClearCallback ();
199}
200
201bool
202Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id)
203{
204 return m_options.InvokeCallback (context, GetID(), bp_loc_id);
205}
206
207BreakpointOptions *
208Breakpoint::GetOptions ()
209{
210 return &m_options;
211}
212
213void
214Breakpoint::ResolveBreakpoint ()
215{
216 if (m_resolver_sp)
217 m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
218}
219
220void
221Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
222{
223 if (m_resolver_sp)
224 m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
225}
226
227void
228Breakpoint::ClearAllBreakpointSites ()
229{
230 m_locations.ClearAllBreakpointSites();
231}
232
233//----------------------------------------------------------------------
234// ModulesChanged: Pass in a list of new modules, and
235//----------------------------------------------------------------------
236
237void
238Breakpoint::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
325void
326Breakpoint::Dump (Stream *)
327{
328}
329
330size_t
331Breakpoint::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
338size_t
339Breakpoint::GetNumLocations() const
340{
341 return m_locations.GetSize();
342}
343
344void
345Breakpoint::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
419Breakpoint::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
426Breakpoint::BreakpointEventData::~BreakpointEventData ()
427{
428}
429
430const ConstString &
431Breakpoint::BreakpointEventData::GetFlavorString ()
432{
433 static ConstString g_flavor ("Breakpoint::BreakpointEventData");
434 return g_flavor;
435}
436
437const ConstString &
438Breakpoint::BreakpointEventData::GetFlavor () const
439{
440 return BreakpointEventData::GetFlavorString ();
441}
442
443
444BreakpointSP &
445Breakpoint::BreakpointEventData::GetBreakpoint ()
446{
447 return m_new_breakpoint_sp;
448}
449
450Breakpoint::BreakpointEventData::EventSubType
451Breakpoint::BreakpointEventData::GetSubType () const
452{
453 return m_sub_type;
454}
455
456void
457Breakpoint::BreakpointEventData::Dump (Stream *s) const
458{
459}
460
461Breakpoint::BreakpointEventData *
462Breakpoint::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
473Breakpoint::BreakpointEventData::EventSubType
474Breakpoint::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
484BreakpointSP
485Breakpoint::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
499void
500Breakpoint::GetResolverDescription (Stream *s)
501{
502 if (m_resolver_sp)
503 m_resolver_sp->GetDescription (s);
504}
505
506void
507Breakpoint::GetFilterDescription (Stream *s)
508{
509 m_filter_sp->GetDescription (s);
510}
511
512const BreakpointSP
513Breakpoint::GetSP ()
514{
515 return m_target.GetBreakpointList().FindBreakpointByID (GetID());
516}