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 (bool) 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.SetRawAddress (vm_addr);
155             }
156             sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address));
157         }
158     }
159     return sb_bp_location;
160 }
161 
162 break_id_t
163 SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr)
164 {
165     break_id_t break_id = LLDB_INVALID_BREAK_ID;
166 
167     if (m_opaque_sp && vm_addr != LLDB_INVALID_ADDRESS)
168     {
169         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
170         Address address;
171         Target &target = m_opaque_sp->GetTarget();
172         if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
173         {
174             address.SetRawAddress (vm_addr);
175         }
176         break_id = m_opaque_sp->FindLocationIDByAddress (address);
177     }
178 
179     return break_id;
180 }
181 
182 SBBreakpointLocation
183 SBBreakpoint::FindLocationByID (break_id_t bp_loc_id)
184 {
185     SBBreakpointLocation sb_bp_location;
186 
187     if (m_opaque_sp)
188     {
189         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
190         sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id));
191     }
192 
193     return sb_bp_location;
194 }
195 
196 SBBreakpointLocation
197 SBBreakpoint::GetLocationAtIndex (uint32_t index)
198 {
199     SBBreakpointLocation sb_bp_location;
200 
201     if (m_opaque_sp)
202     {
203         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
204         sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index));
205     }
206 
207     return sb_bp_location;
208 }
209 
210 void
211 SBBreakpoint::SetEnabled (bool enable)
212 {
213     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
214 
215     if (log)
216         log->Printf ("SBBreakpoint(%p)::SetEnabled (enabled=%i)", m_opaque_sp.get(), enable);
217 
218     if (m_opaque_sp)
219     {
220         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
221         m_opaque_sp->SetEnabled (enable);
222     }
223 }
224 
225 bool
226 SBBreakpoint::IsEnabled ()
227 {
228     if (m_opaque_sp)
229     {
230         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
231         return m_opaque_sp->IsEnabled();
232     }
233     else
234         return false;
235 }
236 
237 bool
238 SBBreakpoint::IsInternal ()
239 {
240     if (m_opaque_sp)
241     {
242         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
243         return m_opaque_sp->IsInternal();
244     }
245     else
246         return false;
247 }
248 
249 void
250 SBBreakpoint::SetIgnoreCount (uint32_t count)
251 {
252     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
253 
254     if (log)
255         log->Printf ("SBBreakpoint(%p)::SetIgnoreCount (count=%u)", m_opaque_sp.get(), count);
256 
257     if (m_opaque_sp)
258     {
259         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
260         m_opaque_sp->SetIgnoreCount (count);
261     }
262 }
263 
264 void
265 SBBreakpoint::SetCondition (const char *condition)
266 {
267     if (m_opaque_sp)
268     {
269         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
270         m_opaque_sp->SetCondition (condition);
271     }
272 }
273 
274 const char *
275 SBBreakpoint::GetCondition ()
276 {
277     if (m_opaque_sp)
278     {
279         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
280         return m_opaque_sp->GetConditionText ();
281     }
282     return NULL;
283 }
284 
285 uint32_t
286 SBBreakpoint::GetHitCount () const
287 {
288     uint32_t count = 0;
289     if (m_opaque_sp)
290     {
291         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
292         count = m_opaque_sp->GetHitCount();
293     }
294 
295     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
296     if (log)
297         log->Printf ("SBBreakpoint(%p)::GetHitCount () => %u", m_opaque_sp.get(), count);
298 
299     return count;
300 }
301 
302 uint32_t
303 SBBreakpoint::GetIgnoreCount () const
304 {
305     uint32_t count = 0;
306     if (m_opaque_sp)
307     {
308         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
309         count = m_opaque_sp->GetIgnoreCount();
310     }
311 
312     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
313     if (log)
314         log->Printf ("SBBreakpoint(%p)::GetIgnoreCount () => %u", m_opaque_sp.get(), count);
315 
316     return count;
317 }
318 
319 void
320 SBBreakpoint::SetThreadID (tid_t tid)
321 {
322     if (m_opaque_sp)
323     {
324         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
325         m_opaque_sp->SetThreadID (tid);
326     }
327     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
328     if (log)
329         log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4llx)", m_opaque_sp.get(), tid);
330 
331 }
332 
333 tid_t
334 SBBreakpoint::GetThreadID ()
335 {
336     tid_t tid = LLDB_INVALID_THREAD_ID;
337     if (m_opaque_sp)
338     {
339         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
340         tid = m_opaque_sp->GetThreadID();
341     }
342 
343     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
344     if (log)
345         log->Printf ("SBBreakpoint(%p)::GetThreadID () => 0x%4.4llx", m_opaque_sp.get(), tid);
346     return tid;
347 }
348 
349 void
350 SBBreakpoint::SetThreadIndex (uint32_t index)
351 {
352     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
353     if (log)
354         log->Printf ("SBBreakpoint(%p)::SetThreadIndex (%u)", m_opaque_sp.get(), index);
355     if (m_opaque_sp)
356     {
357         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
358         m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index);
359     }
360 }
361 
362 uint32_t
363 SBBreakpoint::GetThreadIndex() const
364 {
365     uint32_t thread_idx = UINT32_MAX;
366     if (m_opaque_sp)
367     {
368         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
369         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
370         if (thread_spec != NULL)
371             thread_idx = thread_spec->GetIndex();
372     }
373     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
374     if (log)
375         log->Printf ("SBBreakpoint(%p)::GetThreadIndex () => %u", m_opaque_sp.get(), thread_idx);
376 
377     return thread_idx;
378 }
379 
380 
381 void
382 SBBreakpoint::SetThreadName (const char *thread_name)
383 {
384     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
385     if (log)
386         log->Printf ("SBBreakpoint(%p)::SetThreadName (%s)", m_opaque_sp.get(), thread_name);
387 
388     if (m_opaque_sp)
389     {
390         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
391         m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name);
392     }
393 }
394 
395 const char *
396 SBBreakpoint::GetThreadName () const
397 {
398     const char *name = NULL;
399     if (m_opaque_sp)
400     {
401         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
402         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
403         if (thread_spec != NULL)
404             name = thread_spec->GetName();
405     }
406     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
407     if (log)
408         log->Printf ("SBBreakpoint(%p)::GetThreadName () => %s", m_opaque_sp.get(), name);
409 
410     return name;
411 }
412 
413 void
414 SBBreakpoint::SetQueueName (const char *queue_name)
415 {
416     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
417     if (log)
418         log->Printf ("SBBreakpoint(%p)::SetQueueName (%s)", m_opaque_sp.get(), queue_name);
419     if (m_opaque_sp)
420     {
421         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
422         m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name);
423     }
424 }
425 
426 const char *
427 SBBreakpoint::GetQueueName () const
428 {
429     const char *name = NULL;
430     if (m_opaque_sp)
431     {
432         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
433         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
434         if (thread_spec)
435             name = thread_spec->GetQueueName();
436     }
437     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
438     if (log)
439         log->Printf ("SBBreakpoint(%p)::GetQueueName () => %s", m_opaque_sp.get(), name);
440 
441     return name;
442 }
443 
444 size_t
445 SBBreakpoint::GetNumResolvedLocations() const
446 {
447     size_t num_resolved = 0;
448     if (m_opaque_sp)
449     {
450         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
451         num_resolved = m_opaque_sp->GetNumResolvedLocations();
452     }
453     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
454     if (log)
455         log->Printf ("SBBreakpoint(%p)::GetNumResolvedLocations () => %llu", m_opaque_sp.get(), (uint64_t)num_resolved);
456     return num_resolved;
457 }
458 
459 size_t
460 SBBreakpoint::GetNumLocations() const
461 {
462     size_t num_locs = 0;
463     if (m_opaque_sp)
464     {
465         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
466         num_locs = m_opaque_sp->GetNumLocations();
467     }
468     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
469     if (log)
470         log->Printf ("SBBreakpoint(%p)::GetNumLocations () => %llu", m_opaque_sp.get(), (uint64_t)num_locs);
471     return num_locs;
472 }
473 
474 bool
475 SBBreakpoint::GetDescription (SBStream &s)
476 {
477     if (m_opaque_sp)
478     {
479         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
480         s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID());
481         m_opaque_sp->GetResolverDescription (s.get());
482         m_opaque_sp->GetFilterDescription (s.get());
483         const size_t num_locations = m_opaque_sp->GetNumLocations ();
484         s.Printf(", locations = %llu", (uint64_t)num_locations);
485         return true;
486     }
487     s.Printf ("No value");
488     return false;
489 }
490 
491 bool
492 SBBreakpoint::PrivateBreakpointHitCallback
493 (
494     void *baton,
495     StoppointCallbackContext *ctx,
496     lldb::user_id_t break_id,
497     lldb::user_id_t break_loc_id
498 )
499 {
500     ExecutionContext exe_ctx (ctx->exe_ctx_ref);
501     BreakpointSP bp_sp(exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
502     if (baton && bp_sp)
503     {
504         CallbackData *data = (CallbackData *)baton;
505         lldb_private::Breakpoint *bp = bp_sp.get();
506         if (bp && data->callback)
507         {
508             Process *process = exe_ctx.GetProcessPtr();
509             if (process)
510             {
511                 SBProcess sb_process (process->shared_from_this());
512                 SBThread sb_thread;
513                 SBBreakpointLocation sb_location;
514                 assert (bp_sp);
515                 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id));
516                 Thread *thread = exe_ctx.GetThreadPtr();
517                 if (thread)
518                     sb_thread.SetThread(thread->shared_from_this());
519 
520                 return data->callback (data->callback_baton,
521                                           sb_process,
522                                           sb_thread,
523                                           sb_location);
524             }
525         }
526     }
527     return true;    // Return true if we should stop at this breakpoint
528 }
529 
530 void
531 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton)
532 {
533     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
534 
535     if (log)
536         log->Printf ("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)", m_opaque_sp.get(), callback, baton);
537 
538     if (m_opaque_sp)
539     {
540         Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
541         BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton));
542         m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false);
543     }
544 }
545 
546 
547 lldb_private::Breakpoint *
548 SBBreakpoint::operator->() const
549 {
550     return m_opaque_sp.get();
551 }
552 
553 lldb_private::Breakpoint *
554 SBBreakpoint::get() const
555 {
556     return m_opaque_sp.get();
557 }
558 
559 lldb::BreakpointSP &
560 SBBreakpoint::operator *()
561 {
562     return m_opaque_sp;
563 }
564 
565 const lldb::BreakpointSP &
566 SBBreakpoint::operator *() const
567 {
568     return m_opaque_sp;
569 }
570 
571 bool
572 SBBreakpoint::EventIsBreakpointEvent (const lldb::SBEvent &event)
573 {
574     return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != NULL;
575 
576 }
577 
578 BreakpointEventType
579 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event)
580 {
581     if (event.IsValid())
582         return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP());
583     return eBreakpointEventTypeInvalidType;
584 }
585 
586 SBBreakpoint
587 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event)
588 {
589     SBBreakpoint sb_breakpoint;
590     if (event.IsValid())
591         sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP());
592     return sb_breakpoint;
593 }
594 
595 SBBreakpointLocation
596 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx)
597 {
598     SBBreakpointLocation sb_breakpoint_loc;
599     if (event.IsValid())
600         sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx));
601     return sb_breakpoint_loc;
602 }
603 
604 uint32_t
605 SBBreakpoint::GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event)
606 {
607     uint32_t num_locations = 0;
608     if (event.IsValid())
609         num_locations = (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (event.GetSP()));
610     return num_locations;
611 }
612 
613 
614