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