1 //===-- BreakpointLocationList.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/BreakpointLocationList.h"
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Core/ModuleList.h"
18 #include "lldb/Target/Target.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 
23 BreakpointLocationList::BreakpointLocationList() :
24     m_locations(),
25     m_address_to_location (),
26     m_mutex (Mutex::eMutexTypeRecursive)
27 {
28 }
29 
30 BreakpointLocationList::~BreakpointLocationList()
31 {
32 }
33 
34 BreakpointLocationSP
35 BreakpointLocationList::Create (Breakpoint &bp, const Address &addr)
36 {
37     Mutex::Locker locker (m_mutex);
38     // The location ID is just the size of the location list + 1
39     lldb::break_id_t bp_loc_id = m_locations.size() + 1;
40     BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, bp, addr));
41     m_locations.push_back (bp_loc_sp);
42     m_address_to_location[addr] = bp_loc_sp;
43     return bp_loc_sp;
44 }
45 
46 bool
47 BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
48 {
49     BreakpointLocationSP bp = FindByID (break_id);
50     if (bp)
51     {
52         // Let the BreakpointLocation decide if it should stop here (could not have
53         // reached it's target hit count yet, or it could have a callback
54         // that decided it shouldn't stop (shared library loads/unloads).
55         return bp->ShouldStop (context);
56     }
57     // We should stop here since this BreakpointLocation isn't valid anymore or it
58     // doesn't exist.
59     return true;
60 }
61 
62 lldb::break_id_t
63 BreakpointLocationList::FindIDByAddress (const Address &addr)
64 {
65     BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
66     if (bp_loc_sp)
67     {
68         return bp_loc_sp->GetID();
69     }
70     return LLDB_INVALID_BREAK_ID;
71 }
72 
73 BreakpointLocationSP
74 BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
75 {
76     BreakpointLocationSP bp_loc_sp;
77     Mutex::Locker locker (m_mutex);
78     // We never remove a breakpoint locations, so the ID can be translated into
79     // the location index by subtracting 1
80     uint32_t idx = break_id - 1;
81     if (idx <= m_locations.size())
82     {
83         bp_loc_sp = m_locations[idx];
84     }
85     return bp_loc_sp;
86 }
87 
88 size_t
89 BreakpointLocationList::FindInModule (Module *module,
90                                       BreakpointLocationCollection& bp_loc_list)
91 {
92     Mutex::Locker locker (m_mutex);
93     const size_t orig_size = bp_loc_list.GetSize();
94     collection::iterator pos, end = m_locations.end();
95 
96     for (pos = m_locations.begin(); pos != end; ++pos)
97     {
98         BreakpointLocationSP break_loc = (*pos);
99         const Section *section = break_loc->GetAddress().GetSection();
100         if (section && section->GetModule() == module)
101         {
102             bp_loc_list.Add (break_loc);
103         }
104     }
105     return bp_loc_list.GetSize() - orig_size;
106 }
107 
108 const BreakpointLocationSP
109 BreakpointLocationList::FindByAddress (const Address &addr) const
110 {
111     Mutex::Locker locker (m_mutex);
112     BreakpointLocationSP bp_loc_sp;
113     if (!m_locations.empty())
114     {
115         addr_map::const_iterator pos = m_address_to_location.find (addr);
116         if (pos != m_address_to_location.end())
117             bp_loc_sp = pos->second;
118     }
119 
120     return bp_loc_sp;
121 }
122 
123 void
124 BreakpointLocationList::Dump (Stream *s) const
125 {
126     s->Printf("%p: ", this);
127     //s->Indent();
128     Mutex::Locker locker (m_mutex);
129     s->Printf("BreakpointLocationList with %zu BreakpointLocations:\n", m_locations.size());
130     s->IndentMore();
131     collection::const_iterator pos, end = m_locations.end();
132     for (pos = m_locations.begin(); pos != end; ++pos)
133         (*pos).get()->Dump(s);
134     s->IndentLess();
135 }
136 
137 
138 BreakpointLocationSP
139 BreakpointLocationList::GetByIndex (uint32_t i)
140 {
141     Mutex::Locker locker (m_mutex);
142     BreakpointLocationSP bp_loc_sp;
143     if (i < m_locations.size())
144         bp_loc_sp = m_locations[i];
145 
146     return bp_loc_sp;
147 }
148 
149 const BreakpointLocationSP
150 BreakpointLocationList::GetByIndex (uint32_t i) const
151 {
152     Mutex::Locker locker (m_mutex);
153     BreakpointLocationSP bp_loc_sp;
154     if (i < m_locations.size())
155         bp_loc_sp = m_locations[i];
156 
157     return bp_loc_sp;
158 }
159 
160 void
161 BreakpointLocationList::ClearAllBreakpointSites ()
162 {
163     Mutex::Locker locker (m_mutex);
164     collection::iterator pos, end = m_locations.end();
165     for (pos = m_locations.begin(); pos != end; ++pos)
166         (*pos)->ClearBreakpointSite();
167 }
168 
169 void
170 BreakpointLocationList::ResolveAllBreakpointSites ()
171 {
172     Mutex::Locker locker (m_mutex);
173     collection::iterator pos, end = m_locations.end();
174 
175     for (pos = m_locations.begin(); pos != end; ++pos)
176     {
177         if ((*pos)->IsEnabled())
178             (*pos)->ResolveBreakpointSite();
179     }
180 }
181 
182 uint32_t
183 BreakpointLocationList::GetHitCount () const
184 {
185     uint32_t hit_count = 0;
186     Mutex::Locker locker (m_mutex);
187     collection::const_iterator pos, end = m_locations.end();
188     for (pos = m_locations.begin(); pos != end; ++pos)
189         hit_count += (*pos)->GetHitCount();
190     return hit_count;
191 }
192 
193 size_t
194 BreakpointLocationList::GetNumResolvedLocations() const
195 {
196     Mutex::Locker locker (m_mutex);
197     size_t resolve_count = 0;
198     collection::const_iterator pos, end = m_locations.end();
199     for (pos = m_locations.begin(); pos != end; ++pos)
200     {
201         if ((*pos)->IsResolved())
202             ++resolve_count;
203     }
204     return resolve_count;
205 }
206 
207 void
208 BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
209 {
210     Mutex::Locker locker (m_mutex);
211     collection::iterator pos, end = m_locations.end();
212 
213     for (pos = m_locations.begin(); pos != end; ++pos)
214     {
215         s->Printf(" ");
216         (*pos)->GetDescription(s, level);
217     }
218 }
219 
220