blob: 4fa77dd7135b8ca799120255441fde4a8238284f [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"
Johnny Chena62ad7c2010-10-28 17:27:46 +000019#include "lldb/Breakpoint/BreakpointLocationCollection.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Breakpoint/BreakpointResolver.h"
Johnny Chena62ad7c2010-10-28 17:27:46 +000021#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Core/Log.h"
23#include "lldb/Core/ModuleList.h"
24#include "lldb/Core/SearchFilter.h"
25#include "lldb/Core/Stream.h"
26#include "lldb/Core/StreamString.h"
27#include "lldb/Symbol/SymbolContext.h"
28#include "lldb/Target/Target.h"
Jim Ingham3c7b5b92010-06-16 02:00:15 +000029#include "lldb/Target/ThreadSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000030#include "lldb/lldb-private-log.h"
Johnny Chena62ad7c2010-10-28 17:27:46 +000031#include "llvm/Support/Casting.h"
Chris Lattner24943d22010-06-08 16:52:24 +000032
33using namespace lldb;
34using namespace lldb_private;
Johnny Chena62ad7c2010-10-28 17:27:46 +000035using namespace llvm;
Chris Lattner24943d22010-06-08 16:52:24 +000036
37const ConstString &
38Breakpoint::GetEventIdentifier ()
39{
40 static ConstString g_identifier("event-identifier.breakpoint.changed");
41 return g_identifier;
42}
43
44//----------------------------------------------------------------------
45// Breakpoint constructor
46//----------------------------------------------------------------------
47Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) :
48 m_target (target),
49 m_filter_sp (filter_sp),
50 m_resolver_sp (resolver_sp),
51 m_options (),
52 m_locations ()
53{
54}
55
56//----------------------------------------------------------------------
57// Destructor
58//----------------------------------------------------------------------
59Breakpoint::~Breakpoint()
60{
61}
62
63bool
64Breakpoint::IsInternal () const
65{
66 return LLDB_BREAK_ID_IS_INTERNAL(m_bid);
67}
68
69
70
71Target&
72Breakpoint::GetTarget ()
73{
74 return m_target;
75}
76
77const Target&
78Breakpoint::GetTarget () const
79{
80 return m_target;
81}
82
83BreakpointLocationSP
Greg Clayton19a1ab82011-02-05 00:38:04 +000084Breakpoint::AddLocation (const Address &addr, bool *new_location)
Chris Lattner24943d22010-06-08 16:52:24 +000085{
Chris Lattner24943d22010-06-08 16:52:24 +000086 if (new_location)
Greg Clayton19a1ab82011-02-05 00:38:04 +000087 *new_location = false;
88 BreakpointLocationSP bp_loc_sp (m_locations.FindByAddress(addr));
89 if (!bp_loc_sp)
90 {
91 bp_loc_sp = m_locations.Create (*this, addr);
92 if (bp_loc_sp)
93 {
94 bp_loc_sp->ResolveBreakpointSite();
95
96 if (new_location)
97 *new_location = true;
98 }
99 }
Chris Lattner24943d22010-06-08 16:52:24 +0000100 return bp_loc_sp;
101}
102
103BreakpointLocationSP
Greg Clayton19a1ab82011-02-05 00:38:04 +0000104Breakpoint::FindLocationByAddress (const Address &addr)
Chris Lattner24943d22010-06-08 16:52:24 +0000105{
106 return m_locations.FindByAddress(addr);
107}
108
109break_id_t
Greg Clayton19a1ab82011-02-05 00:38:04 +0000110Breakpoint::FindLocationIDByAddress (const Address &addr)
Chris Lattner24943d22010-06-08 16:52:24 +0000111{
112 return m_locations.FindIDByAddress(addr);
113}
114
115BreakpointLocationSP
116Breakpoint::FindLocationByID (break_id_t bp_loc_id)
117{
118 return m_locations.FindByID(bp_loc_id);
119}
120
121BreakpointLocationSP
122Breakpoint::GetLocationAtIndex (uint32_t index)
123{
124 return m_locations.GetByIndex(index);
125}
126
127BreakpointLocationSP
128Breakpoint::GetLocationSP (BreakpointLocation *bp_loc_ptr)
129{
Chris Lattner24943d22010-06-08 16:52:24 +0000130 return m_locations.FindByID(bp_loc_ptr->GetID());
131}
132
133
134// For each of the overall options we need to decide how they propagate to
135// the location options. This will determine the precedence of options on
136// the breakpoint vrs. its locations.
137
138// Disable at the breakpoint level should override the location settings.
139// That way you can conveniently turn off a whole breakpoint without messing
140// up the individual settings.
141
142void
143Breakpoint::SetEnabled (bool enable)
144{
145 m_options.SetEnabled(enable);
146 if (enable)
147 m_locations.ResolveAllBreakpointSites();
148 else
149 m_locations.ClearAllBreakpointSites();
150}
151
152bool
153Breakpoint::IsEnabled ()
154{
155 return m_options.IsEnabled();
156}
157
158void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000159Breakpoint::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000160{
161 m_options.SetIgnoreCount(n);
162}
163
Greg Clayton54e7afa2010-07-09 20:39:50 +0000164uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000165Breakpoint::GetIgnoreCount () const
166{
167 return m_options.GetIgnoreCount();
168}
169
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000170uint32_t
171Breakpoint::GetHitCount () const
172{
173 return m_locations.GetHitCount();
174}
175
Chris Lattner24943d22010-06-08 16:52:24 +0000176void
177Breakpoint::SetThreadID (lldb::tid_t thread_id)
178{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000179 m_options.GetThreadSpec()->SetTID(thread_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000180}
181
182lldb::tid_t
183Breakpoint::GetThreadID ()
184{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000185 if (m_options.GetThreadSpec() == NULL)
186 return LLDB_INVALID_THREAD_ID;
187 else
188 return m_options.GetThreadSpec()->GetTID();
Chris Lattner24943d22010-06-08 16:52:24 +0000189}
190
Jim Inghamd1686902010-10-14 23:45:03 +0000191void
192Breakpoint::SetCondition (const char *condition)
193{
194 m_options.SetCondition (condition);
195}
196
197ThreadPlan *
198Breakpoint::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, lldb::BreakpointLocationSP loc_sp, Stream &error)
199{
200 return m_options.GetThreadPlanToTestCondition (exe_ctx, loc_sp, error);
201}
202
203const char *
Jim Inghamac354422011-06-15 21:16:00 +0000204Breakpoint::GetConditionText () const
Jim Inghamd1686902010-10-14 23:45:03 +0000205{
206 return m_options.GetConditionText();
207}
208
Chris Lattner24943d22010-06-08 16:52:24 +0000209// This function is used when "baton" doesn't need to be freed
210void
211Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous)
212{
213 // The default "Baton" class will keep a copy of "baton" and won't free
214 // or delete it when it goes goes out of scope.
215 m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
216}
217
218// This function is used when a baton needs to be freed and therefore is
219// contained in a "Baton" subclass.
220void
221Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
222{
223 m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
224}
225
226void
227Breakpoint::ClearCallback ()
228{
229 m_options.ClearCallback ();
230}
231
232bool
233Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id)
234{
235 return m_options.InvokeCallback (context, GetID(), bp_loc_id);
236}
237
238BreakpointOptions *
239Breakpoint::GetOptions ()
240{
241 return &m_options;
242}
243
244void
245Breakpoint::ResolveBreakpoint ()
246{
247 if (m_resolver_sp)
248 m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
249}
250
251void
252Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
253{
254 if (m_resolver_sp)
255 m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
256}
257
258void
259Breakpoint::ClearAllBreakpointSites ()
260{
261 m_locations.ClearAllBreakpointSites();
262}
263
264//----------------------------------------------------------------------
265// ModulesChanged: Pass in a list of new modules, and
266//----------------------------------------------------------------------
267
268void
269Breakpoint::ModulesChanged (ModuleList &module_list, bool load)
270{
271 if (load)
272 {
273 // The logic for handling new modules is:
274 // 1) If the filter rejects this module, then skip it.
275 // 2) Run through the current location list and if there are any locations
276 // for that module, we mark the module as "seen" and we don't try to re-resolve
277 // breakpoint locations for that module.
278 // However, we do add breakpoint sites to these locations if needed.
279 // 3) If we don't see this module in our breakpoint location list, call ResolveInModules.
280
281 ModuleList new_modules; // We'll stuff the "unseen" modules in this list, and then resolve
Greg Clayton19a1ab82011-02-05 00:38:04 +0000282 // them after the locations pass. Have to do it this way because
283 // resolving breakpoints will add new locations potentially.
284
285 const size_t num_locs = m_locations.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000286
Greg Clayton54e7afa2010-07-09 20:39:50 +0000287 for (size_t i = 0; i < module_list.GetSize(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000288 {
289 bool seen = false;
290 ModuleSP module_sp (module_list.GetModuleAtIndex (i));
Chris Lattner24943d22010-06-08 16:52:24 +0000291 if (!m_filter_sp->ModulePasses (module_sp))
292 continue;
293
Greg Clayton19a1ab82011-02-05 00:38:04 +0000294 for (size_t loc_idx = 0; loc_idx < num_locs; loc_idx++)
Chris Lattner24943d22010-06-08 16:52:24 +0000295 {
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000296 BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx);
Jim Ingham1de036b2010-10-20 03:36:33 +0000297 if (!break_loc->IsEnabled())
298 continue;
Chris Lattner24943d22010-06-08 16:52:24 +0000299 const Section *section = break_loc->GetAddress().GetSection();
Greg Clayton19a1ab82011-02-05 00:38:04 +0000300 if (section == NULL || section->GetModule() == module_sp.get())
Chris Lattner24943d22010-06-08 16:52:24 +0000301 {
302 if (!seen)
303 seen = true;
304
305 if (!break_loc->ResolveBreakpointSite())
306 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000307 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +0000308 if (log)
309 log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n",
310 break_loc->GetID(), GetID());
311 }
312 }
313 }
314
315 if (!seen)
Greg Claytonab429022010-12-12 21:03:32 +0000316 new_modules.AppendIfNeeded (module_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000317
318 }
319 if (new_modules.GetSize() > 0)
320 {
321 ResolveBreakpointInModules(new_modules);
322 }
323 }
324 else
325 {
326 // Go through the currently set locations and if any have breakpoints in
327 // the module list, then remove their breakpoint sites.
328 // FIXME: Think about this... Maybe it's better to delete the locations?
329 // Are we sure that on load-unload-reload the module pointer will remain
330 // the same? Or do we need to do an equality on modules that is an
331 // "equivalence"???
332
Greg Clayton54e7afa2010-07-09 20:39:50 +0000333 for (size_t i = 0; i < module_list.GetSize(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000334 {
335 ModuleSP module_sp (module_list.GetModuleAtIndex (i));
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000336 if (m_filter_sp->ModulePasses (module_sp))
Chris Lattner24943d22010-06-08 16:52:24 +0000337 {
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000338 const size_t num_locs = m_locations.GetSize();
339 for (size_t loc_idx = 0; loc_idx < num_locs; ++loc_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000340 {
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000341 BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx);
342 const Section *section = break_loc->GetAddress().GetSection();
343 if (section && section->GetModule() == module_sp.get())
344 {
345 // Remove this breakpoint since the shared library is
346 // unloaded, but keep the breakpoint location around
347 // so we always get complete hit count and breakpoint
348 // lifetime info
Chris Lattner24943d22010-06-08 16:52:24 +0000349 break_loc->ClearBreakpointSite();
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000350 }
Chris Lattner24943d22010-06-08 16:52:24 +0000351 }
Chris Lattner24943d22010-06-08 16:52:24 +0000352 }
353 }
354 }
355}
356
357void
358Breakpoint::Dump (Stream *)
359{
360}
361
362size_t
363Breakpoint::GetNumResolvedLocations() const
364{
365 // Return the number of breakpoints that are actually resolved and set
366 // down in the inferior process.
367 return m_locations.GetNumResolvedLocations();
368}
369
370size_t
371Breakpoint::GetNumLocations() const
372{
373 return m_locations.GetSize();
374}
375
376void
377Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
378{
379 assert (s != NULL);
Greg Clayton12bec712010-06-28 21:30:43 +0000380 s->Printf("%i: ", GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000381 GetResolverDescription (s);
Greg Clayton12bec712010-06-28 21:30:43 +0000382 GetFilterDescription (s);
Chris Lattner24943d22010-06-08 16:52:24 +0000383
Greg Clayton54e7afa2010-07-09 20:39:50 +0000384 const size_t num_locations = GetNumLocations ();
385 const size_t num_resolved_locations = GetNumResolvedLocations ();
Chris Lattner24943d22010-06-08 16:52:24 +0000386
387 switch (level)
388 {
389 case lldb::eDescriptionLevelBrief:
390 case lldb::eDescriptionLevelFull:
391 if (num_locations > 0)
392 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000393 s->Printf(", locations = %zu", num_locations);
Chris Lattner24943d22010-06-08 16:52:24 +0000394 if (num_resolved_locations > 0)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000395 s->Printf(", resolved = %zu", num_resolved_locations);
Chris Lattner24943d22010-06-08 16:52:24 +0000396 }
397 else
398 {
Greg Clayton12bec712010-06-28 21:30:43 +0000399 s->Printf(", locations = 0 (pending)");
Chris Lattner24943d22010-06-08 16:52:24 +0000400 }
401
Jim Ingham649492b2010-06-18 01:00:58 +0000402 GetOptions()->GetDescription(s, level);
403
Chris Lattner24943d22010-06-08 16:52:24 +0000404 if (level == lldb::eDescriptionLevelFull)
405 {
Jim Ingham649492b2010-06-18 01:00:58 +0000406 s->IndentLess();
407 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000408 }
409 break;
410
411 case lldb::eDescriptionLevelVerbose:
412 // Verbose mode does a debug dump of the breakpoint
413 Dump (s);
Jim Ingham649492b2010-06-18 01:00:58 +0000414 s->EOL ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000415 //s->Indent();
Jim Ingham649492b2010-06-18 01:00:58 +0000416 GetOptions()->GetDescription(s, level);
Chris Lattner24943d22010-06-08 16:52:24 +0000417 break;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000418
419 default:
420 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000421 }
422
Jim Ingham1cd466f2011-05-14 01:11:02 +0000423 // The brief description is just the location name (1.2 or whatever). That's pointless to
424 // show in the breakpoint's description, so suppress it.
425 if (show_locations && level != lldb::eDescriptionLevelBrief)
Chris Lattner24943d22010-06-08 16:52:24 +0000426 {
Chris Lattner24943d22010-06-08 16:52:24 +0000427 s->IndentMore();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000428 for (size_t i = 0; i < num_locations; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000429 {
430 BreakpointLocation *loc = GetLocationAtIndex(i).get();
431 loc->GetDescription(s, level);
432 s->EOL();
433 }
434 s->IndentLess();
Chris Lattner24943d22010-06-08 16:52:24 +0000435 }
436}
437
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000438Breakpoint::BreakpointEventData::BreakpointEventData (BreakpointEventType sub_type,
Jim Ingham649492b2010-06-18 01:00:58 +0000439 BreakpointSP &new_breakpoint_sp) :
Chris Lattner24943d22010-06-08 16:52:24 +0000440 EventData (),
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000441 m_breakpoint_event (sub_type),
Chris Lattner24943d22010-06-08 16:52:24 +0000442 m_new_breakpoint_sp (new_breakpoint_sp)
443{
444}
445
446Breakpoint::BreakpointEventData::~BreakpointEventData ()
447{
448}
449
450const ConstString &
451Breakpoint::BreakpointEventData::GetFlavorString ()
452{
453 static ConstString g_flavor ("Breakpoint::BreakpointEventData");
454 return g_flavor;
455}
456
457const ConstString &
458Breakpoint::BreakpointEventData::GetFlavor () const
459{
460 return BreakpointEventData::GetFlavorString ();
461}
462
463
464BreakpointSP &
465Breakpoint::BreakpointEventData::GetBreakpoint ()
466{
467 return m_new_breakpoint_sp;
468}
469
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000470BreakpointEventType
471Breakpoint::BreakpointEventData::GetBreakpointEventType () const
Chris Lattner24943d22010-06-08 16:52:24 +0000472{
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000473 return m_breakpoint_event;
Chris Lattner24943d22010-06-08 16:52:24 +0000474}
475
476void
477Breakpoint::BreakpointEventData::Dump (Stream *s) const
478{
479}
480
481Breakpoint::BreakpointEventData *
482Breakpoint::BreakpointEventData::GetEventDataFromEvent (const EventSP &event_sp)
483{
484 if (event_sp)
485 {
486 EventData *event_data = event_sp->GetData();
487 if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
488 return static_cast <BreakpointEventData *> (event_sp->GetData());
489 }
490 return NULL;
491}
492
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000493BreakpointEventType
494Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (const EventSP &event_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000495{
496 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
497
498 if (data == NULL)
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000499 return eBreakpointEventTypeInvalidType;
Chris Lattner24943d22010-06-08 16:52:24 +0000500 else
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000501 return data->GetBreakpointEventType();
Chris Lattner24943d22010-06-08 16:52:24 +0000502}
503
504BreakpointSP
505Breakpoint::BreakpointEventData::GetBreakpointFromEvent (const EventSP &event_sp)
506{
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000507 BreakpointSP bp_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000508
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000509 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
510 if (data)
511 bp_sp = data->GetBreakpoint();
512
513 return bp_sp;
514}
515
516lldb::BreakpointLocationSP
517Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (const lldb::EventSP &event_sp, uint32_t bp_loc_idx)
518{
519 lldb::BreakpointLocationSP bp_loc_sp;
520
521 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
522 if (data)
Chris Lattner24943d22010-06-08 16:52:24 +0000523 {
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000524 Breakpoint *bp = data->GetBreakpoint().get();
525 if (bp)
526 bp_loc_sp = bp->GetLocationAtIndex(bp_loc_idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000527 }
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000528
529 return bp_loc_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000530}
531
532
533void
534Breakpoint::GetResolverDescription (Stream *s)
535{
536 if (m_resolver_sp)
537 m_resolver_sp->GetDescription (s);
538}
539
Johnny Chena62ad7c2010-10-28 17:27:46 +0000540
541bool
542Breakpoint::GetMatchingFileLine (const ConstString &filename, uint32_t line_number, BreakpointLocationCollection &loc_coll)
543{
544 // TODO: To be correct, this method needs to fill the breakpoint location collection
545 // with the location IDs which match the filename and line_number.
546 //
547
548 if (m_resolver_sp)
549 {
550 BreakpointResolverFileLine *resolverFileLine = dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get());
551 if (resolverFileLine &&
552 resolverFileLine->m_file_spec.GetFilename() == filename &&
553 resolverFileLine->m_line_number == line_number)
554 {
555 return true;
556 }
557 }
558 return false;
559}
560
Chris Lattner24943d22010-06-08 16:52:24 +0000561void
562Breakpoint::GetFilterDescription (Stream *s)
563{
564 m_filter_sp->GetDescription (s);
565}
566
567const BreakpointSP
568Breakpoint::GetSP ()
569{
570 return m_target.GetBreakpointList().FindBreakpointByID (GetID());
571}