SBBreakpoint.cpp revision 269024
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/Log.h"
23#include "lldb/Core/Stream.h"
24#include "lldb/Core/StreamFile.h"
25#include "lldb/Target/Process.h"
26#include "lldb/Target/SectionLoadList.h"
27#include "lldb/Target/Target.h"
28#include "lldb/Target/Thread.h"
29#include "lldb/Target/ThreadSpec.h"
30
31
32#include "lldb/lldb-enumerations.h"
33
34using namespace lldb;
35using namespace lldb_private;
36
37struct CallbackData
38{
39    SBBreakpoint::BreakpointHitCallback callback;
40    void *callback_baton;
41};
42
43class SBBreakpointCallbackBaton : public Baton
44{
45public:
46
47    SBBreakpointCallbackBaton (SBBreakpoint::BreakpointHitCallback callback, void *baton) :
48        Baton (new CallbackData)
49    {
50        CallbackData *data = (CallbackData *)m_data;
51        data->callback = callback;
52        data->callback_baton = baton;
53    }
54
55    virtual ~SBBreakpointCallbackBaton()
56    {
57        CallbackData *data = (CallbackData *)m_data;
58
59        if (data)
60        {
61            delete data;
62            m_data = NULL;
63        }
64    }
65};
66
67
68SBBreakpoint::SBBreakpoint () :
69    m_opaque_sp ()
70{
71}
72
73SBBreakpoint::SBBreakpoint (const SBBreakpoint& rhs) :
74    m_opaque_sp (rhs.m_opaque_sp)
75{
76}
77
78
79SBBreakpoint::SBBreakpoint (const lldb::BreakpointSP &bp_sp) :
80    m_opaque_sp (bp_sp)
81{
82}
83
84SBBreakpoint::~SBBreakpoint()
85{
86}
87
88const SBBreakpoint &
89SBBreakpoint::operator = (const SBBreakpoint& rhs)
90{
91    if (this != &rhs)
92        m_opaque_sp = rhs.m_opaque_sp;
93    return *this;
94}
95
96bool
97SBBreakpoint::operator == (const lldb::SBBreakpoint& rhs)
98{
99    if (m_opaque_sp && rhs.m_opaque_sp)
100        return m_opaque_sp.get() == rhs.m_opaque_sp.get();
101    return false;
102}
103
104bool
105SBBreakpoint::operator != (const lldb::SBBreakpoint& rhs)
106{
107    if (m_opaque_sp && rhs.m_opaque_sp)
108        return m_opaque_sp.get() != rhs.m_opaque_sp.get();
109    return (m_opaque_sp && !rhs.m_opaque_sp) || (rhs.m_opaque_sp && !m_opaque_sp);
110}
111
112break_id_t
113SBBreakpoint::GetID () const
114{
115    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
116
117    break_id_t break_id = LLDB_INVALID_BREAK_ID;
118    if (m_opaque_sp)
119        break_id = m_opaque_sp->GetID();
120
121    if (log)
122    {
123        if (break_id == LLDB_INVALID_BREAK_ID)
124            log->Printf ("SBBreakpoint(%p)::GetID () => LLDB_INVALID_BREAK_ID", m_opaque_sp.get());
125        else
126            log->Printf ("SBBreakpoint(%p)::GetID () => %u", m_opaque_sp.get(), break_id);
127    }
128
129    return break_id;
130}
131
132
133bool
134SBBreakpoint::IsValid() const
135{
136    return (bool) m_opaque_sp;
137}
138
139void
140SBBreakpoint::ClearAllBreakpointSites ()
141{
142    if (m_opaque_sp)
143    {
144        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
145        m_opaque_sp->ClearAllBreakpointSites ();
146    }
147}
148
149SBBreakpointLocation
150SBBreakpoint::FindLocationByAddress (addr_t vm_addr)
151{
152    SBBreakpointLocation sb_bp_location;
153
154    if (m_opaque_sp)
155    {
156        if (vm_addr != LLDB_INVALID_ADDRESS)
157        {
158            Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
159            Address address;
160            Target &target = m_opaque_sp->GetTarget();
161            if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
162            {
163                address.SetRawAddress (vm_addr);
164            }
165            sb_bp_location.SetLocation (m_opaque_sp->FindLocationByAddress (address));
166        }
167    }
168    return sb_bp_location;
169}
170
171break_id_t
172SBBreakpoint::FindLocationIDByAddress (addr_t vm_addr)
173{
174    break_id_t break_id = LLDB_INVALID_BREAK_ID;
175
176    if (m_opaque_sp && vm_addr != LLDB_INVALID_ADDRESS)
177    {
178        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
179        Address address;
180        Target &target = m_opaque_sp->GetTarget();
181        if (target.GetSectionLoadList().ResolveLoadAddress (vm_addr, address) == false)
182        {
183            address.SetRawAddress (vm_addr);
184        }
185        break_id = m_opaque_sp->FindLocationIDByAddress (address);
186    }
187
188    return break_id;
189}
190
191SBBreakpointLocation
192SBBreakpoint::FindLocationByID (break_id_t bp_loc_id)
193{
194    SBBreakpointLocation sb_bp_location;
195
196    if (m_opaque_sp)
197    {
198        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
199        sb_bp_location.SetLocation (m_opaque_sp->FindLocationByID (bp_loc_id));
200    }
201
202    return sb_bp_location;
203}
204
205SBBreakpointLocation
206SBBreakpoint::GetLocationAtIndex (uint32_t index)
207{
208    SBBreakpointLocation sb_bp_location;
209
210    if (m_opaque_sp)
211    {
212        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
213        sb_bp_location.SetLocation (m_opaque_sp->GetLocationAtIndex (index));
214    }
215
216    return sb_bp_location;
217}
218
219void
220SBBreakpoint::SetEnabled (bool enable)
221{
222    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
223
224    if (log)
225        log->Printf ("SBBreakpoint(%p)::SetEnabled (enabled=%i)", m_opaque_sp.get(), enable);
226
227    if (m_opaque_sp)
228    {
229        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
230        m_opaque_sp->SetEnabled (enable);
231    }
232}
233
234bool
235SBBreakpoint::IsEnabled ()
236{
237    if (m_opaque_sp)
238    {
239        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
240        return m_opaque_sp->IsEnabled();
241    }
242    else
243        return false;
244}
245
246void
247SBBreakpoint::SetOneShot (bool one_shot)
248{
249    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
250
251    if (log)
252        log->Printf ("SBBreakpoint(%p)::SetOneShot (one_shot=%i)", m_opaque_sp.get(), one_shot);
253
254    if (m_opaque_sp)
255    {
256        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
257        m_opaque_sp->SetOneShot (one_shot);
258    }
259}
260
261bool
262SBBreakpoint::IsOneShot () const
263{
264    if (m_opaque_sp)
265    {
266        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
267        return m_opaque_sp->IsOneShot();
268    }
269    else
270        return false;
271}
272
273bool
274SBBreakpoint::IsInternal ()
275{
276    if (m_opaque_sp)
277    {
278        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
279        return m_opaque_sp->IsInternal();
280    }
281    else
282        return false;
283}
284
285void
286SBBreakpoint::SetIgnoreCount (uint32_t count)
287{
288    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
289
290    if (log)
291        log->Printf ("SBBreakpoint(%p)::SetIgnoreCount (count=%u)", m_opaque_sp.get(), count);
292
293    if (m_opaque_sp)
294    {
295        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
296        m_opaque_sp->SetIgnoreCount (count);
297    }
298}
299
300void
301SBBreakpoint::SetCondition (const char *condition)
302{
303    if (m_opaque_sp)
304    {
305        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
306        m_opaque_sp->SetCondition (condition);
307    }
308}
309
310const char *
311SBBreakpoint::GetCondition ()
312{
313    if (m_opaque_sp)
314    {
315        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
316        return m_opaque_sp->GetConditionText ();
317    }
318    return NULL;
319}
320
321uint32_t
322SBBreakpoint::GetHitCount () const
323{
324    uint32_t count = 0;
325    if (m_opaque_sp)
326    {
327        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
328        count = m_opaque_sp->GetHitCount();
329    }
330
331    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
332    if (log)
333        log->Printf ("SBBreakpoint(%p)::GetHitCount () => %u", m_opaque_sp.get(), count);
334
335    return count;
336}
337
338uint32_t
339SBBreakpoint::GetIgnoreCount () const
340{
341    uint32_t count = 0;
342    if (m_opaque_sp)
343    {
344        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
345        count = m_opaque_sp->GetIgnoreCount();
346    }
347
348    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
349    if (log)
350        log->Printf ("SBBreakpoint(%p)::GetIgnoreCount () => %u", m_opaque_sp.get(), count);
351
352    return count;
353}
354
355void
356SBBreakpoint::SetThreadID (tid_t tid)
357{
358    if (m_opaque_sp)
359    {
360        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
361        m_opaque_sp->SetThreadID (tid);
362    }
363    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
364    if (log)
365        log->Printf ("SBBreakpoint(%p)::SetThreadID (tid=0x%4.4" PRIx64 ")", m_opaque_sp.get(), tid);
366
367}
368
369tid_t
370SBBreakpoint::GetThreadID ()
371{
372    tid_t tid = LLDB_INVALID_THREAD_ID;
373    if (m_opaque_sp)
374    {
375        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
376        tid = m_opaque_sp->GetThreadID();
377    }
378
379    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
380    if (log)
381        log->Printf ("SBBreakpoint(%p)::GetThreadID () => 0x%4.4" PRIx64, m_opaque_sp.get(), tid);
382    return tid;
383}
384
385void
386SBBreakpoint::SetThreadIndex (uint32_t index)
387{
388    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
389    if (log)
390        log->Printf ("SBBreakpoint(%p)::SetThreadIndex (%u)", m_opaque_sp.get(), index);
391    if (m_opaque_sp)
392    {
393        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
394        m_opaque_sp->GetOptions()->GetThreadSpec()->SetIndex (index);
395    }
396}
397
398uint32_t
399SBBreakpoint::GetThreadIndex() const
400{
401    uint32_t thread_idx = UINT32_MAX;
402    if (m_opaque_sp)
403    {
404        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
405        const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
406        if (thread_spec != NULL)
407            thread_idx = thread_spec->GetIndex();
408    }
409    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
410    if (log)
411        log->Printf ("SBBreakpoint(%p)::GetThreadIndex () => %u", m_opaque_sp.get(), thread_idx);
412
413    return thread_idx;
414}
415
416
417void
418SBBreakpoint::SetThreadName (const char *thread_name)
419{
420    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
421    if (log)
422        log->Printf ("SBBreakpoint(%p)::SetThreadName (%s)", m_opaque_sp.get(), thread_name);
423
424    if (m_opaque_sp)
425    {
426        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
427        m_opaque_sp->GetOptions()->GetThreadSpec()->SetName (thread_name);
428    }
429}
430
431const char *
432SBBreakpoint::GetThreadName () const
433{
434    const char *name = NULL;
435    if (m_opaque_sp)
436    {
437        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
438        const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
439        if (thread_spec != NULL)
440            name = thread_spec->GetName();
441    }
442    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
443    if (log)
444        log->Printf ("SBBreakpoint(%p)::GetThreadName () => %s", m_opaque_sp.get(), name);
445
446    return name;
447}
448
449void
450SBBreakpoint::SetQueueName (const char *queue_name)
451{
452    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
453    if (log)
454        log->Printf ("SBBreakpoint(%p)::SetQueueName (%s)", m_opaque_sp.get(), queue_name);
455    if (m_opaque_sp)
456    {
457        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
458        m_opaque_sp->GetOptions()->GetThreadSpec()->SetQueueName (queue_name);
459    }
460}
461
462const char *
463SBBreakpoint::GetQueueName () const
464{
465    const char *name = NULL;
466    if (m_opaque_sp)
467    {
468        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
469        const ThreadSpec *thread_spec = m_opaque_sp->GetOptions()->GetThreadSpecNoCreate();
470        if (thread_spec)
471            name = thread_spec->GetQueueName();
472    }
473    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
474    if (log)
475        log->Printf ("SBBreakpoint(%p)::GetQueueName () => %s", m_opaque_sp.get(), name);
476
477    return name;
478}
479
480size_t
481SBBreakpoint::GetNumResolvedLocations() const
482{
483    size_t num_resolved = 0;
484    if (m_opaque_sp)
485    {
486        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
487        num_resolved = m_opaque_sp->GetNumResolvedLocations();
488    }
489    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
490    if (log)
491        log->Printf ("SBBreakpoint(%p)::GetNumResolvedLocations () => %" PRIu64, m_opaque_sp.get(), (uint64_t)num_resolved);
492    return num_resolved;
493}
494
495size_t
496SBBreakpoint::GetNumLocations() const
497{
498    size_t num_locs = 0;
499    if (m_opaque_sp)
500    {
501        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
502        num_locs = m_opaque_sp->GetNumLocations();
503    }
504    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
505    if (log)
506        log->Printf ("SBBreakpoint(%p)::GetNumLocations () => %" PRIu64, m_opaque_sp.get(), (uint64_t)num_locs);
507    return num_locs;
508}
509
510bool
511SBBreakpoint::GetDescription (SBStream &s)
512{
513    if (m_opaque_sp)
514    {
515        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
516        s.Printf("SBBreakpoint: id = %i, ", m_opaque_sp->GetID());
517        m_opaque_sp->GetResolverDescription (s.get());
518        m_opaque_sp->GetFilterDescription (s.get());
519        const size_t num_locations = m_opaque_sp->GetNumLocations ();
520        s.Printf(", locations = %" PRIu64, (uint64_t)num_locations);
521        return true;
522    }
523    s.Printf ("No value");
524    return false;
525}
526
527bool
528SBBreakpoint::PrivateBreakpointHitCallback
529(
530    void *baton,
531    StoppointCallbackContext *ctx,
532    lldb::user_id_t break_id,
533    lldb::user_id_t break_loc_id
534)
535{
536    ExecutionContext exe_ctx (ctx->exe_ctx_ref);
537    BreakpointSP bp_sp(exe_ctx.GetTargetRef().GetBreakpointList().FindBreakpointByID(break_id));
538    if (baton && bp_sp)
539    {
540        CallbackData *data = (CallbackData *)baton;
541        lldb_private::Breakpoint *bp = bp_sp.get();
542        if (bp && data->callback)
543        {
544            Process *process = exe_ctx.GetProcessPtr();
545            if (process)
546            {
547                SBProcess sb_process (process->shared_from_this());
548                SBThread sb_thread;
549                SBBreakpointLocation sb_location;
550                assert (bp_sp);
551                sb_location.SetLocation (bp_sp->FindLocationByID (break_loc_id));
552                Thread *thread = exe_ctx.GetThreadPtr();
553                if (thread)
554                    sb_thread.SetThread(thread->shared_from_this());
555
556                return data->callback (data->callback_baton,
557                                          sb_process,
558                                          sb_thread,
559                                          sb_location);
560            }
561        }
562    }
563    return true;    // Return true if we should stop at this breakpoint
564}
565
566void
567SBBreakpoint::SetCallback (BreakpointHitCallback callback, void *baton)
568{
569    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
570
571    if (log)
572        log->Printf ("SBBreakpoint(%p)::SetCallback (callback=%p, baton=%p)", m_opaque_sp.get(), callback, baton);
573
574    if (m_opaque_sp)
575    {
576        Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex());
577        BatonSP baton_sp(new SBBreakpointCallbackBaton (callback, baton));
578        m_opaque_sp->SetCallback (SBBreakpoint::PrivateBreakpointHitCallback, baton_sp, false);
579    }
580}
581
582
583lldb_private::Breakpoint *
584SBBreakpoint::operator->() const
585{
586    return m_opaque_sp.get();
587}
588
589lldb_private::Breakpoint *
590SBBreakpoint::get() const
591{
592    return m_opaque_sp.get();
593}
594
595lldb::BreakpointSP &
596SBBreakpoint::operator *()
597{
598    return m_opaque_sp;
599}
600
601const lldb::BreakpointSP &
602SBBreakpoint::operator *() const
603{
604    return m_opaque_sp;
605}
606
607bool
608SBBreakpoint::EventIsBreakpointEvent (const lldb::SBEvent &event)
609{
610    return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != NULL;
611
612}
613
614BreakpointEventType
615SBBreakpoint::GetBreakpointEventTypeFromEvent (const SBEvent& event)
616{
617    if (event.IsValid())
618        return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event.GetSP());
619    return eBreakpointEventTypeInvalidType;
620}
621
622SBBreakpoint
623SBBreakpoint::GetBreakpointFromEvent (const lldb::SBEvent& event)
624{
625    SBBreakpoint sb_breakpoint;
626    if (event.IsValid())
627        sb_breakpoint.m_opaque_sp = Breakpoint::BreakpointEventData::GetBreakpointFromEvent (event.GetSP());
628    return sb_breakpoint;
629}
630
631SBBreakpointLocation
632SBBreakpoint::GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx)
633{
634    SBBreakpointLocation sb_breakpoint_loc;
635    if (event.IsValid())
636        sb_breakpoint_loc.SetLocation (Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent (event.GetSP(), loc_idx));
637    return sb_breakpoint_loc;
638}
639
640uint32_t
641SBBreakpoint::GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event)
642{
643    uint32_t num_locations = 0;
644    if (event.IsValid())
645        num_locations = (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent (event.GetSP()));
646    return num_locations;
647}
648
649
650