blob: 2cf4e0b824fb16cef4227111643148147f5f96d1 [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"
23#include "lldb/Target/Thread.h"
24#include "lldb/Target/Target.h"
25
26
27#include "lldb/lldb-enumerations.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
32struct CallbackData
33{
34 SBBreakpoint::BreakpointHitCallback callback;
35 void *callback_baton;
36};
37
38class SBBreakpointCallbackBaton : public Baton
39{
40public:
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
63SBBreakpoint::SBBreakpoint () :
64 m_break_sp ()
65{
66}
67
68SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) :
69 m_break_sp (rhs.m_break_sp)
70{
71}
72
73
74SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) :
75 m_break_sp (bp_sp)
76{
77}
78
79SBBreakpoint::~SBBreakpoint()
80{
81}
82
83const SBBreakpoint &
84SBBreakpoint::operator = (const SBBreakpoint& rhs)
85{
86 if (this != &rhs)
87 {
88 m_break_sp = rhs.m_break_sp;
89 }
90 return *this;
91}
92
93break_id_t
94SBBreakpoint::GetID () const
95{
96 if (m_break_sp)
97 return m_break_sp->GetID();
98 return LLDB_INVALID_BREAK_ID;
99}
100
101
102bool
103SBBreakpoint::IsValid() const
104{
105 return m_break_sp;
106}
107
108void
109SBBreakpoint::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
122void
123SBBreakpoint::ClearAllBreakpointSites ()
124{
125 if (m_break_sp)
126 m_break_sp->ClearAllBreakpointSites ();
127}
128
129SBBreakpointLocation
130SBBreakpoint::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
151break_id_t
152SBBreakpoint::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
174SBBreakpointLocation
175SBBreakpoint::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
185SBBreakpointLocation
186SBBreakpoint::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
196void
197SBBreakpoint::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
230void
231SBBreakpoint::SetEnabled (bool enable)
232{
233 if (m_break_sp)
234 m_break_sp->SetEnabled (enable);
235}
236
237bool
238SBBreakpoint::IsEnabled ()
239{
240 if (m_break_sp)
241 return m_break_sp->IsEnabled();
242 else
243 return false;
244}
245
246void
247SBBreakpoint::SetIgnoreCount (int32_t count)
248{
249 if (m_break_sp)
250 m_break_sp->SetIgnoreCount (count);
251}
252
253int32_t
254SBBreakpoint::GetIgnoreCount () const
255{
256 if (m_break_sp)
257 return m_break_sp->GetIgnoreCount();
258 else
259 return 0;
260}
261
262void
263SBBreakpoint::SetThreadID (tid_t sb_thread_id)
264{
265 if (m_break_sp)
266 m_break_sp->SetThreadID (sb_thread_id);
267}
268
269tid_t
270SBBreakpoint::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
279size_t
280SBBreakpoint::GetNumResolvedLocations() const
281{
282 if (m_break_sp)
283 return m_break_sp->GetNumResolvedLocations();
284 else
285 return 0;
286}
287
288size_t
289SBBreakpoint::GetNumLocations() const
290{
291 if (m_break_sp)
292 return m_break_sp->GetNumLocations();
293 else
294 return 0;
295}
296
297void
298SBBreakpoint::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
334bool
335SBBreakpoint::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
370void
371SBBreakpoint::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
381lldb_private::Breakpoint *
382SBBreakpoint::operator->() const
383{
384 return m_break_sp.get();
385}
386
387lldb_private::Breakpoint *
388SBBreakpoint::get() const
389{
390 return m_break_sp.get();
391}
392
393lldb::BreakpointSP &
394SBBreakpoint::operator *()
395{
396 return m_break_sp;
397}
398
399const lldb::BreakpointSP &
400SBBreakpoint::operator *() const
401{
402 return m_break_sp;
403}
404