1 //===-- BreakpointLocationCollection.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 
11 // C Includes
12 // C++ Includes
13 // Other libraries and framework includes
14 // Project includes
15 #include "lldb/Breakpoint/BreakpointLocationCollection.h"
16 #include "lldb/Core/ModuleList.h"
17 #include "lldb/Breakpoint/Breakpoint.h"
18 #include "lldb/Breakpoint/BreakpointLocation.h"
19 #include "lldb/Target/Thread.h"
20 #include "lldb/Target/ThreadSpec.h"
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 
25 //----------------------------------------------------------------------
26 // BreakpointLocationCollection constructor
27 //----------------------------------------------------------------------
28 BreakpointLocationCollection::BreakpointLocationCollection() :
29     m_break_loc_collection(),
30     m_collection_mutex()
31 {
32 }
33 
34 //----------------------------------------------------------------------
35 // Destructor
36 //----------------------------------------------------------------------
37 BreakpointLocationCollection::~BreakpointLocationCollection()
38 {
39 }
40 
41 void
42 BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc)
43 {
44     std::lock_guard<std::mutex> guard(m_collection_mutex);
45     BreakpointLocationSP old_bp_loc = FindByIDPair (bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
46     if (!old_bp_loc.get())
47         m_break_loc_collection.push_back(bp_loc);
48 }
49 
50 bool
51 BreakpointLocationCollection::Remove (lldb::break_id_t bp_id, lldb::break_id_t bp_loc_id)
52 {
53     std::lock_guard<std::mutex> guard(m_collection_mutex);
54     collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id);    // Predicate
55     if (pos != m_break_loc_collection.end())
56     {
57         m_break_loc_collection.erase(pos);
58         return true;
59     }
60     return false;
61 
62 }
63 
64 class BreakpointIDPairMatches
65 {
66 public:
67     BreakpointIDPairMatches (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) :
68         m_break_id(break_id),
69         m_break_loc_id (break_loc_id)
70     {
71     }
72 
73     bool operator() (const BreakpointLocationSP &bp_loc) const
74     {
75         return m_break_id == bp_loc->GetBreakpoint().GetID()
76             && m_break_loc_id == bp_loc->GetID();
77     }
78 
79 private:
80    const lldb::break_id_t m_break_id;
81    const lldb::break_id_t m_break_loc_id;
82 };
83 
84 BreakpointLocationCollection::collection::iterator
85 BreakpointLocationCollection::GetIDPairIterator (lldb::break_id_t break_id, lldb::break_id_t break_loc_id)
86 {
87     return std::find_if(m_break_loc_collection.begin(), m_break_loc_collection.end(),   // Search full range
88                         BreakpointIDPairMatches(break_id, break_loc_id));               // Predicate
89 }
90 
91 BreakpointLocationCollection::collection::const_iterator
92 BreakpointLocationCollection::GetIDPairConstIterator (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const
93 {
94     return std::find_if(m_break_loc_collection.begin(), m_break_loc_collection.end(),   // Search full range
95                         BreakpointIDPairMatches(break_id, break_loc_id));               // Predicate
96 }
97 
98 BreakpointLocationSP
99 BreakpointLocationCollection::FindByIDPair (lldb::break_id_t break_id, lldb::break_id_t break_loc_id)
100 {
101     BreakpointLocationSP stop_sp;
102     collection::iterator pos = GetIDPairIterator(break_id, break_loc_id);
103     if (pos != m_break_loc_collection.end())
104         stop_sp = *pos;
105 
106     return stop_sp;
107 }
108 
109 const BreakpointLocationSP
110 BreakpointLocationCollection::FindByIDPair (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const
111 {
112     BreakpointLocationSP stop_sp;
113     collection::const_iterator pos = GetIDPairConstIterator(break_id, break_loc_id);
114     if (pos != m_break_loc_collection.end())
115         stop_sp = *pos;
116 
117     return stop_sp;
118 }
119 
120 BreakpointLocationSP
121 BreakpointLocationCollection::GetByIndex (size_t i)
122 {
123     std::lock_guard<std::mutex> guard(m_collection_mutex);
124     BreakpointLocationSP stop_sp;
125     if (i < m_break_loc_collection.size())
126         stop_sp = m_break_loc_collection[i];
127 
128     return stop_sp;
129 }
130 
131 const BreakpointLocationSP
132 BreakpointLocationCollection::GetByIndex (size_t i) const
133 {
134     std::lock_guard<std::mutex> guard(m_collection_mutex);
135     BreakpointLocationSP stop_sp;
136     if (i < m_break_loc_collection.size())
137         stop_sp = m_break_loc_collection[i];
138 
139     return stop_sp;
140 }
141 
142 bool
143 BreakpointLocationCollection::ShouldStop (StoppointCallbackContext *context)
144 {
145     bool shouldStop = false;
146     size_t i = 0;
147     size_t prev_size = GetSize();
148     while (i < prev_size)
149     {
150         // ShouldStop can remove the breakpoint from the list
151         if (GetByIndex(i)->ShouldStop(context))
152             shouldStop = true;
153 
154         if (prev_size == GetSize())
155             i++;
156         prev_size = GetSize();
157     }
158     return shouldStop;
159 }
160 
161 bool
162 BreakpointLocationCollection::ValidForThisThread (Thread *thread)
163 {
164     std::lock_guard<std::mutex> guard(m_collection_mutex);
165     collection::iterator pos,
166         begin = m_break_loc_collection.begin(),
167         end = m_break_loc_collection.end();
168 
169     for (pos = begin; pos != end; ++pos)
170     {
171         if ((*pos)->ValidForThisThread (thread))
172             return true;
173     }
174     return false;
175 }
176 
177 bool
178 BreakpointLocationCollection::IsInternal () const
179 {
180     std::lock_guard<std::mutex> guard(m_collection_mutex);
181     collection::const_iterator pos,
182         begin = m_break_loc_collection.begin(),
183         end = m_break_loc_collection.end();
184 
185     bool is_internal = true;
186 
187     for (pos = begin; pos != end; ++pos)
188     {
189         if (!(*pos)->GetBreakpoint().IsInternal ())
190         {
191             is_internal = false;
192             break;
193         }
194     }
195     return is_internal;
196 }
197 
198 void
199 BreakpointLocationCollection::GetDescription (Stream *s, lldb::DescriptionLevel level)
200 {
201     std::lock_guard<std::mutex> guard(m_collection_mutex);
202     collection::iterator pos,
203         begin = m_break_loc_collection.begin(),
204         end = m_break_loc_collection.end();
205 
206     for (pos = begin; pos != end; ++pos)
207     {
208         if (pos != begin)
209             s->PutChar(' ');
210         (*pos)->GetDescription(s, level);
211     }
212 }
213 
214