blob: 7f8b7dfff3c79a3137da93fc77fe667b33787702 [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"
Jim Ingham3c7b5b92010-06-16 02:00:15 +000027#include "lldb/Target/ThreadSpec.h"
Chris Lattner24943d22010-06-08 16:52:24 +000028#include "lldb/lldb-private-log.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33const ConstString &
34Breakpoint::GetEventIdentifier ()
35{
36 static ConstString g_identifier("event-identifier.breakpoint.changed");
37 return g_identifier;
38}
39
40//----------------------------------------------------------------------
41// Breakpoint constructor
42//----------------------------------------------------------------------
43Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp, BreakpointResolverSP &resolver_sp) :
44 m_target (target),
45 m_filter_sp (filter_sp),
46 m_resolver_sp (resolver_sp),
47 m_options (),
48 m_locations ()
49{
50}
51
52//----------------------------------------------------------------------
53// Destructor
54//----------------------------------------------------------------------
55Breakpoint::~Breakpoint()
56{
57}
58
59bool
60Breakpoint::IsInternal () const
61{
62 return LLDB_BREAK_ID_IS_INTERNAL(m_bid);
63}
64
65
66
67Target&
68Breakpoint::GetTarget ()
69{
70 return m_target;
71}
72
73const Target&
74Breakpoint::GetTarget () const
75{
76 return m_target;
77}
78
79BreakpointLocationSP
80Breakpoint::AddLocation (Address &addr, bool *new_location)
81{
82 BreakpointLocationSP bp_loc_sp (m_locations.FindByAddress(addr));
83 if (bp_loc_sp)
84 {
85 if (new_location)
86 *new_location = false;
87 return bp_loc_sp;
88 }
89
90 bp_loc_sp.reset (new BreakpointLocation (m_locations.GetNextID(), *this, addr));
91 m_locations.Add (bp_loc_sp);
92 bp_loc_sp->ResolveBreakpointSite();
93
94 if (new_location)
95 *new_location = true;
96 return bp_loc_sp;
97}
98
99BreakpointLocationSP
100Breakpoint::FindLocationByAddress (Address &addr)
101{
102 return m_locations.FindByAddress(addr);
103}
104
105break_id_t
106Breakpoint::FindLocationIDByAddress (Address &addr)
107{
108 return m_locations.FindIDByAddress(addr);
109}
110
111BreakpointLocationSP
112Breakpoint::FindLocationByID (break_id_t bp_loc_id)
113{
114 return m_locations.FindByID(bp_loc_id);
115}
116
117BreakpointLocationSP
118Breakpoint::GetLocationAtIndex (uint32_t index)
119{
120 return m_locations.GetByIndex(index);
121}
122
123BreakpointLocationSP
124Breakpoint::GetLocationSP (BreakpointLocation *bp_loc_ptr)
125{
126 assert (bp_loc_ptr->GetBreakpoint().GetID() == GetID());
127 return m_locations.FindByID(bp_loc_ptr->GetID());
128}
129
130
131// For each of the overall options we need to decide how they propagate to
132// the location options. This will determine the precedence of options on
133// the breakpoint vrs. its locations.
134
135// Disable at the breakpoint level should override the location settings.
136// That way you can conveniently turn off a whole breakpoint without messing
137// up the individual settings.
138
139void
140Breakpoint::SetEnabled (bool enable)
141{
142 m_options.SetEnabled(enable);
143 if (enable)
144 m_locations.ResolveAllBreakpointSites();
145 else
146 m_locations.ClearAllBreakpointSites();
147}
148
149bool
150Breakpoint::IsEnabled ()
151{
152 return m_options.IsEnabled();
153}
154
155void
Greg Clayton54e7afa2010-07-09 20:39:50 +0000156Breakpoint::SetIgnoreCount (uint32_t n)
Chris Lattner24943d22010-06-08 16:52:24 +0000157{
158 m_options.SetIgnoreCount(n);
159}
160
Greg Clayton54e7afa2010-07-09 20:39:50 +0000161uint32_t
Chris Lattner24943d22010-06-08 16:52:24 +0000162Breakpoint::GetIgnoreCount () const
163{
164 return m_options.GetIgnoreCount();
165}
166
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000167uint32_t
168Breakpoint::GetHitCount () const
169{
170 return m_locations.GetHitCount();
171}
172
Chris Lattner24943d22010-06-08 16:52:24 +0000173void
174Breakpoint::SetThreadID (lldb::tid_t thread_id)
175{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000176 m_options.GetThreadSpec()->SetTID(thread_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000177}
178
179lldb::tid_t
180Breakpoint::GetThreadID ()
181{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000182 if (m_options.GetThreadSpec() == NULL)
183 return LLDB_INVALID_THREAD_ID;
184 else
185 return m_options.GetThreadSpec()->GetTID();
Chris Lattner24943d22010-06-08 16:52:24 +0000186}
187
Jim Inghamd1686902010-10-14 23:45:03 +0000188void
189Breakpoint::SetCondition (const char *condition)
190{
191 m_options.SetCondition (condition);
192}
193
194ThreadPlan *
195Breakpoint::GetThreadPlanToTestCondition (ExecutionContext &exe_ctx, lldb::BreakpointLocationSP loc_sp, Stream &error)
196{
197 return m_options.GetThreadPlanToTestCondition (exe_ctx, loc_sp, error);
198}
199
200const char *
201Breakpoint::GetConditionText ()
202{
203 return m_options.GetConditionText();
204}
205
Chris Lattner24943d22010-06-08 16:52:24 +0000206// This function is used when "baton" doesn't need to be freed
207void
208Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous)
209{
210 // The default "Baton" class will keep a copy of "baton" and won't free
211 // or delete it when it goes goes out of scope.
212 m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
213}
214
215// This function is used when a baton needs to be freed and therefore is
216// contained in a "Baton" subclass.
217void
218Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
219{
220 m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
221}
222
223void
224Breakpoint::ClearCallback ()
225{
226 m_options.ClearCallback ();
227}
228
229bool
230Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id)
231{
232 return m_options.InvokeCallback (context, GetID(), bp_loc_id);
233}
234
235BreakpointOptions *
236Breakpoint::GetOptions ()
237{
238 return &m_options;
239}
240
241void
242Breakpoint::ResolveBreakpoint ()
243{
244 if (m_resolver_sp)
245 m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
246}
247
248void
249Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
250{
251 if (m_resolver_sp)
252 m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
253}
254
255void
256Breakpoint::ClearAllBreakpointSites ()
257{
258 m_locations.ClearAllBreakpointSites();
259}
260
261//----------------------------------------------------------------------
262// ModulesChanged: Pass in a list of new modules, and
263//----------------------------------------------------------------------
264
265void
266Breakpoint::ModulesChanged (ModuleList &module_list, bool load)
267{
268 if (load)
269 {
270 // The logic for handling new modules is:
271 // 1) If the filter rejects this module, then skip it.
272 // 2) Run through the current location list and if there are any locations
273 // for that module, we mark the module as "seen" and we don't try to re-resolve
274 // breakpoint locations for that module.
275 // However, we do add breakpoint sites to these locations if needed.
276 // 3) If we don't see this module in our breakpoint location list, call ResolveInModules.
277
278 ModuleList new_modules; // We'll stuff the "unseen" modules in this list, and then resolve
279 // them after the locations pass. Have to do it this way because
280 // resolving breakpoints will add new locations potentially.
281
Greg Clayton54e7afa2010-07-09 20:39:50 +0000282 for (size_t i = 0; i < module_list.GetSize(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000283 {
284 bool seen = false;
285 ModuleSP module_sp (module_list.GetModuleAtIndex (i));
286 Module *module = module_sp.get();
287 if (!m_filter_sp->ModulePasses (module_sp))
288 continue;
289
Greg Clayton54e7afa2010-07-09 20:39:50 +0000290 for (size_t j = 0; j < m_locations.GetSize(); j++)
Chris Lattner24943d22010-06-08 16:52:24 +0000291 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000292 BreakpointLocationSP break_loc = m_locations.GetByIndex(j);
Jim Ingham1de036b2010-10-20 03:36:33 +0000293 if (!break_loc->IsEnabled())
294 continue;
Chris Lattner24943d22010-06-08 16:52:24 +0000295 const Section *section = break_loc->GetAddress().GetSection();
296 if (section == NULL || section->GetModule() == module)
297 {
298 if (!seen)
299 seen = true;
300
301 if (!break_loc->ResolveBreakpointSite())
302 {
303 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
304 if (log)
305 log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n",
306 break_loc->GetID(), GetID());
307 }
308 }
309 }
310
311 if (!seen)
312 new_modules.AppendInNeeded (module_sp);
313
314 }
315 if (new_modules.GetSize() > 0)
316 {
317 ResolveBreakpointInModules(new_modules);
318 }
319 }
320 else
321 {
322 // Go through the currently set locations and if any have breakpoints in
323 // the module list, then remove their breakpoint sites.
324 // FIXME: Think about this... Maybe it's better to delete the locations?
325 // Are we sure that on load-unload-reload the module pointer will remain
326 // the same? Or do we need to do an equality on modules that is an
327 // "equivalence"???
328
Greg Clayton54e7afa2010-07-09 20:39:50 +0000329 for (size_t i = 0; i < module_list.GetSize(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000330 {
331 ModuleSP module_sp (module_list.GetModuleAtIndex (i));
332 if (!m_filter_sp->ModulePasses (module_sp))
333 continue;
334
Greg Clayton54e7afa2010-07-09 20:39:50 +0000335 for (size_t j = 0; j < m_locations.GetSize(); j++)
Chris Lattner24943d22010-06-08 16:52:24 +0000336 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000337 BreakpointLocationSP break_loc = m_locations.GetByIndex(j);
Chris Lattner24943d22010-06-08 16:52:24 +0000338 const Section *section = break_loc->GetAddress().GetSection();
339 if (section)
340 {
341 if (section->GetModule() == module_sp.get())
342 break_loc->ClearBreakpointSite();
343 }
344// else
345// {
346// Address temp_addr;
347// if (module->ResolveLoadAddress(break_loc->GetLoadAddress(), m_target->GetProcess(), temp_addr))
348// break_loc->ClearBreakpointSite();
349// }
350 }
351 }
352 }
353}
354
355void
356Breakpoint::Dump (Stream *)
357{
358}
359
360size_t
361Breakpoint::GetNumResolvedLocations() const
362{
363 // Return the number of breakpoints that are actually resolved and set
364 // down in the inferior process.
365 return m_locations.GetNumResolvedLocations();
366}
367
368size_t
369Breakpoint::GetNumLocations() const
370{
371 return m_locations.GetSize();
372}
373
374void
375Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
376{
377 assert (s != NULL);
Greg Clayton12bec712010-06-28 21:30:43 +0000378 s->Printf("%i: ", GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000379 GetResolverDescription (s);
Greg Clayton12bec712010-06-28 21:30:43 +0000380 GetFilterDescription (s);
Chris Lattner24943d22010-06-08 16:52:24 +0000381
Greg Clayton54e7afa2010-07-09 20:39:50 +0000382 const size_t num_locations = GetNumLocations ();
383 const size_t num_resolved_locations = GetNumResolvedLocations ();
Chris Lattner24943d22010-06-08 16:52:24 +0000384
385 switch (level)
386 {
387 case lldb::eDescriptionLevelBrief:
388 case lldb::eDescriptionLevelFull:
389 if (num_locations > 0)
390 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000391 s->Printf(", locations = %zu", num_locations);
Chris Lattner24943d22010-06-08 16:52:24 +0000392 if (num_resolved_locations > 0)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000393 s->Printf(", resolved = %zu", num_resolved_locations);
Chris Lattner24943d22010-06-08 16:52:24 +0000394 }
395 else
396 {
Greg Clayton12bec712010-06-28 21:30:43 +0000397 s->Printf(", locations = 0 (pending)");
Chris Lattner24943d22010-06-08 16:52:24 +0000398 }
399
Jim Ingham649492b2010-06-18 01:00:58 +0000400 GetOptions()->GetDescription(s, level);
401
Chris Lattner24943d22010-06-08 16:52:24 +0000402 if (level == lldb::eDescriptionLevelFull)
403 {
Jim Ingham649492b2010-06-18 01:00:58 +0000404 s->IndentLess();
405 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000406 }
407 break;
408
409 case lldb::eDescriptionLevelVerbose:
410 // Verbose mode does a debug dump of the breakpoint
411 Dump (s);
Jim Ingham649492b2010-06-18 01:00:58 +0000412 s->EOL ();
413 s->Indent();
414 GetOptions()->GetDescription(s, level);
Chris Lattner24943d22010-06-08 16:52:24 +0000415 break;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000416
417 default:
418 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000419 }
420
421 if (show_locations)
422 {
Chris Lattner24943d22010-06-08 16:52:24 +0000423 s->IndentMore();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000424 for (size_t i = 0; i < num_locations; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000425 {
426 BreakpointLocation *loc = GetLocationAtIndex(i).get();
427 loc->GetDescription(s, level);
428 s->EOL();
429 }
430 s->IndentLess();
Chris Lattner24943d22010-06-08 16:52:24 +0000431 }
432}
433
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000434Breakpoint::BreakpointEventData::BreakpointEventData (BreakpointEventType sub_type,
Jim Ingham649492b2010-06-18 01:00:58 +0000435 BreakpointSP &new_breakpoint_sp) :
Chris Lattner24943d22010-06-08 16:52:24 +0000436 EventData (),
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000437 m_breakpoint_event (sub_type),
Chris Lattner24943d22010-06-08 16:52:24 +0000438 m_new_breakpoint_sp (new_breakpoint_sp)
439{
440}
441
442Breakpoint::BreakpointEventData::~BreakpointEventData ()
443{
444}
445
446const ConstString &
447Breakpoint::BreakpointEventData::GetFlavorString ()
448{
449 static ConstString g_flavor ("Breakpoint::BreakpointEventData");
450 return g_flavor;
451}
452
453const ConstString &
454Breakpoint::BreakpointEventData::GetFlavor () const
455{
456 return BreakpointEventData::GetFlavorString ();
457}
458
459
460BreakpointSP &
461Breakpoint::BreakpointEventData::GetBreakpoint ()
462{
463 return m_new_breakpoint_sp;
464}
465
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000466BreakpointEventType
467Breakpoint::BreakpointEventData::GetBreakpointEventType () const
Chris Lattner24943d22010-06-08 16:52:24 +0000468{
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000469 return m_breakpoint_event;
Chris Lattner24943d22010-06-08 16:52:24 +0000470}
471
472void
473Breakpoint::BreakpointEventData::Dump (Stream *s) const
474{
475}
476
477Breakpoint::BreakpointEventData *
478Breakpoint::BreakpointEventData::GetEventDataFromEvent (const EventSP &event_sp)
479{
480 if (event_sp)
481 {
482 EventData *event_data = event_sp->GetData();
483 if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
484 return static_cast <BreakpointEventData *> (event_sp->GetData());
485 }
486 return NULL;
487}
488
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000489BreakpointEventType
490Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (const EventSP &event_sp)
Chris Lattner24943d22010-06-08 16:52:24 +0000491{
492 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
493
494 if (data == NULL)
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000495 return eBreakpointEventTypeInvalidType;
Chris Lattner24943d22010-06-08 16:52:24 +0000496 else
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000497 return data->GetBreakpointEventType();
Chris Lattner24943d22010-06-08 16:52:24 +0000498}
499
500BreakpointSP
501Breakpoint::BreakpointEventData::GetBreakpointFromEvent (const EventSP &event_sp)
502{
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000503 BreakpointSP bp_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000504
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000505 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
506 if (data)
507 bp_sp = data->GetBreakpoint();
508
509 return bp_sp;
510}
511
512lldb::BreakpointLocationSP
513Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (const lldb::EventSP &event_sp, uint32_t bp_loc_idx)
514{
515 lldb::BreakpointLocationSP bp_loc_sp;
516
517 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
518 if (data)
Chris Lattner24943d22010-06-08 16:52:24 +0000519 {
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000520 Breakpoint *bp = data->GetBreakpoint().get();
521 if (bp)
522 bp_loc_sp = bp->GetLocationAtIndex(bp_loc_idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000523 }
Greg Claytonc7f5d5c2010-07-23 23:33:17 +0000524
525 return bp_loc_sp;
Chris Lattner24943d22010-06-08 16:52:24 +0000526}
527
528
529void
530Breakpoint::GetResolverDescription (Stream *s)
531{
532 if (m_resolver_sp)
533 m_resolver_sp->GetDescription (s);
534}
535
536void
537Breakpoint::GetFilterDescription (Stream *s)
538{
539 m_filter_sp->GetDescription (s);
540}
541
542const BreakpointSP
543Breakpoint::GetSP ()
544{
545 return m_target.GetBreakpointList().FindBreakpointByID (GetID());
546}