blob: 9095db064ee81fbd8b7f0f6c6fa1014aa596b15e [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
Chris Lattner24943d22010-06-08 16:52:24 +0000127// For each of the overall options we need to decide how they propagate to
128// the location options. This will determine the precedence of options on
Johnny Chen736f0d62012-01-25 23:08:23 +0000129// the breakpoint vs. its locations.
Chris Lattner24943d22010-06-08 16:52:24 +0000130
131// Disable at the breakpoint level should override the location settings.
132// That way you can conveniently turn off a whole breakpoint without messing
133// up the individual settings.
134
135void
136Breakpoint::SetEnabled (bool enable)
137{
138 m_options.SetEnabled(enable);
139 if (enable)
140 m_locations.ResolveAllBreakpointSites();
141 else
142 m_locations.ClearAllBreakpointSites();
143}
144
145bool
146Breakpoint::IsEnabled ()
147{
148 return m_options.IsEnabled();
149}
150
151void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000152Breakpoint::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000153{
154 m_options.SetIgnoreCount(n);
155}
156
Greg Clayton54e7afa2010-07-09 20:39:50 +0000157uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000158Breakpoint::GetIgnoreCount () const
159{
160 return m_options.GetIgnoreCount();
161}
162
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000163uint32_t
164Breakpoint::GetHitCount () const
165{
166 return m_locations.GetHitCount();
167}
168
Chris Lattner24943d22010-06-08 16:52:24 +0000169void
170Breakpoint::SetThreadID (lldb::tid_t thread_id)
171{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000172 m_options.GetThreadSpec()->SetTID(thread_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000173}
174
175lldb::tid_t
176Breakpoint::GetThreadID ()
177{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000178 if (m_options.GetThreadSpec() == NULL)
179 return LLDB_INVALID_THREAD_ID;
180 else
181 return m_options.GetThreadSpec()->GetTID();
Chris Lattner24943d22010-06-08 16:52:24 +0000182}
183
Jim Inghamd1686902010-10-14 23:45:03 +0000184void
185Breakpoint::SetCondition (const char *condition)
186{
187 m_options.SetCondition (condition);
188}
189
190ThreadPlan *
191Breakpoint::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, lldb::BreakpointLocationSP loc_sp, Stream &error)
192{
193 return m_options.GetThreadPlanToTestCondition (exe_ctx, loc_sp, error);
194}
195
196const char *
Jim Inghamac354422011-06-15 21:16:00 +0000197Breakpoint::GetConditionText () const
Jim Inghamd1686902010-10-14 23:45:03 +0000198{
199 return m_options.GetConditionText();
200}
201
Chris Lattner24943d22010-06-08 16:52:24 +0000202// This function is used when "baton" doesn't need to be freed
203void
204Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous)
205{
206 // The default "Baton" class will keep a copy of "baton" and won't free
207 // or delete it when it goes goes out of scope.
208 m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
209}
210
211// This function is used when a baton needs to be freed and therefore is
212// contained in a "Baton" subclass.
213void
214Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
215{
216 m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
217}
218
219void
220Breakpoint::ClearCallback ()
221{
222 m_options.ClearCallback ();
223}
224
225bool
226Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id)
227{
228 return m_options.InvokeCallback (context, GetID(), bp_loc_id);
229}
230
231BreakpointOptions *
232Breakpoint::GetOptions ()
233{
234 return &m_options;
235}
236
237void
238Breakpoint::ResolveBreakpoint ()
239{
240 if (m_resolver_sp)
241 m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
242}
243
244void
245Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
246{
247 if (m_resolver_sp)
248 m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
249}
250
251void
252Breakpoint::ClearAllBreakpointSites ()
253{
254 m_locations.ClearAllBreakpointSites();
255}
256
257//----------------------------------------------------------------------
258// ModulesChanged: Pass in a list of new modules, and
259//----------------------------------------------------------------------
260
261void
262Breakpoint::ModulesChanged (ModuleList &module_list, bool load)
263{
264 if (load)
265 {
266 // The logic for handling new modules is:
267 // 1) If the filter rejects this module, then skip it.
268 // 2) Run through the current location list and if there are any locations
269 // for that module, we mark the module as "seen" and we don't try to re-resolve
270 // breakpoint locations for that module.
271 // However, we do add breakpoint sites to these locations if needed.
272 // 3) If we don't see this module in our breakpoint location list, call ResolveInModules.
273
274 ModuleList new_modules; // We'll stuff the "unseen" modules in this list, and then resolve
Greg Clayton19a1ab82011-02-05 00:38:04 +0000275 // them after the locations pass. Have to do it this way because
276 // resolving breakpoints will add new locations potentially.
277
278 const size_t num_locs = m_locations.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000279
Greg Clayton54e7afa2010-07-09 20:39:50 +0000280 for (size_t i = 0; i < module_list.GetSize(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000281 {
282 bool seen = false;
283 ModuleSP module_sp (module_list.GetModuleAtIndex (i));
Chris Lattner24943d22010-06-08 16:52:24 +0000284 if (!m_filter_sp->ModulePasses (module_sp))
285 continue;
286
Greg Clayton19a1ab82011-02-05 00:38:04 +0000287 for (size_t loc_idx = 0; loc_idx < num_locs; loc_idx++)
Chris Lattner24943d22010-06-08 16:52:24 +0000288 {
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000289 BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx);
Jim Ingham1de036b2010-10-20 03:36:33 +0000290 if (!break_loc->IsEnabled())
291 continue;
Chris Lattner24943d22010-06-08 16:52:24 +0000292 const Section *section = break_loc->GetAddress().GetSection();
Greg Clayton19a1ab82011-02-05 00:38:04 +0000293 if (section == NULL || section->GetModule() == module_sp.get())
Chris Lattner24943d22010-06-08 16:52:24 +0000294 {
295 if (!seen)
296 seen = true;
297
298 if (!break_loc->ResolveBreakpointSite())
299 {
Greg Claytone005f2c2010-11-06 01:53:30 +0000300 LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
Chris Lattner24943d22010-06-08 16:52:24 +0000301 if (log)
302 log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n",
303 break_loc->GetID(), GetID());
304 }
305 }
306 }
307
308 if (!seen)
Greg Claytonab429022010-12-12 21:03:32 +0000309 new_modules.AppendIfNeeded (module_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000310
311 }
312 if (new_modules.GetSize() > 0)
313 {
314 ResolveBreakpointInModules(new_modules);
315 }
316 }
317 else
318 {
319 // Go through the currently set locations and if any have breakpoints in
320 // the module list, then remove their breakpoint sites.
321 // FIXME: Think about this... Maybe it's better to delete the locations?
322 // Are we sure that on load-unload-reload the module pointer will remain
323 // the same? Or do we need to do an equality on modules that is an
324 // "equivalence"???
325
Greg Clayton54e7afa2010-07-09 20:39:50 +0000326 for (size_t i = 0; i < module_list.GetSize(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000327 {
328 ModuleSP module_sp (module_list.GetModuleAtIndex (i));
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000329 if (m_filter_sp->ModulePasses (module_sp))
Chris Lattner24943d22010-06-08 16:52:24 +0000330 {
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000331 const size_t num_locs = m_locations.GetSize();
332 for (size_t loc_idx = 0; loc_idx < num_locs; ++loc_idx)
Chris Lattner24943d22010-06-08 16:52:24 +0000333 {
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000334 BreakpointLocationSP break_loc = m_locations.GetByIndex(loc_idx);
335 const Section *section = break_loc->GetAddress().GetSection();
336 if (section && section->GetModule() == module_sp.get())
337 {
338 // Remove this breakpoint since the shared library is
339 // unloaded, but keep the breakpoint location around
340 // so we always get complete hit count and breakpoint
341 // lifetime info
Chris Lattner24943d22010-06-08 16:52:24 +0000342 break_loc->ClearBreakpointSite();
Greg Clayton7b9fcc02010-12-06 23:51:26 +0000343 }
Chris Lattner24943d22010-06-08 16:52:24 +0000344 }
Chris Lattner24943d22010-06-08 16:52:24 +0000345 }
346 }
347 }
348}
349
350void
351Breakpoint::Dump (Stream *)
352{
353}
354
355size_t
356Breakpoint::GetNumResolvedLocations() const
357{
358 // Return the number of breakpoints that are actually resolved and set
359 // down in the inferior process.
360 return m_locations.GetNumResolvedLocations();
361}
362
363size_t
364Breakpoint::GetNumLocations() const
365{
366 return m_locations.GetSize();
367}
368
369void
370Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
371{
372 assert (s != NULL);
Greg Clayton12bec712010-06-28 21:30:43 +0000373 s->Printf("%i: ", GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000374 GetResolverDescription (s);
Greg Clayton12bec712010-06-28 21:30:43 +0000375 GetFilterDescription (s);
Chris Lattner24943d22010-06-08 16:52:24 +0000376
Greg Clayton54e7afa2010-07-09 20:39:50 +0000377 const size_t num_locations = GetNumLocations ();
378 const size_t num_resolved_locations = GetNumResolvedLocations ();
Chris Lattner24943d22010-06-08 16:52:24 +0000379
380 switch (level)
381 {
382 case lldb::eDescriptionLevelBrief:
383 case lldb::eDescriptionLevelFull:
384 if (num_locations > 0)
385 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000386 s->Printf(", locations = %zu", num_locations);
Chris Lattner24943d22010-06-08 16:52:24 +0000387 if (num_resolved_locations > 0)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000388 s->Printf(", resolved = %zu", num_resolved_locations);
Chris Lattner24943d22010-06-08 16:52:24 +0000389 }
390 else
391 {
Greg Clayton12bec712010-06-28 21:30:43 +0000392 s->Printf(", locations = 0 (pending)");
Chris Lattner24943d22010-06-08 16:52:24 +0000393 }
394
Jim Ingham649492b2010-06-18 01:00:58 +0000395 GetOptions()->GetDescription(s, level);
396
Chris Lattner24943d22010-06-08 16:52:24 +0000397 if (level == lldb::eDescriptionLevelFull)
398 {
Jim Ingham649492b2010-06-18 01:00:58 +0000399 s->IndentLess();
400 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000401 }
402 break;
403
404 case lldb::eDescriptionLevelVerbose:
405 // Verbose mode does a debug dump of the breakpoint
406 Dump (s);
Jim Ingham649492b2010-06-18 01:00:58 +0000407 s->EOL ();
Greg Claytonb1888f22011-03-19 01:12:21 +0000408 //s->Indent();
Jim Ingham649492b2010-06-18 01:00:58 +0000409 GetOptions()->GetDescription(s, level);
Chris Lattner24943d22010-06-08 16:52:24 +0000410 break;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000411
412 default:
413 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000414 }
415
Jim Ingham1cd466f2011-05-14 01:11:02 +0000416 // The brief description is just the location name (1.2 or whatever). That's pointless to
417 // show in the breakpoint's description, so suppress it.
418 if (show_locations && level != lldb::eDescriptionLevelBrief)
Chris Lattner24943d22010-06-08 16:52:24 +0000419 {
Chris Lattner24943d22010-06-08 16:52:24 +0000420 s->IndentMore();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000421 for (size_t i = 0; i < num_locations; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000422 {
423 BreakpointLocation *loc = GetLocationAtIndex(i).get();
424 loc->GetDescription(s, level);
425 s->EOL();
426 }
427 s->IndentLess();
Chris Lattner24943d22010-06-08 16:52:24 +0000428 }
429}
430
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000431Breakpoint::BreakpointEventData::BreakpointEventData (BreakpointEventType sub_type,
Jim Ingham649492b2010-06-18 01:00:58 +0000432 BreakpointSP &new_breakpoint_sp) :
Chris Lattner24943d22010-06-08 16:52:24 +0000433 EventData (),
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000434 m_breakpoint_event (sub_type),
Chris Lattner24943d22010-06-08 16:52:24 +0000435 m_new_breakpoint_sp (new_breakpoint_sp)
436{
437}
438
439Breakpoint::BreakpointEventData::~BreakpointEventData ()
440{
441}
442
443const ConstString &
444Breakpoint::BreakpointEventData::GetFlavorString ()
445{
446 static ConstString g_flavor ("Breakpoint::BreakpointEventData");
447 return g_flavor;
448}
449
450const ConstString &
451Breakpoint::BreakpointEventData::GetFlavor () const
452{
453 return BreakpointEventData::GetFlavorString ();
454}
455
456
457BreakpointSP &
458Breakpoint::BreakpointEventData::GetBreakpoint ()
459{
460 return m_new_breakpoint_sp;
461}
462
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000463BreakpointEventType
464Breakpoint::BreakpointEventData::GetBreakpointEventType () const
Chris Lattner24943d22010-06-08 16:52:24 +0000465{
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000466 return m_breakpoint_event;
Chris Lattner24943d22010-06-08 16:52:24 +0000467}
468
469void
470Breakpoint::BreakpointEventData::Dump (Stream *s) const
471{
472}
473
474Breakpoint::BreakpointEventData *
475Breakpoint::BreakpointEventData::GetEventDataFromEvent (const EventSP &event_sp)
476{
477 if (event_sp)
478 {
479 EventData *event_data = event_sp->GetData();
480 if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
481 return static_cast <BreakpointEventData *> (event_sp->GetData());
482 }
483 return NULL;
484}
485
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000486BreakpointEventType
487Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (const EventSP &event_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000488{
489 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
490
491 if (data == NULL)
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000492 return eBreakpointEventTypeInvalidType;
Chris Lattner24943d22010-06-08 16:52:24 +0000493 else
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000494 return data->GetBreakpointEventType();
Chris Lattner24943d22010-06-08 16:52:24 +0000495}
496
497BreakpointSP
498Breakpoint::BreakpointEventData::GetBreakpointFromEvent (const EventSP &event_sp)
499{
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000500 BreakpointSP bp_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000501
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000502 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
503 if (data)
504 bp_sp = data->GetBreakpoint();
505
506 return bp_sp;
507}
508
509lldb::BreakpointLocationSP
510Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (const lldb::EventSP &event_sp, uint32_t bp_loc_idx)
511{
512 lldb::BreakpointLocationSP bp_loc_sp;
513
514 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
515 if (data)
Chris Lattner24943d22010-06-08 16:52:24 +0000516 {
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000517 Breakpoint *bp = data->GetBreakpoint().get();
518 if (bp)
519 bp_loc_sp = bp->GetLocationAtIndex(bp_loc_idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000520 }
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000521
522 return bp_loc_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000523}
524
525
526void
527Breakpoint::GetResolverDescription (Stream *s)
528{
529 if (m_resolver_sp)
530 m_resolver_sp->GetDescription (s);
531}
532
Johnny Chena62ad7c2010-10-28 17:27:46 +0000533
534bool
535Breakpoint::GetMatchingFileLine (const ConstString &filename, uint32_t line_number, BreakpointLocationCollection &loc_coll)
536{
537 // TODO: To be correct, this method needs to fill the breakpoint location collection
538 // with the location IDs which match the filename and line_number.
539 //
540
541 if (m_resolver_sp)
542 {
543 BreakpointResolverFileLine *resolverFileLine = dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get());
544 if (resolverFileLine &&
545 resolverFileLine->m_file_spec.GetFilename() == filename &&
546 resolverFileLine->m_line_number == line_number)
547 {
548 return true;
549 }
550 }
551 return false;
552}
553
Chris Lattner24943d22010-06-08 16:52:24 +0000554void
555Breakpoint::GetFilterDescription (Stream *s)
556{
557 m_filter_sp->GetDescription (s);
558}
559
560const BreakpointSP
561Breakpoint::GetSP ()
562{
Greg Clayton987c7eb2011-09-17 08:33:22 +0000563 // This object contains an instrusive ref count base class so we can
564 // easily make a shared pointer to this object
565 return BreakpointSP (this);
Chris Lattner24943d22010-06-08 16:52:24 +0000566}