]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Breakpoint/BreakpointLocationList.cpp
Merge clang trunk r338150 (just before the 7.0.0 branch point), and
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Breakpoint / BreakpointLocationList.cpp
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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Breakpoint/BreakpointLocationList.h"
15
16 #include "lldb/Breakpoint/Breakpoint.h"
17 #include "lldb/Breakpoint/BreakpointLocation.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/Section.h"
20 #include "lldb/Target/SectionLoadList.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/ArchSpec.h"
23
24 using namespace lldb;
25 using namespace lldb_private;
26
27 BreakpointLocationList::BreakpointLocationList(Breakpoint &owner)
28     : m_owner(owner), m_locations(), m_address_to_location(), m_mutex(),
29       m_next_id(0), m_new_location_recorder(nullptr) {}
30
31 BreakpointLocationList::~BreakpointLocationList() = default;
32
33 BreakpointLocationSP
34 BreakpointLocationList::Create(const Address &addr,
35                                bool resolve_indirect_symbols) {
36   std::lock_guard<std::recursive_mutex> guard(m_mutex);
37   // The location ID is just the size of the location list + 1
38   lldb::break_id_t bp_loc_id = ++m_next_id;
39   BreakpointLocationSP bp_loc_sp(
40       new BreakpointLocation(bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID,
41                              m_owner.IsHardware(), resolve_indirect_symbols));
42   m_locations.push_back(bp_loc_sp);
43   m_address_to_location[addr] = bp_loc_sp;
44   return bp_loc_sp;
45 }
46
47 bool BreakpointLocationList::ShouldStop(StoppointCallbackContext *context,
48                                         lldb::break_id_t break_id) {
49   BreakpointLocationSP bp = FindByID(break_id);
50   if (bp) {
51     // Let the BreakpointLocation decide if it should stop here (could not have
52     // reached it's target hit count yet, or it could have a callback that
53     // decided it shouldn't stop (shared library loads/unloads).
54     return bp->ShouldStop(context);
55   }
56   // We should stop here since this BreakpointLocation isn't valid anymore or
57   // it doesn't exist.
58   return true;
59 }
60
61 lldb::break_id_t BreakpointLocationList::FindIDByAddress(const Address &addr) {
62   BreakpointLocationSP bp_loc_sp = FindByAddress(addr);
63   if (bp_loc_sp) {
64     return bp_loc_sp->GetID();
65   }
66   return LLDB_INVALID_BREAK_ID;
67 }
68
69 static bool Compare(BreakpointLocationSP lhs, lldb::break_id_t val) {
70   return lhs->GetID() < val;
71 }
72
73 BreakpointLocationSP
74 BreakpointLocationList::FindByID(lldb::break_id_t break_id) const {
75   std::lock_guard<std::recursive_mutex> guard(m_mutex);
76   collection::const_iterator end = m_locations.end();
77   collection::const_iterator pos =
78       std::lower_bound(m_locations.begin(), end, break_id, Compare);
79   if (pos != end && (*pos)->GetID() == break_id)
80     return *(pos);
81   else
82     return BreakpointLocationSP();
83 }
84
85 size_t BreakpointLocationList::FindInModule(
86     Module *module, BreakpointLocationCollection &bp_loc_list) {
87   std::lock_guard<std::recursive_mutex> guard(m_mutex);
88   const size_t orig_size = bp_loc_list.GetSize();
89   collection::iterator pos, end = m_locations.end();
90
91   for (pos = m_locations.begin(); pos != end; ++pos) {
92     BreakpointLocationSP break_loc = (*pos);
93     SectionSP section_sp(break_loc->GetAddress().GetSection());
94     if (section_sp && section_sp->GetModule().get() == module) {
95       bp_loc_list.Add(break_loc);
96     }
97   }
98   return bp_loc_list.GetSize() - orig_size;
99 }
100
101 const BreakpointLocationSP
102 BreakpointLocationList::FindByAddress(const Address &addr) const {
103   std::lock_guard<std::recursive_mutex> guard(m_mutex);
104   BreakpointLocationSP bp_loc_sp;
105   if (!m_locations.empty()) {
106     Address so_addr;
107
108     if (addr.IsSectionOffset()) {
109       so_addr = addr;
110     } else {
111       // Try and resolve as a load address if possible.
112       m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress(
113           addr.GetOffset(), so_addr);
114       if (!so_addr.IsValid()) {
115         // The address didn't resolve, so just set to passed in addr.
116         so_addr = addr;
117       }
118     }
119
120     addr_map::const_iterator pos = m_address_to_location.find(so_addr);
121     if (pos != m_address_to_location.end())
122       bp_loc_sp = pos->second;
123   }
124
125   return bp_loc_sp;
126 }
127
128 void BreakpointLocationList::Dump(Stream *s) const {
129   s->Printf("%p: ", static_cast<const void *>(this));
130   // s->Indent();
131   std::lock_guard<std::recursive_mutex> guard(m_mutex);
132   s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n",
133             (uint64_t)m_locations.size());
134   s->IndentMore();
135   collection::const_iterator pos, end = m_locations.end();
136   for (pos = m_locations.begin(); pos != end; ++pos)
137     (*pos).get()->Dump(s);
138   s->IndentLess();
139 }
140
141 BreakpointLocationSP BreakpointLocationList::GetByIndex(size_t i) {
142   std::lock_guard<std::recursive_mutex> guard(m_mutex);
143   BreakpointLocationSP bp_loc_sp;
144   if (i < m_locations.size())
145     bp_loc_sp = m_locations[i];
146
147   return bp_loc_sp;
148 }
149
150 const BreakpointLocationSP BreakpointLocationList::GetByIndex(size_t i) const {
151   std::lock_guard<std::recursive_mutex> guard(m_mutex);
152   BreakpointLocationSP bp_loc_sp;
153   if (i < m_locations.size())
154     bp_loc_sp = m_locations[i];
155
156   return bp_loc_sp;
157 }
158
159 void BreakpointLocationList::ClearAllBreakpointSites() {
160   std::lock_guard<std::recursive_mutex> guard(m_mutex);
161   collection::iterator pos, end = m_locations.end();
162   for (pos = m_locations.begin(); pos != end; ++pos)
163     (*pos)->ClearBreakpointSite();
164 }
165
166 void BreakpointLocationList::ResolveAllBreakpointSites() {
167   std::lock_guard<std::recursive_mutex> guard(m_mutex);
168   collection::iterator pos, end = m_locations.end();
169
170   for (pos = m_locations.begin(); pos != end; ++pos) {
171     if ((*pos)->IsEnabled())
172       (*pos)->ResolveBreakpointSite();
173   }
174 }
175
176 uint32_t BreakpointLocationList::GetHitCount() const {
177   uint32_t hit_count = 0;
178   std::lock_guard<std::recursive_mutex> guard(m_mutex);
179   collection::const_iterator pos, end = m_locations.end();
180   for (pos = m_locations.begin(); pos != end; ++pos)
181     hit_count += (*pos)->GetHitCount();
182   return hit_count;
183 }
184
185 size_t BreakpointLocationList::GetNumResolvedLocations() const {
186   std::lock_guard<std::recursive_mutex> guard(m_mutex);
187   size_t resolve_count = 0;
188   collection::const_iterator pos, end = m_locations.end();
189   for (pos = m_locations.begin(); pos != end; ++pos) {
190     if ((*pos)->IsResolved())
191       ++resolve_count;
192   }
193   return resolve_count;
194 }
195
196 void BreakpointLocationList::GetDescription(Stream *s,
197                                             lldb::DescriptionLevel level) {
198   std::lock_guard<std::recursive_mutex> guard(m_mutex);
199   collection::iterator pos, end = m_locations.end();
200
201   for (pos = m_locations.begin(); pos != end; ++pos) {
202     s->Printf(" ");
203     (*pos)->GetDescription(s, level);
204   }
205 }
206
207 BreakpointLocationSP BreakpointLocationList::AddLocation(
208     const Address &addr, bool resolve_indirect_symbols, bool *new_location) {
209   std::lock_guard<std::recursive_mutex> guard(m_mutex);
210
211   if (new_location)
212     *new_location = false;
213   BreakpointLocationSP bp_loc_sp(FindByAddress(addr));
214   if (!bp_loc_sp) {
215     bp_loc_sp = Create(addr, resolve_indirect_symbols);
216     if (bp_loc_sp) {
217       bp_loc_sp->ResolveBreakpointSite();
218
219       if (new_location)
220         *new_location = true;
221       if (m_new_location_recorder) {
222         m_new_location_recorder->Add(bp_loc_sp);
223       }
224     }
225   }
226   return bp_loc_sp;
227 }
228
229 void BreakpointLocationList::SwapLocation(
230     BreakpointLocationSP to_location_sp,
231     BreakpointLocationSP from_location_sp) {
232   if (!from_location_sp || !to_location_sp)
233     return;
234
235   m_address_to_location.erase(to_location_sp->GetAddress());
236   to_location_sp->SwapLocation(from_location_sp);
237   RemoveLocation(from_location_sp);
238   m_address_to_location[to_location_sp->GetAddress()] = to_location_sp;
239   to_location_sp->ResolveBreakpointSite();
240 }
241
242 bool BreakpointLocationList::RemoveLocation(
243     const lldb::BreakpointLocationSP &bp_loc_sp) {
244   if (bp_loc_sp) {
245     std::lock_guard<std::recursive_mutex> guard(m_mutex);
246
247     m_address_to_location.erase(bp_loc_sp->GetAddress());
248
249     size_t num_locations = m_locations.size();
250     for (size_t idx = 0; idx < num_locations; idx++) {
251       if (m_locations[idx].get() == bp_loc_sp.get()) {
252         RemoveLocationByIndex(idx);
253         return true;
254       }
255     }
256   }
257   return false;
258 }
259
260 void BreakpointLocationList::RemoveLocationByIndex(size_t idx) {
261   assert (idx < m_locations.size());
262   m_address_to_location.erase(m_locations[idx]->GetAddress());
263   m_locations.erase(m_locations.begin() + idx);
264 }
265
266 void BreakpointLocationList::RemoveInvalidLocations(const ArchSpec &arch) {
267   std::lock_guard<std::recursive_mutex> guard(m_mutex);
268   size_t idx = 0;
269   // Don't cache m_location.size() as it will change since we might remove
270   // locations from our vector...
271   while (idx < m_locations.size()) {
272     BreakpointLocation *bp_loc = m_locations[idx].get();
273     if (bp_loc->GetAddress().SectionWasDeleted()) {
274       // Section was deleted which means this breakpoint comes from a module
275       // that is no longer valid, so we should remove it.
276       RemoveLocationByIndex(idx);
277       continue;
278     }
279     if (arch.IsValid()) {
280       ModuleSP module_sp(bp_loc->GetAddress().GetModule());
281       if (module_sp) {
282         if (!arch.IsCompatibleMatch(module_sp->GetArchitecture())) {
283           // The breakpoint was in a module whose architecture is no longer
284           // compatible with "arch", so we need to remove it
285           RemoveLocationByIndex(idx);
286           continue;
287         }
288       }
289     }
290     // Only increment the index if we didn't remove the locations at index
291     // "idx"
292     ++idx;
293   }
294 }
295
296 void BreakpointLocationList::StartRecordingNewLocations(
297     BreakpointLocationCollection &new_locations) {
298   std::lock_guard<std::recursive_mutex> guard(m_mutex);
299   assert(m_new_location_recorder == nullptr);
300   m_new_location_recorder = &new_locations;
301 }
302
303 void BreakpointLocationList::StopRecordingNewLocations() {
304   std::lock_guard<std::recursive_mutex> guard(m_mutex);
305   m_new_location_recorder = nullptr;
306 }
307
308 void BreakpointLocationList::Compact() {
309   lldb::break_id_t highest_id = 0;
310
311   for (BreakpointLocationSP loc_sp : m_locations) {
312     lldb::break_id_t cur_id = loc_sp->GetID();
313     if (cur_id > highest_id)
314       highest_id = cur_id;
315   }
316   m_next_id = highest_id;
317 }