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