blob: fb277b223bad9636d82e50cd40b1c721803af6b4 [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
156Breakpoint::SetIgnoreCount (int32_t n)
157{
158 m_options.SetIgnoreCount(n);
159}
160
161int32_t
162Breakpoint::GetIgnoreCount () const
163{
164 return m_options.GetIgnoreCount();
165}
166
167void
168Breakpoint::SetThreadID (lldb::tid_t thread_id)
169{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000170 m_options.GetThreadSpec()->SetTID(thread_id);
Chris Lattner24943d22010-06-08 16:52:24 +0000171}
172
173lldb::tid_t
174Breakpoint::GetThreadID ()
175{
Jim Ingham3c7b5b92010-06-16 02:00:15 +0000176 if (m_options.GetThreadSpec() == NULL)
177 return LLDB_INVALID_THREAD_ID;
178 else
179 return m_options.GetThreadSpec()->GetTID();
Chris Lattner24943d22010-06-08 16:52:24 +0000180}
181
182// This function is used when "baton" doesn't need to be freed
183void
184Breakpoint::SetCallback (BreakpointHitCallback callback, void *baton, bool is_synchronous)
185{
186 // The default "Baton" class will keep a copy of "baton" and won't free
187 // or delete it when it goes goes out of scope.
188 m_options.SetCallback(callback, BatonSP (new Baton(baton)), is_synchronous);
189}
190
191// This function is used when a baton needs to be freed and therefore is
192// contained in a "Baton" subclass.
193void
194Breakpoint::SetCallback (BreakpointHitCallback callback, const BatonSP &callback_baton_sp, bool is_synchronous)
195{
196 m_options.SetCallback(callback, callback_baton_sp, is_synchronous);
197}
198
199void
200Breakpoint::ClearCallback ()
201{
202 m_options.ClearCallback ();
203}
204
205bool
206Breakpoint::InvokeCallback (StoppointCallbackContext *context, break_id_t bp_loc_id)
207{
208 return m_options.InvokeCallback (context, GetID(), bp_loc_id);
209}
210
211BreakpointOptions *
212Breakpoint::GetOptions ()
213{
214 return &m_options;
215}
216
217void
218Breakpoint::ResolveBreakpoint ()
219{
220 if (m_resolver_sp)
221 m_resolver_sp->ResolveBreakpoint(*m_filter_sp);
222}
223
224void
225Breakpoint::ResolveBreakpointInModules (ModuleList &module_list)
226{
227 if (m_resolver_sp)
228 m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);
229}
230
231void
232Breakpoint::ClearAllBreakpointSites ()
233{
234 m_locations.ClearAllBreakpointSites();
235}
236
237//----------------------------------------------------------------------
238// ModulesChanged: Pass in a list of new modules, and
239//----------------------------------------------------------------------
240
241void
242Breakpoint::ModulesChanged (ModuleList &module_list, bool load)
243{
244 if (load)
245 {
246 // The logic for handling new modules is:
247 // 1) If the filter rejects this module, then skip it.
248 // 2) Run through the current location list and if there are any locations
249 // for that module, we mark the module as "seen" and we don't try to re-resolve
250 // breakpoint locations for that module.
251 // However, we do add breakpoint sites to these locations if needed.
252 // 3) If we don't see this module in our breakpoint location list, call ResolveInModules.
253
254 ModuleList new_modules; // We'll stuff the "unseen" modules in this list, and then resolve
255 // them after the locations pass. Have to do it this way because
256 // resolving breakpoints will add new locations potentially.
257
258 for (int i = 0; i < module_list.GetSize(); i++)
259 {
260 bool seen = false;
261 ModuleSP module_sp (module_list.GetModuleAtIndex (i));
262 Module *module = module_sp.get();
263 if (!m_filter_sp->ModulePasses (module_sp))
264 continue;
265
266 for (int i = 0; i < m_locations.GetSize(); i++)
267 {
268 BreakpointLocationSP break_loc = m_locations.GetByIndex(i);
269 const Section *section = break_loc->GetAddress().GetSection();
270 if (section == NULL || section->GetModule() == module)
271 {
272 if (!seen)
273 seen = true;
274
275 if (!break_loc->ResolveBreakpointSite())
276 {
277 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
278 if (log)
279 log->Printf ("Warning: could not set breakpoint site for breakpoint location %d of breakpoint %d.\n",
280 break_loc->GetID(), GetID());
281 }
282 }
283 }
284
285 if (!seen)
286 new_modules.AppendInNeeded (module_sp);
287
288 }
289 if (new_modules.GetSize() > 0)
290 {
291 ResolveBreakpointInModules(new_modules);
292 }
293 }
294 else
295 {
296 // Go through the currently set locations and if any have breakpoints in
297 // the module list, then remove their breakpoint sites.
298 // FIXME: Think about this... Maybe it's better to delete the locations?
299 // Are we sure that on load-unload-reload the module pointer will remain
300 // the same? Or do we need to do an equality on modules that is an
301 // "equivalence"???
302
303 for (int i = 0; i < module_list.GetSize(); i++)
304 {
305 ModuleSP module_sp (module_list.GetModuleAtIndex (i));
306 if (!m_filter_sp->ModulePasses (module_sp))
307 continue;
308
309 for (int i = 0; i < m_locations.GetSize(); i++)
310 {
311 BreakpointLocationSP break_loc = m_locations.GetByIndex(i);
312 const Section *section = break_loc->GetAddress().GetSection();
313 if (section)
314 {
315 if (section->GetModule() == module_sp.get())
316 break_loc->ClearBreakpointSite();
317 }
318// else
319// {
320// Address temp_addr;
321// if (module->ResolveLoadAddress(break_loc->GetLoadAddress(), m_target->GetProcess(), temp_addr))
322// break_loc->ClearBreakpointSite();
323// }
324 }
325 }
326 }
327}
328
329void
330Breakpoint::Dump (Stream *)
331{
332}
333
334size_t
335Breakpoint::GetNumResolvedLocations() const
336{
337 // Return the number of breakpoints that are actually resolved and set
338 // down in the inferior process.
339 return m_locations.GetNumResolvedLocations();
340}
341
342size_t
343Breakpoint::GetNumLocations() const
344{
345 return m_locations.GetSize();
346}
347
348void
349Breakpoint::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_locations)
350{
351 assert (s != NULL);
352 StreamString filter_strm;
353
354
355 s->Printf("%i ", GetID());
356 GetResolverDescription (s);
357 GetFilterDescription (&filter_strm);
358 if (filter_strm.GetString().compare ("No Filter") != 0)
359 {
360 s->Printf (", ");
361 GetFilterDescription (s);
362 }
363
364 const uint32_t num_locations = GetNumLocations ();
365 const uint32_t num_resolved_locations = GetNumResolvedLocations ();
366
367 switch (level)
368 {
369 case lldb::eDescriptionLevelBrief:
370 case lldb::eDescriptionLevelFull:
371 if (num_locations > 0)
372 {
373 s->Printf(" with %u location%s", num_locations, num_locations > 1 ? "s" : "");
374 if (num_resolved_locations > 0)
375 s->Printf(" (%u resolved)", num_resolved_locations);
376 s->PutChar(';');
377 }
378 else
379 {
380 s->Printf(" with 0 locations (Pending Breakpoint).");
381 }
382
Jim Ingham649492b2010-06-18 01:00:58 +0000383 GetOptions()->GetDescription(s, level);
384
Chris Lattner24943d22010-06-08 16:52:24 +0000385 if (level == lldb::eDescriptionLevelFull)
386 {
Jim Ingham649492b2010-06-18 01:00:58 +0000387 s->IndentLess();
388 s->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000389 }
390 break;
391
392 case lldb::eDescriptionLevelVerbose:
393 // Verbose mode does a debug dump of the breakpoint
394 Dump (s);
Jim Ingham649492b2010-06-18 01:00:58 +0000395 s->EOL ();
396 s->Indent();
397 GetOptions()->GetDescription(s, level);
Chris Lattner24943d22010-06-08 16:52:24 +0000398 break;
399 }
400
401 if (show_locations)
402 {
403 s->EOL();
404 s->IndentMore();
405 for (int i = 0; i < GetNumLocations(); ++i)
406 {
407 BreakpointLocation *loc = GetLocationAtIndex(i).get();
408 loc->GetDescription(s, level);
409 s->EOL();
410 }
411 s->IndentLess();
412
413 }
414}
415
Jim Ingham649492b2010-06-18 01:00:58 +0000416Breakpoint::BreakpointEventData::BreakpointEventData (Breakpoint::BreakpointEventData::EventSubType sub_type,
417 BreakpointSP &new_breakpoint_sp) :
Chris Lattner24943d22010-06-08 16:52:24 +0000418 EventData (),
419 m_sub_type (sub_type),
420 m_new_breakpoint_sp (new_breakpoint_sp)
421{
422}
423
424Breakpoint::BreakpointEventData::~BreakpointEventData ()
425{
426}
427
428const ConstString &
429Breakpoint::BreakpointEventData::GetFlavorString ()
430{
431 static ConstString g_flavor ("Breakpoint::BreakpointEventData");
432 return g_flavor;
433}
434
435const ConstString &
436Breakpoint::BreakpointEventData::GetFlavor () const
437{
438 return BreakpointEventData::GetFlavorString ();
439}
440
441
442BreakpointSP &
443Breakpoint::BreakpointEventData::GetBreakpoint ()
444{
445 return m_new_breakpoint_sp;
446}
447
448Breakpoint::BreakpointEventData::EventSubType
449Breakpoint::BreakpointEventData::GetSubType () const
450{
451 return m_sub_type;
452}
453
454void
455Breakpoint::BreakpointEventData::Dump (Stream *s) const
456{
457}
458
459Breakpoint::BreakpointEventData *
460Breakpoint::BreakpointEventData::GetEventDataFromEvent (const EventSP &event_sp)
461{
462 if (event_sp)
463 {
464 EventData *event_data = event_sp->GetData();
465 if (event_data && event_data->GetFlavor() == BreakpointEventData::GetFlavorString())
466 return static_cast <BreakpointEventData *> (event_sp->GetData());
467 }
468 return NULL;
469}
470
471Breakpoint::BreakpointEventData::EventSubType
472Breakpoint::BreakpointEventData::GetSubTypeFromEvent (const EventSP &event_sp)
473{
474 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
475
476 if (data == NULL)
477 return eBreakpointInvalidType;
478 else
479 return data->GetSubType();
480}
481
482BreakpointSP
483Breakpoint::BreakpointEventData::GetBreakpointFromEvent (const EventSP &event_sp)
484{
485 BreakpointEventData *data = GetEventDataFromEvent (event_sp);
486
487 if (data == NULL)
488 {
489 BreakpointSP ret_val;
490 return ret_val;
491 }
492 else
493 return data->GetBreakpoint();
494}
495
496
497void
498Breakpoint::GetResolverDescription (Stream *s)
499{
500 if (m_resolver_sp)
501 m_resolver_sp->GetDescription (s);
502}
503
504void
505Breakpoint::GetFilterDescription (Stream *s)
506{
507 m_filter_sp->GetDescription (s);
508}
509
510const BreakpointSP
511Breakpoint::GetSP ()
512{
513 return m_target.GetBreakpointList().FindBreakpointByID (GetID());
514}