1254721Semaste//===-- BreakpointList.cpp --------------------------------------*- C++ -*-===//
2254721Semaste//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste
9254721Semaste#include "lldb/Breakpoint/BreakpointList.h"
10254721Semaste
11254721Semaste#include "lldb/Target/Target.h"
12254721Semaste
13360784Sdim#include "llvm/Support/Errc.h"
14360784Sdim
15254721Semasteusing namespace lldb;
16254721Semasteusing namespace lldb_private;
17254721Semaste
18344779Sdimstatic void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) {
19344779Sdim  Target &target = bp->GetTarget();
20344779Sdim  if (target.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
21344779Sdim    target.BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
22344779Sdim                          new Breakpoint::BreakpointEventData(event, bp));
23344779Sdim}
24344779Sdim
25309124SdimBreakpointList::BreakpointList(bool is_internal)
26314564Sdim    : m_mutex(), m_breakpoints(), m_next_break_id(0),
27314564Sdim      m_is_internal(is_internal) {}
28254721Semaste
29314564SdimBreakpointList::~BreakpointList() {}
30254721Semaste
31314564Sdimbreak_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
32314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
33344779Sdim
34314564Sdim  // Internal breakpoint IDs are negative, normal ones are positive
35314564Sdim  bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);
36254721Semaste
37314564Sdim  m_breakpoints.push_back(bp_sp);
38344779Sdim
39344779Sdim  if (notify)
40344779Sdim    NotifyChange(bp_sp, eBreakpointEventTypeAdded);
41344779Sdim
42314564Sdim  return bp_sp->GetID();
43254721Semaste}
44254721Semaste
45314564Sdimbool BreakpointList::Remove(break_id_t break_id, bool notify) {
46314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
47344779Sdim
48344779Sdim  auto it = std::find_if(
49344779Sdim      m_breakpoints.begin(), m_breakpoints.end(),
50344779Sdim      [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
51344779Sdim
52344779Sdim  if (it == m_breakpoints.end())
53344779Sdim    return false;
54344779Sdim
55344779Sdim  if (notify)
56344779Sdim    NotifyChange(*it, eBreakpointEventTypeRemoved);
57344779Sdim
58344779Sdim  m_breakpoints.erase(it);
59344779Sdim
60344779Sdim  return true;
61254721Semaste}
62254721Semaste
63314564Sdimvoid BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {
64314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
65314564Sdim  for (const auto &bp_sp : m_breakpoints)
66314564Sdim    bp_sp->RemoveInvalidLocations(arch);
67258884Semaste}
68258884Semaste
69314564Sdimvoid BreakpointList::SetEnabledAll(bool enabled) {
70314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
71314564Sdim  for (const auto &bp_sp : m_breakpoints)
72314564Sdim    bp_sp->SetEnabled(enabled);
73254721Semaste}
74254721Semaste
75327952Sdimvoid BreakpointList::SetEnabledAllowed(bool enabled) {
76327952Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
77327952Sdim  for (const auto &bp_sp : m_breakpoints)
78327952Sdim    if (bp_sp->AllowDisable())
79327952Sdim      bp_sp->SetEnabled(enabled);
80327952Sdim}
81327952Sdim
82314564Sdimvoid BreakpointList::RemoveAll(bool notify) {
83314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
84314564Sdim  ClearAllBreakpointSites();
85254721Semaste
86314564Sdim  if (notify) {
87344779Sdim    for (const auto &bp_sp : m_breakpoints)
88344779Sdim      NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
89314564Sdim  }
90344779Sdim
91344779Sdim  m_breakpoints.clear();
92254721Semaste}
93254721Semaste
94327952Sdimvoid BreakpointList::RemoveAllowed(bool notify) {
95327952Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
96341825Sdim
97344779Sdim  for (const auto &bp_sp : m_breakpoints) {
98344779Sdim    if (bp_sp->AllowDelete())
99344779Sdim      bp_sp->ClearAllBreakpointSites();
100344779Sdim    if (notify)
101344779Sdim      NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
102327952Sdim  }
103344779Sdim
104344779Sdim  m_breakpoints.erase(
105344779Sdim      std::remove_if(m_breakpoints.begin(), m_breakpoints.end(),
106344779Sdim                     [&](const BreakpointSP &bp) { return bp->AllowDelete(); }),
107344779Sdim      m_breakpoints.end());
108327952Sdim}
109327952Sdim
110254721SemasteBreakpointList::bp_collection::iterator
111314564SdimBreakpointList::GetBreakpointIDIterator(break_id_t break_id) {
112344779Sdim  return std::find_if(
113344779Sdim      m_breakpoints.begin(), m_breakpoints.end(),
114344779Sdim      [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
115254721Semaste}
116254721Semaste
117254721SemasteBreakpointList::bp_collection::const_iterator
118314564SdimBreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {
119344779Sdim  return std::find_if(
120344779Sdim      m_breakpoints.begin(), m_breakpoints.end(),
121344779Sdim      [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
122254721Semaste}
123254721Semaste
124344779SdimBreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const {
125314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
126254721Semaste
127344779Sdim  auto it = GetBreakpointIDConstIterator(break_id);
128344779Sdim  if (it != m_breakpoints.end())
129344779Sdim    return *it;
130344779Sdim  return {};
131254721Semaste}
132254721Semaste
133360784Sdimllvm::Expected<std::vector<lldb::BreakpointSP>>
134360784SdimBreakpointList::FindBreakpointsByName(const char *name) {
135314564Sdim  if (!name)
136360784Sdim    return llvm::createStringError(llvm::errc::invalid_argument,
137360784Sdim                                   "FindBreakpointsByName requires a name");
138254721Semaste
139360784Sdim  Status error;
140314564Sdim  if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))
141360784Sdim    return error.ToError();
142254721Semaste
143360784Sdim  std::vector<lldb::BreakpointSP> matching_bps;
144314564Sdim  for (BreakpointSP bkpt_sp : Breakpoints()) {
145314564Sdim    if (bkpt_sp->MatchesName(name)) {
146360784Sdim      matching_bps.push_back(bkpt_sp);
147254721Semaste    }
148314564Sdim  }
149344779Sdim
150360784Sdim  return matching_bps;
151254721Semaste}
152254721Semaste
153314564Sdimvoid BreakpointList::Dump(Stream *s) const {
154314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
155314564Sdim  s->Printf("%p: ", static_cast<const void *>(this));
156314564Sdim  s->Indent();
157314564Sdim  s->Printf("BreakpointList with %u Breakpoints:\n",
158314564Sdim            (uint32_t)m_breakpoints.size());
159314564Sdim  s->IndentMore();
160314564Sdim  for (const auto &bp_sp : m_breakpoints)
161314564Sdim    bp_sp->Dump(s);
162314564Sdim  s->IndentLess();
163254721Semaste}
164254721Semaste
165344779SdimBreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
166314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
167344779Sdim  if (i < m_breakpoints.size())
168344779Sdim    return m_breakpoints[i];
169344779Sdim  return {};
170314564Sdim}
171254721Semaste
172314564Sdimvoid BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,
173314564Sdim                                       bool delete_locations) {
174314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
175314564Sdim  for (const auto &bp_sp : m_breakpoints)
176314564Sdim    bp_sp->ModulesChanged(module_list, added, delete_locations);
177314564Sdim}
178254721Semaste
179314564Sdimvoid BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(
180314564Sdim    ModuleSP old_module_sp, ModuleSP new_module_sp) {
181314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
182314564Sdim  for (const auto &bp_sp : m_breakpoints)
183314564Sdim    bp_sp->ModuleReplaced(old_module_sp, new_module_sp);
184254721Semaste}
185254721Semaste
186314564Sdimvoid BreakpointList::ClearAllBreakpointSites() {
187314564Sdim  std::lock_guard<std::recursive_mutex> guard(m_mutex);
188314564Sdim  for (const auto &bp_sp : m_breakpoints)
189314564Sdim    bp_sp->ClearAllBreakpointSites();
190254721Semaste}
191254721Semaste
192314564Sdimvoid BreakpointList::GetListMutex(
193314564Sdim    std::unique_lock<std::recursive_mutex> &lock) {
194314564Sdim  lock = std::unique_lock<std::recursive_mutex>(m_mutex);
195254721Semaste}
196