1 //===-- SBBreakpoint.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 #include "lldb/API/SBBreakpoint.h"
11 #include "lldb/API/SBBreakpointLocation.h"
12 #include "lldb/API/SBDebugger.h"
13 #include "lldb/API/SBEvent.h"
14 #include "lldb/API/SBProcess.h"
15 #include "lldb/API/SBStream.h"
16 #include "lldb/API/SBThread.h"
17 
18 #include "lldb/Breakpoint/Breakpoint.h"
19 #include "lldb/Breakpoint/BreakpointLocation.h"
20 #include "lldb/Breakpoint/StoppointCallbackContext.h"
21 #include "lldb/Core/Address.h"
22 #include "lldb/Core/Log.h"
23 #include "lldb/Core/Stream.h"
24 #include "lldb/Core/StreamFile.h"
25 #include "lldb/Target/Process.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Target/Thread.h"
28 #include "lldb/Target/ThreadSpec.h"
29 
30 
31 #include "lldb/lldb-enumerations.h"
32 
33 using namespace lldb;
34 using namespace lldb_private;
35 
36 struct CallbackData
37 {
38     SBBreakpoint::BreakpointHitCallback callback;
39     void *callback_baton;
40 };
41 
42 class SBBreakpointCallbackBaton : public Baton
43 {
44 public:
45 
46     SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) :
47         Baton (new CallbackData)
48     {
49         CallbackData *data = (CallbackData *)m_data;
50         data->callback = callback;
51         data->callback_baton = baton;
52     }
53 
54     virtual ~SBBreakpointCallbackBaton()
55     {
56         CallbackData *data = (CallbackData *)m_data;
57 
58         if (data)
59         {
60             delete data;
61             m_data = NULL;
62         }
63     }
64 };
65 
66 
67 SBBreakpoint::SBBreakpoint () :
68     m_opaque_sp ()
69 {
70 }
71 
72 SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) :
73     m_opaque_sp (rhs.m_opaque_sp)
74 {
75 }
76 
77 
78 SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) :
79     m_opaque_sp (bp_sp)
80 {
81 }
82 
83 SBBreakpoint::~SBBreakpoint()
84 {
85 }
86 
87 const SBBreakpoint &
88 SBBreakpoint::operator = (const SBBreakpoint& rhs)
89 {
90     if (this != &rhs)
91         m_opaque_sp = rhs.m_opaque_sp;
92     return *this;
93 }
94 
95 bool
96 SBBreakpoint::operator == (const lldb::SBBreakpoint& rhs)
97 {
98     if (m_opaque_sp && rhs.m_opaque_sp)
99         return m_opaque_sp.get() == rhs.m_opaque_sp.get();
100     return false;
101 }
102 
103 break_id_t
104 SBBreakpoint::GetID () const
105 {
106     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
107 
108     break_id_t break_id = LLDB_INVALID_BREAK_ID;
109     if (m_opaque_sp)
110         break_id = m_opaque_sp->GetID();
111 
112     if (log)
113     {
114         if (break_id == LLDB_INVALID_BREAK_ID)
115             log->Printf ("SBBreakpoint(%p)::GetID () => LLDB_INVALID_BREAK_ID", m_opaque_sp.get());
116         else
117             log->Printf ("SBBreakpoint(%p)::GetID () => %u", m_opaque_sp.get(), break_id);
118     }
119 
120     return break_id;
121 }
122 
123 
124 bool
125 SBBreakpoint::IsValid() const
126 {
127     return m_opaque_sp;
128 }
129 
130 void
131 SBBreakpoint::ClearAllBreakpointSites ()
132 {
133     if (m_opaque_sp)
134     {
135         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
136         m_opaque_sp->ClearAllBreakpointSites ();
137     }
138 }
139 
140 SBBreakpointLocation
141 SBBreakpoint::FindLocationByAddress (addr_t vm_addr)
142 {
143     SBBreakpointLocation sb_bp_location;
144 
145     if (m_opaque_sp)
146     {
147         if (vm_addr != LLDB_INVALID_ADDRESS)
148         {
149             Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
150             Address address;
151             Target &target = m_opaque_sp->GetTarget();
152             if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
153             {
154                 address.SetSection (NULL);
155                 address.SetOffset (vm_addr);
156             }
157             sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address));
158         }
159     }
160     return sb_bp_location;
161 }
162 
163 break_id_t
164 SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr)
165 {
166     break_id_t break_id = LLDB_INVALID_BREAK_ID;
167 
168     if (m_opaque_sp && vm_addr != LLDB_INVALID_ADDRESS)
169     {
170         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
171         Address address;
172         Target &target = m_opaque_sp->GetTarget();
173         if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
174         {
175             address.SetSection (NULL);
176             address.SetOffset (vm_addr);
177         }
178         break_id = m_opaque_sp->FindLocationIDByAddress (address);
179     }
180 
181     return break_id;
182 }
183 
184 SBBreakpointLocation
185 SBBreakpoint::FindLocationByID (break_id_t bp_loc_id)
186 {
187     SBBreakpointLocation sb_bp_location;
188 
189     if (m_opaque_sp)
190     {
191         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
192         sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id));
193     }
194 
195     return sb_bp_location;
196 }
197 
198 SBBreakpointLocation
199 SBBreakpoint::GetLocationAtIndex (uint32_t index)
200 {
201     SBBreakpointLocation sb_bp_location;
202 
203     if (m_opaque_sp)
204     {
205         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
206         sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index));
207     }
208 
209     return sb_bp_location;
210 }
211 
212 void
213 SBBreakpoint::SetEnabled (bool enable)
214 {
215     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
216 
217     if (log)
218         log->Printf ("SBBreakpoint(%p)::SetEnabled (enabled=%i)", m_opaque_sp.get(), enable);
219 
220     if (m_opaque_sp)
221     {
222         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
223         m_opaque_sp->SetEnabled (enable);
224     }
225 }
226 
227 bool
228 SBBreakpoint::IsEnabled ()
229 {
230     if (m_opaque_sp)
231     {
232         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
233         return m_opaque_sp->IsEnabled();
234     }
235     else
236         return false;
237 }
238 
239 void
240 SBBreakpoint::SetIgnoreCount (uint32_t count)
241 {
242     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
243 
244     if (log)
245         log->Printf ("SBBreakpoint(%p)::SetIgnoreCount (count=%u)", m_opaque_sp.get(), count);
246 
247     if (m_opaque_sp)
248     {
249         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
250         m_opaque_sp->SetIgnoreCount (count);
251     }
252 }
253 
254 void
255 SBBreakpoint::SetCondition (const char *condition)
256 {
257     if (m_opaque_sp)
258     {
259         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
260         m_opaque_sp->SetCondition (condition);
261     }
262 }
263 
264 const char *
265 SBBreakpoint::GetCondition ()
266 {
267     if (m_opaque_sp)
268     {
269         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
270         return m_opaque_sp->GetConditionText ();
271     }
272     return NULL;
273 }
274 
275 uint32_t
276 SBBreakpoint::GetHitCount () const
277 {
278     uint32_t count = 0;
279     if (m_opaque_sp)
280     {
281         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
282         count = m_opaque_sp->GetHitCount();
283     }
284 
285     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
286     if (log)
287         log->Printf ("SBBreakpoint(%p)::GetHitCount () => %u", m_opaque_sp.get(), count);
288 
289     return count;
290 }
291 
292 uint32_t
293 SBBreakpoint::GetIgnoreCount () const
294 {
295     uint32_t count = 0;
296     if (m_opaque_sp)
297     {
298         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
299         count = m_opaque_sp->GetIgnoreCount();
300     }
301 
302     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
303     if (log)
304         log->Printf ("SBBreakpoint(%p)::GetIgnoreCount () => %u", m_opaque_sp.get(), count);
305 
306     return count;
307 }
308 
309 void
310 SBBreakpoint::SetThreadID (tid_t tid)
311 {
312     if (m_opaque_sp)
313     {
314         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
315         m_opaque_sp->SetThreadID (tid);
316     }
317     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
318     if (log)
319         log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4x)", m_opaque_sp.get(), tid);
320 
321 }
322 
323 tid_t
324 SBBreakpoint::GetThreadID ()
325 {
326     tid_t tid = LLDB_INVALID_THREAD_ID;
327     if (m_opaque_sp)
328     {
329         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
330         tid = m_opaque_sp->GetThreadID();
331     }
332 
333     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
334     if (log)
335         log->Printf ("SBBreakpoint(%p)::GetThreadID () => 0x%4.4x", m_opaque_sp.get(), tid);
336     return tid;
337 }
338 
339 void
340 SBBreakpoint::SetThreadIndex (uint32_t index)
341 {
342     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
343     if (log)
344         log->Printf ("SBBreakpoint(%p)::SetThreadIndex (%u)", m_opaque_sp.get(), index);
345     if (m_opaque_sp)
346     {
347         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
348         m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index);
349     }
350 }
351 
352 uint32_t
353 SBBreakpoint::GetThreadIndex() const
354 {
355     uint32_t thread_idx = UINT32_MAX;
356     if (m_opaque_sp)
357     {
358         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
359         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
360         if (thread_spec != NULL)
361             thread_idx = thread_spec->GetIndex();
362     }
363     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
364     if (log)
365         log->Printf ("SBBreakpoint(%p)::GetThreadIndex () => %u", m_opaque_sp.get(), thread_idx);
366 
367     return thread_idx;
368 }
369 
370 
371 void
372 SBBreakpoint::SetThreadName (const char *thread_name)
373 {
374     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
375     if (log)
376         log->Printf ("SBBreakpoint(%p)::SetThreadName (%s)", m_opaque_sp.get(), thread_name);
377 
378     if (m_opaque_sp)
379     {
380         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
381         m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name);
382     }
383 }
384 
385 const char *
386 SBBreakpoint::GetThreadName () const
387 {
388     const char *name = NULL;
389     if (m_opaque_sp)
390     {
391         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
392         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
393         if (thread_spec != NULL)
394             name = thread_spec->GetName();
395     }
396     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
397     if (log)
398         log->Printf ("SBBreakpoint(%p)::GetThreadName () => %s", m_opaque_sp.get(), name);
399 
400     return name;
401 }
402 
403 void
404 SBBreakpoint::SetQueueName (const char *queue_name)
405 {
406     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
407     if (log)
408         log->Printf ("SBBreakpoint(%p)::SetQueueName (%s)", m_opaque_sp.get(), queue_name);
409     if (m_opaque_sp)
410     {
411         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
412         m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name);
413     }
414 }
415 
416 const char *
417 SBBreakpoint::GetQueueName () const
418 {
419     const char *name = NULL;
420     if (m_opaque_sp)
421     {
422         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
423         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
424         if (thread_spec)
425             name = thread_spec->GetQueueName();
426     }
427     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
428     if (log)
429         log->Printf ("SBBreakpoint(%p)::GetQueueName () => %s", m_opaque_sp.get(), name);
430 
431     return name;
432 }
433 
434 size_t
435 SBBreakpoint::GetNumResolvedLocations() const
436 {
437     size_t num_resolved = 0;
438     if (m_opaque_sp)
439     {
440         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
441         num_resolved = m_opaque_sp->GetNumResolvedLocations();
442     }
443     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
444     if (log)
445         log->Printf ("SBBreakpoint(%p)::GetNumResolvedLocations () => %zu", m_opaque_sp.get(), num_resolved);
446     return num_resolved;
447 }
448 
449 size_t
450 SBBreakpoint::GetNumLocations() const
451 {
452     size_t num_locs = 0;
453     if (m_opaque_sp)
454     {
455         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
456         num_locs = m_opaque_sp->GetNumLocations();
457     }
458     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
459     if (log)
460         log->Printf ("SBBreakpoint(%p)::GetNumLocations () => %zu", m_opaque_sp.get(), num_locs);
461     return num_locs;
462 }
463 
464 bool
465 SBBreakpoint::GetDescription (SBStream &s)
466 {
467     if (m_opaque_sp)
468     {
469         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
470         s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID());
471         m_opaque_sp->GetResolverDescription (s.get());
472         m_opaque_sp->GetFilterDescription (s.get());
473         const size_t num_locations = m_opaque_sp->GetNumLocations ();
474         s.Printf(", locations = %zu", num_locations);
475         return true;
476     }
477     s.Printf ("No value");
478     return false;
479 }
480 
481 bool
482 SBBreakpoint::PrivateBreakpointHitCallback
483 (
484     void *baton,
485     StoppointCallbackContext *ctx,
486     lldb::user_id_t break_id,
487     lldb::user_id_t break_loc_id
488 )
489 {
490     BreakpointSP bp_sp(ctx->exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
491     if (baton && bp_sp)
492     {
493         CallbackData *data = (CallbackData *)baton;
494         lldb_private::Breakpoint *bp = bp_sp.get();
495         if (bp && data->callback)
496         {
497             Process *process = ctx->exe_ctx.GetProcessPtr();
498             if (process)
499             {
500                 SBProcess sb_process (process->GetSP());
501                 SBThread sb_thread;
502                 SBBreakpointLocation sb_location;
503                 assert (bp_sp);
504                 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id));
505                 Thread *thread = ctx->exe_ctx.GetThreadPtr();
506                 if (thread)
507                     sb_thread.SetThread(thread->GetSP());
508 
509                 return data->callback (data->callback_baton,
510                                           sb_process,
511                                           sb_thread,
512                                           sb_location);
513             }
514         }
515     }
516     return true;    // Return true if we should stop at this breakpoint
517 }
518 
519 void
520 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton)
521 {
522     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
523 
524     if (log)
525         log->Printf ("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)", m_opaque_sp.get(), callback, baton);
526 
527     if (m_opaque_sp)
528     {
529         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
530         BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton));
531         m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false);
532     }
533 }
534 
535 
536 lldb_private::Breakpoint *
537 SBBreakpoint::operator->() const
538 {
539     return m_opaque_sp.get();
540 }
541 
542 lldb_private::Breakpoint *
543 SBBreakpoint::get() const
544 {
545     return m_opaque_sp.get();
546 }
547 
548 lldb::BreakpointSP &
549 SBBreakpoint::operator *()
550 {
551     return m_opaque_sp;
552 }
553 
554 const lldb::BreakpointSP &
555 SBBreakpoint::operator *() const
556 {
557     return m_opaque_sp;
558 }
559 
560 BreakpointEventType
561 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event)
562 {
563     if (event.IsValid())
564         return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP());
565     return eBreakpointEventTypeInvalidType;
566 }
567 
568 SBBreakpoint
569 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event)
570 {
571     SBBreakpoint sb_breakpoint;
572     if (event.IsValid())
573         sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP());
574     return sb_breakpoint;
575 }
576 
577 SBBreakpointLocation
578 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx)
579 {
580     SBBreakpointLocation sb_breakpoint_loc;
581     if (event.IsValid())
582         sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx));
583     return sb_breakpoint_loc;
584 }
585 
586 
587