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/Stream.h"
23 #include "lldb/Core/StreamFile.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Target/Thread.h"
27 #include "lldb/Target/ThreadSpec.h"
28 
29 
30 #include "lldb/lldb-enumerations.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 struct CallbackData
36 {
37     SBBreakpoint::BreakpointHitCallback callback;
38     void *callback_baton;
39 };
40 
41 class SBBreakpointCallbackBaton : public Baton
42 {
43 public:
44 
45     SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) :
46         Baton (new CallbackData)
47     {
48         CallbackData *data = (CallbackData *)m_data;
49         data->callback = callback;
50         data->callback_baton = baton;
51     }
52 
53     virtual ~SBBreakpointCallbackBaton()
54     {
55         CallbackData *data = (CallbackData *)m_data;
56 
57         if (data)
58         {
59             delete data;
60             m_data = NULL;
61         }
62     }
63 };
64 
65 
66 SBBreakpoint::SBBreakpoint () :
67     m_opaque_sp ()
68 {
69 }
70 
71 SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) :
72     m_opaque_sp (rhs.m_opaque_sp)
73 {
74 }
75 
76 
77 SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) :
78     m_opaque_sp (bp_sp)
79 {
80 }
81 
82 SBBreakpoint::~SBBreakpoint()
83 {
84 }
85 
86 const SBBreakpoint &
87 SBBreakpoint::operator = (const SBBreakpoint& rhs)
88 {
89     if (this != &rhs)
90     {
91         m_opaque_sp = rhs.m_opaque_sp;
92     }
93     return *this;
94 }
95 
96 break_id_t
97 SBBreakpoint::GetID () const
98 {
99     if (m_opaque_sp)
100         return m_opaque_sp->GetID();
101     return LLDB_INVALID_BREAK_ID;
102 }
103 
104 
105 bool
106 SBBreakpoint::IsValid() const
107 {
108     return m_opaque_sp;
109 }
110 
111 void
112 SBBreakpoint::ClearAllBreakpointSites ()
113 {
114     if (m_opaque_sp)
115         m_opaque_sp->ClearAllBreakpointSites ();
116 }
117 
118 SBBreakpointLocation
119 SBBreakpoint::FindLocationByAddress (addr_t vm_addr)
120 {
121     SBBreakpointLocation sb_bp_location;
122 
123     if (m_opaque_sp)
124     {
125         if (vm_addr != LLDB_INVALID_ADDRESS)
126         {
127             Address address;
128             Target &target = m_opaque_sp->GetTarget();
129             if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
130             {
131                 address.SetSection (NULL);
132                 address.SetOffset (vm_addr);
133             }
134             sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address));
135         }
136     }
137     return sb_bp_location;
138 }
139 
140 break_id_t
141 SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr)
142 {
143     break_id_t lldb_id = (break_id_t) 0;
144 
145     if (m_opaque_sp)
146     {
147         if (vm_addr != LLDB_INVALID_ADDRESS)
148         {
149             Address address;
150             Target &target = m_opaque_sp->GetTarget();
151             if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
152             {
153                 address.SetSection (NULL);
154                 address.SetOffset (vm_addr);
155             }
156             lldb_id = m_opaque_sp->FindLocationIDByAddress (address);
157         }
158     }
159 
160     return lldb_id;
161 }
162 
163 SBBreakpointLocation
164 SBBreakpoint::FindLocationByID (break_id_t bp_loc_id)
165 {
166     SBBreakpointLocation sb_bp_location;
167 
168     if (m_opaque_sp)
169         sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id));
170 
171     return sb_bp_location;
172 }
173 
174 SBBreakpointLocation
175 SBBreakpoint::GetLocationAtIndex (uint32_t index)
176 {
177     SBBreakpointLocation sb_bp_location;
178 
179     if (m_opaque_sp)
180         sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index));
181 
182     return sb_bp_location;
183 }
184 
185 void
186 SBBreakpoint::SetEnabled (bool enable)
187 {
188     if (m_opaque_sp)
189         m_opaque_sp->SetEnabled (enable);
190 }
191 
192 bool
193 SBBreakpoint::IsEnabled ()
194 {
195     if (m_opaque_sp)
196         return m_opaque_sp->IsEnabled();
197     else
198         return false;
199 }
200 
201 void
202 SBBreakpoint::SetIgnoreCount (uint32_t count)
203 {
204     if (m_opaque_sp)
205         m_opaque_sp->SetIgnoreCount (count);
206 }
207 
208 void
209 SBBreakpoint::SetCondition (const char *condition)
210 {
211     m_opaque_sp->SetCondition (condition);
212 }
213 
214 const char *
215 SBBreakpoint::GetCondition ()
216 {
217     return m_opaque_sp->GetConditionText ();
218 }
219 
220 uint32_t
221 SBBreakpoint::GetHitCount () const
222 {
223     if (m_opaque_sp)
224         return m_opaque_sp->GetHitCount();
225     else
226         return 0;
227 }
228 
229 uint32_t
230 SBBreakpoint::GetIgnoreCount () const
231 {
232     if (m_opaque_sp)
233         return m_opaque_sp->GetIgnoreCount();
234     else
235         return 0;
236 }
237 
238 void
239 SBBreakpoint::SetThreadID (tid_t sb_thread_id)
240 {
241     if (m_opaque_sp)
242         m_opaque_sp->SetThreadID (sb_thread_id);
243 }
244 
245 tid_t
246 SBBreakpoint::GetThreadID ()
247 {
248     tid_t lldb_thread_id = LLDB_INVALID_THREAD_ID;
249     if (m_opaque_sp)
250         lldb_thread_id = m_opaque_sp->GetThreadID();
251 
252     return lldb_thread_id;
253 }
254 
255 void
256 SBBreakpoint::SetThreadIndex (uint32_t index)
257 {
258     if (m_opaque_sp)
259         m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index);
260 }
261 
262 uint32_t
263 SBBreakpoint::GetThreadIndex() const
264 {
265     if (m_opaque_sp)
266     {
267         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec();
268         if (thread_spec == NULL)
269             return 0;
270         else
271             return thread_spec->GetIndex();
272     }
273     return 0;
274 }
275 
276 
277 void
278 SBBreakpoint::SetThreadName (const char *thread_name)
279 {
280     if (m_opaque_sp)
281         m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name);
282 }
283 
284 const char *
285 SBBreakpoint::GetThreadName () const
286 {
287     if (m_opaque_sp)
288     {
289         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec();
290         if (thread_spec == NULL)
291             return NULL;
292         else
293             return thread_spec->GetName();
294     }
295     return NULL;
296 }
297 
298 void
299 SBBreakpoint::SetQueueName (const char *queue_name)
300 {
301     if (m_opaque_sp)
302         m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name);
303 }
304 
305 const char *
306 SBBreakpoint::GetQueueName () const
307 {
308     if (m_opaque_sp)
309     {
310         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec();
311         if (thread_spec == NULL)
312             return NULL;
313         else
314             return thread_spec->GetQueueName();
315     }
316     return NULL;
317 }
318 
319 size_t
320 SBBreakpoint::GetNumResolvedLocations() const
321 {
322     if (m_opaque_sp)
323         return m_opaque_sp->GetNumResolvedLocations();
324     else
325         return 0;
326 }
327 
328 size_t
329 SBBreakpoint::GetNumLocations() const
330 {
331     if (m_opaque_sp)
332         return m_opaque_sp->GetNumLocations();
333     else
334         return 0;
335 }
336 
337 bool
338 SBBreakpoint::GetDescription (SBStream &s)
339 {
340     if (m_opaque_sp)
341     {
342         s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID());
343         m_opaque_sp->GetResolverDescription (s.get());
344         m_opaque_sp->GetFilterDescription (s.get());
345         const size_t num_locations = m_opaque_sp->GetNumLocations ();
346         s.Printf(", locations = %zu", num_locations);
347         return true;
348     }
349     s.Printf ("No value");
350     return false;
351 }
352 
353 bool
354 SBBreakpoint::PrivateBreakpointHitCallback
355 (
356     void *baton,
357     StoppointCallbackContext *ctx,
358     lldb::user_id_t break_id,
359     lldb::user_id_t break_loc_id
360 )
361 {
362     BreakpointSP bp_sp(ctx->exe_ctx.target->GetBreakpointList().FindBreakpointByID(break_id));
363     if (baton && bp_sp)
364     {
365         CallbackData *data = (CallbackData *)baton;
366         lldb_private::Breakpoint *bp = bp_sp.get();
367         if (bp && data->callback)
368         {
369             if (ctx->exe_ctx.process)
370             {
371                 SBProcess sb_process (ctx->exe_ctx.process->GetSP());
372                 SBThread sb_thread;
373                 SBBreakpointLocation sb_location;
374                 assert (bp_sp);
375                 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id));
376                 if (ctx->exe_ctx.thread)
377                     sb_thread.SetThread(ctx->exe_ctx.thread->GetSP());
378 
379                 return data->callback (data->callback_baton,
380                                           sb_process,
381                                           sb_thread,
382                                           sb_location);
383             }
384         }
385     }
386     return true;    // Return true if we should stop at this breakpoint
387 }
388 
389 void
390 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton)
391 {
392     if (m_opaque_sp.get())
393     {
394         BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton));
395         m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false);
396     }
397 }
398 
399 
400 lldb_private::Breakpoint *
401 SBBreakpoint::operator->() const
402 {
403     return m_opaque_sp.get();
404 }
405 
406 lldb_private::Breakpoint *
407 SBBreakpoint::get() const
408 {
409     return m_opaque_sp.get();
410 }
411 
412 lldb::BreakpointSP &
413 SBBreakpoint::operator *()
414 {
415     return m_opaque_sp;
416 }
417 
418 const lldb::BreakpointSP &
419 SBBreakpoint::operator *() const
420 {
421     return m_opaque_sp;
422 }
423 
424 BreakpointEventType
425 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event)
426 {
427     if (event.IsValid())
428         return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP());
429     return eBreakpointEventTypeInvalidType;
430 }
431 
432 SBBreakpoint
433 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event)
434 {
435     SBBreakpoint sb_breakpoint;
436     if (event.IsValid())
437         sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP());
438     return sb_breakpoint;
439 }
440 
441 SBBreakpointLocation
442 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx)
443 {
444     SBBreakpointLocation sb_breakpoint_loc;
445     if (event.IsValid())
446         sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx));
447     return sb_breakpoint_loc;
448 }
449 
450 
451