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