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