BreakpointList.cpp revision 341825
1254721Semaste//===-- BreakpointList.cpp --------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Breakpoint/BreakpointList.h"
11254721Semaste
12254721Semaste// C Includes
13254721Semaste// C++ Includes
14254721Semaste// Other libraries and framework includes
15254721Semaste// Project includes
16254721Semaste#include "lldb/Target/Target.h"
17254721Semaste
18254721Semasteusing namespace lldb;
19254721Semasteusing namespace lldb_private;
20254721Semaste
21309124SdimBreakpointList::BreakpointList(bool is_internal)
22314564Sdim    : m_mutex(), m_breakpoints(), m_next_break_id(0),
23314564Sdim      m_is_internal(is_internal) {}
24254721Semaste
25314564SdimBreakpointList::~BreakpointList() {}
26254721Semaste
27314564Sdimbreak_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
28314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
29314564Sdim  // Internal breakpoint IDs are negative, normal ones are positive
30314564Sdim  bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);
31254721Semaste
32314564Sdim  m_breakpoints.push_back(bp_sp);
33314564Sdim  if (notify) {
34314564Sdim    if (bp_sp->GetTarget().EventTypeHasListeners(
35314564Sdim            Target::eBroadcastBitBreakpointChanged))
36314564Sdim      bp_sp->GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
37314564Sdim                                        new Breakpoint::BreakpointEventData(
38314564Sdim                                            eBreakpointEventTypeAdded, bp_sp));
39314564Sdim  }
40314564Sdim  return bp_sp->GetID();
41254721Semaste}
42254721Semaste
43314564Sdimbool BreakpointList::Remove(break_id_t break_id, bool notify) {
44314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
45314564Sdim  bp_collection::iterator pos = GetBreakpointIDIterator(break_id); // Predicate
46314564Sdim  if (pos != m_breakpoints.end()) {
47314564Sdim    BreakpointSP bp_sp(*pos);
48314564Sdim    m_breakpoints.erase(pos);
49314564Sdim    if (notify) {
50314564Sdim      if (bp_sp->GetTarget().EventTypeHasListeners(
51314564Sdim              Target::eBroadcastBitBreakpointChanged))
52314564Sdim        bp_sp->GetTarget().BroadcastEvent(
53314564Sdim            Target::eBroadcastBitBreakpointChanged,
54314564Sdim            new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
55314564Sdim                                                bp_sp));
56254721Semaste    }
57314564Sdim    return true;
58314564Sdim  }
59314564Sdim  return false;
60254721Semaste}
61254721Semaste
62314564Sdimvoid BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {
63314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
64314564Sdim  for (const auto &bp_sp : m_breakpoints)
65314564Sdim    bp_sp->RemoveInvalidLocations(arch);
66258884Semaste}
67258884Semaste
68314564Sdimvoid BreakpointList::SetEnabledAll(bool enabled) {
69314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
70314564Sdim  for (const auto &bp_sp : m_breakpoints)
71314564Sdim    bp_sp->SetEnabled(enabled);
72254721Semaste}
73254721Semaste
74327952Sdimvoid BreakpointList::SetEnabledAllowed(bool enabled) {
75327952Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
76327952Sdim  for (const auto &bp_sp : m_breakpoints)
77327952Sdim    if (bp_sp->AllowDisable())
78327952Sdim      bp_sp->SetEnabled(enabled);
79327952Sdim}
80327952Sdim
81314564Sdimvoid BreakpointList::RemoveAll(bool notify) {
82314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
83314564Sdim  ClearAllBreakpointSites();
84254721Semaste
85314564Sdim  if (notify) {
86314564Sdim    bp_collection::iterator pos, end = m_breakpoints.end();
87314564Sdim    for (pos = m_breakpoints.begin(); pos != end; ++pos) {
88314564Sdim      if ((*pos)->GetTarget().EventTypeHasListeners(
89314564Sdim              Target::eBroadcastBitBreakpointChanged)) {
90314564Sdim        (*pos)->GetTarget().BroadcastEvent(
91314564Sdim            Target::eBroadcastBitBreakpointChanged,
92314564Sdim            new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
93314564Sdim                                                *pos));
94314564Sdim      }
95254721Semaste    }
96314564Sdim  }
97314564Sdim  m_breakpoints.erase(m_breakpoints.begin(), m_breakpoints.end());
98254721Semaste}
99254721Semaste
100327952Sdimvoid BreakpointList::RemoveAllowed(bool notify) {
101327952Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
102341825Sdim
103327952Sdim  bp_collection::iterator pos, end = m_breakpoints.end();
104327952Sdim  if (notify) {
105327952Sdim    for (pos = m_breakpoints.begin(); pos != end; ++pos) {
106327952Sdim      if(!(*pos)->AllowDelete())
107327952Sdim        continue;
108327952Sdim      if ((*pos)->GetTarget().EventTypeHasListeners(
109327952Sdim              Target::eBroadcastBitBreakpointChanged)) {
110327952Sdim        (*pos)->GetTarget().BroadcastEvent(
111327952Sdim            Target::eBroadcastBitBreakpointChanged,
112327952Sdim            new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
113327952Sdim                                                *pos));
114327952Sdim      }
115327952Sdim    }
116327952Sdim  }
117327952Sdim  pos = m_breakpoints.begin();
118327952Sdim  while ( pos != end) {
119341825Sdim    auto bp = *pos;
120341825Sdim    if (bp->AllowDelete()) {
121341825Sdim      bp->ClearAllBreakpointSites();
122341825Sdim      pos = m_breakpoints.erase(pos);
123341825Sdim    } else
124341825Sdim      pos++;
125327952Sdim  }
126327952Sdim}
127327952Sdim
128314564Sdimclass BreakpointIDMatches {
129254721Semastepublic:
130314564Sdim  BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {}
131254721Semaste
132314564Sdim  bool operator()(const BreakpointSP &bp) const {
133314564Sdim    return m_break_id == bp->GetID();
134314564Sdim  }
135254721Semaste
136254721Semasteprivate:
137314564Sdim  const break_id_t m_break_id;
138254721Semaste};
139254721Semaste
140254721SemasteBreakpointList::bp_collection::iterator
141314564SdimBreakpointList::GetBreakpointIDIterator(break_id_t break_id) {
142314564Sdim  return std::find_if(m_breakpoints.begin(),
143314564Sdim                      m_breakpoints.end(),            // Search full range
144314564Sdim                      BreakpointIDMatches(break_id)); // Predicate
145254721Semaste}
146254721Semaste
147254721SemasteBreakpointList::bp_collection::const_iterator
148314564SdimBreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {
149314564Sdim  return std::find_if(m_breakpoints.begin(),
150314564Sdim                      m_breakpoints.end(),            // Search full range
151314564Sdim                      BreakpointIDMatches(break_id)); // Predicate
152254721Semaste}
153254721Semaste
154314564SdimBreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) {
155314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
156314564Sdim  BreakpointSP stop_sp;
157314564Sdim  bp_collection::iterator pos = GetBreakpointIDIterator(break_id);
158314564Sdim  if (pos != m_breakpoints.end())
159314564Sdim    stop_sp = *pos;
160254721Semaste
161314564Sdim  return stop_sp;
162254721Semaste}
163254721Semaste
164254721Semasteconst BreakpointSP
165314564SdimBreakpointList::FindBreakpointByID(break_id_t break_id) const {
166314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
167314564Sdim  BreakpointSP stop_sp;
168314564Sdim  bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id);
169314564Sdim  if (pos != m_breakpoints.end())
170314564Sdim    stop_sp = *pos;
171254721Semaste
172314564Sdim  return stop_sp;
173254721Semaste}
174254721Semaste
175314564Sdimbool BreakpointList::FindBreakpointsByName(const char *name,
176314564Sdim                                           BreakpointList &matching_bps) {
177321369Sdim  Status error;
178314564Sdim  if (!name)
179314564Sdim    return false;
180254721Semaste
181314564Sdim  if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))
182314564Sdim    return false;
183254721Semaste
184314564Sdim  for (BreakpointSP bkpt_sp : Breakpoints()) {
185314564Sdim    if (bkpt_sp->MatchesName(name)) {
186314564Sdim      matching_bps.Add(bkpt_sp, false);
187254721Semaste    }
188314564Sdim  }
189314564Sdim  return true;
190254721Semaste}
191254721Semaste
192314564Sdimvoid BreakpointList::Dump(Stream *s) const {
193314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
194314564Sdim  s->Printf("%p: ", static_cast<const void *>(this));
195314564Sdim  s->Indent();
196314564Sdim  s->Printf("BreakpointList with %u Breakpoints:\n",
197314564Sdim            (uint32_t)m_breakpoints.size());
198314564Sdim  s->IndentMore();
199314564Sdim  for (const auto &bp_sp : m_breakpoints)
200314564Sdim    bp_sp->Dump(s);
201314564Sdim  s->IndentLess();
202254721Semaste}
203254721Semaste
204314564SdimBreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) {
205314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
206314564Sdim  BreakpointSP stop_sp;
207314564Sdim  bp_collection::iterator end = m_breakpoints.end();
208314564Sdim  bp_collection::iterator pos;
209314564Sdim  size_t curr_i = 0;
210314564Sdim  for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) {
211314564Sdim    if (curr_i == i)
212314564Sdim      stop_sp = *pos;
213314564Sdim  }
214314564Sdim  return stop_sp;
215314564Sdim}
216254721Semaste
217314564Sdimconst BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
218314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
219314564Sdim  BreakpointSP stop_sp;
220314564Sdim  bp_collection::const_iterator end = m_breakpoints.end();
221314564Sdim  bp_collection::const_iterator pos;
222314564Sdim  size_t curr_i = 0;
223314564Sdim  for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) {
224314564Sdim    if (curr_i == i)
225314564Sdim      stop_sp = *pos;
226314564Sdim  }
227314564Sdim  return stop_sp;
228254721Semaste}
229254721Semaste
230314564Sdimvoid BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,
231314564Sdim                                       bool delete_locations) {
232314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
233314564Sdim  for (const auto &bp_sp : m_breakpoints)
234314564Sdim    bp_sp->ModulesChanged(module_list, added, delete_locations);
235314564Sdim}
236254721Semaste
237314564Sdimvoid BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(
238314564Sdim    ModuleSP old_module_sp, ModuleSP new_module_sp) {
239314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
240314564Sdim  for (const auto &bp_sp : m_breakpoints)
241314564Sdim    bp_sp->ModuleReplaced(old_module_sp, new_module_sp);
242254721Semaste}
243254721Semaste
244314564Sdimvoid BreakpointList::ClearAllBreakpointSites() {
245314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
246314564Sdim  for (const auto &bp_sp : m_breakpoints)
247314564Sdim    bp_sp->ClearAllBreakpointSites();
248254721Semaste}
249254721Semaste
250314564Sdimvoid BreakpointList::GetListMutex(
251314564Sdim    std::unique_lock<std::recursive_mutex> &lock) {
252314564Sdim  lock = std::unique_lock<std::recursive_mutex>(m_mutex);
253254721Semaste}
254