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 uint32_t
209 SBBreakpoint::GetHitCount () const
210 {
211     if (m_opaque_sp)
212         return m_opaque_sp->GetHitCount();
213     else
214         return 0;
215 }
216 
217 uint32_t
218 SBBreakpoint::GetIgnoreCount () const
219 {
220     if (m_opaque_sp)
221         return m_opaque_sp->GetIgnoreCount();
222     else
223         return 0;
224 }
225 
226 void
227 SBBreakpoint::SetThreadID (tid_t sb_thread_id)
228 {
229     if (m_opaque_sp)
230         m_opaque_sp->SetThreadID (sb_thread_id);
231 }
232 
233 tid_t
234 SBBreakpoint::GetThreadID ()
235 {
236     tid_t lldb_thread_id = LLDB_INVALID_THREAD_ID;
237     if (m_opaque_sp)
238         lldb_thread_id = m_opaque_sp->GetThreadID();
239 
240     return lldb_thread_id;
241 }
242 
243 void
244 SBBreakpoint::SetThreadIndex (uint32_t index)
245 {
246     if (m_opaque_sp)
247         m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index);
248 }
249 
250 uint32_t
251 SBBreakpoint::GetThreadIndex() const
252 {
253     if (m_opaque_sp)
254     {
255         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec();
256         if (thread_spec == NULL)
257             return 0;
258         else
259             return thread_spec->GetIndex();
260     }
261     return 0;
262 }
263 
264 
265 void
266 SBBreakpoint::SetThreadName (const char *thread_name)
267 {
268     if (m_opaque_sp)
269         m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name);
270 }
271 
272 const char *
273 SBBreakpoint::GetThreadName () const
274 {
275     if (m_opaque_sp)
276     {
277         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec();
278         if (thread_spec == NULL)
279             return NULL;
280         else
281             return thread_spec->GetName();
282     }
283     return NULL;
284 }
285 
286 void
287 SBBreakpoint::SetQueueName (const char *queue_name)
288 {
289     if (m_opaque_sp)
290         m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name);
291 }
292 
293 const char *
294 SBBreakpoint::GetQueueName () const
295 {
296     if (m_opaque_sp)
297     {
298         const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpec();
299         if (thread_spec == NULL)
300             return NULL;
301         else
302             return thread_spec->GetQueueName();
303     }
304     return NULL;
305 }
306 
307 size_t
308 SBBreakpoint::GetNumResolvedLocations() const
309 {
310     if (m_opaque_sp)
311         return m_opaque_sp->GetNumResolvedLocations();
312     else
313         return 0;
314 }
315 
316 size_t
317 SBBreakpoint::GetNumLocations() const
318 {
319     if (m_opaque_sp)
320         return m_opaque_sp->GetNumLocations();
321     else
322         return 0;
323 }
324 
325 bool
326 SBBreakpoint::GetDescription (SBStream &s)
327 {
328     if (m_opaque_sp)
329     {
330         s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID());
331         m_opaque_sp->GetResolverDescription (s.get());
332         m_opaque_sp->GetFilterDescription (s.get());
333         const size_t num_locations = m_opaque_sp->GetNumLocations ();
334         s.Printf(", locations = %zu", num_locations);
335         return true;
336     }
337     s.Printf ("No value");
338     return false;
339 }
340 
341 bool
342 SBBreakpoint::PrivateBreakpointHitCallback
343 (
344     void *baton,
345     StoppointCallbackContext *ctx,
346     lldb::user_id_t break_id,
347     lldb::user_id_t break_loc_id
348 )
349 {
350     BreakpointSP bp_sp(ctx->exe_ctx.target->GetBreakpointList().FindBreakpointByID(break_id));
351     if (baton && bp_sp)
352     {
353         CallbackData *data = (CallbackData *)baton;
354         lldb_private::Breakpoint *bp = bp_sp.get();
355         if (bp && data->callback)
356         {
357             if (ctx->exe_ctx.process)
358             {
359                 SBProcess sb_process (ctx->exe_ctx.process->GetSP());
360                 SBThread sb_thread;
361                 SBBreakpointLocation sb_location;
362                 assert (bp_sp);
363                 sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id));
364                 if (ctx->exe_ctx.thread)
365                     sb_thread.SetThread(ctx->exe_ctx.thread->GetSP());
366 
367                 return data->callback (data->callback_baton,
368                                           sb_process,
369                                           sb_thread,
370                                           sb_location);
371             }
372         }
373     }
374     return true;    // Return true if we should stop at this breakpoint
375 }
376 
377 void
378 SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton)
379 {
380     if (m_opaque_sp.get())
381     {
382         BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton));
383         m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false);
384     }
385 }
386 
387 
388 lldb_private::Breakpoint *
389 SBBreakpoint::operator->() const
390 {
391     return m_opaque_sp.get();
392 }
393 
394 lldb_private::Breakpoint *
395 SBBreakpoint::get() const
396 {
397     return m_opaque_sp.get();
398 }
399 
400 lldb::BreakpointSP &
401 SBBreakpoint::operator *()
402 {
403     return m_opaque_sp;
404 }
405 
406 const lldb::BreakpointSP &
407 SBBreakpoint::operator *() const
408 {
409     return m_opaque_sp;
410 }
411 
412 BreakpointEventType
413 SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event)
414 {
415     if (event.IsValid())
416         return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP());
417     return eBreakpointEventTypeInvalidType;
418 }
419 
420 SBBreakpoint
421 SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event)
422 {
423     SBBreakpoint sb_breakpoint;
424     if (event.IsValid())
425         sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP());
426     return sb_breakpoint;
427 }
428 
429 SBBreakpointLocation
430 SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx)
431 {
432     SBBreakpointLocation sb_breakpoint_loc;
433     if (event.IsValid())
434         sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx));
435     return sb_breakpoint_loc;
436 }
437 
438 
439