1dda28197Spatrick //===-- BreakpointList.cpp ------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Breakpoint/BreakpointList.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/Target/Target.h"
12061da546Spatrick
13061da546Spatrick #include "llvm/Support/Errc.h"
14061da546Spatrick
15061da546Spatrick using namespace lldb;
16061da546Spatrick using namespace lldb_private;
17061da546Spatrick
NotifyChange(const BreakpointSP & bp,BreakpointEventType event)18061da546Spatrick static void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) {
19061da546Spatrick Target &target = bp->GetTarget();
20061da546Spatrick if (target.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
21061da546Spatrick target.BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
22061da546Spatrick new Breakpoint::BreakpointEventData(event, bp));
23061da546Spatrick }
24061da546Spatrick
BreakpointList(bool is_internal)25061da546Spatrick BreakpointList::BreakpointList(bool is_internal)
26*f6aab3d8Srobert : m_next_break_id(0), m_is_internal(is_internal) {}
27061da546Spatrick
28be691f3bSpatrick BreakpointList::~BreakpointList() = default;
29061da546Spatrick
Add(BreakpointSP & bp_sp,bool notify)30061da546Spatrick break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
31061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
32061da546Spatrick
33061da546Spatrick // Internal breakpoint IDs are negative, normal ones are positive
34061da546Spatrick bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);
35061da546Spatrick
36061da546Spatrick m_breakpoints.push_back(bp_sp);
37061da546Spatrick
38061da546Spatrick if (notify)
39061da546Spatrick NotifyChange(bp_sp, eBreakpointEventTypeAdded);
40061da546Spatrick
41061da546Spatrick return bp_sp->GetID();
42061da546Spatrick }
43061da546Spatrick
Remove(break_id_t break_id,bool notify)44061da546Spatrick bool BreakpointList::Remove(break_id_t break_id, bool notify) {
45061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
46061da546Spatrick
47061da546Spatrick auto it = std::find_if(
48061da546Spatrick m_breakpoints.begin(), m_breakpoints.end(),
49061da546Spatrick [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
50061da546Spatrick
51061da546Spatrick if (it == m_breakpoints.end())
52061da546Spatrick return false;
53061da546Spatrick
54061da546Spatrick if (notify)
55061da546Spatrick NotifyChange(*it, eBreakpointEventTypeRemoved);
56061da546Spatrick
57061da546Spatrick m_breakpoints.erase(it);
58061da546Spatrick
59061da546Spatrick return true;
60061da546Spatrick }
61061da546Spatrick
RemoveInvalidLocations(const ArchSpec & arch)62061da546Spatrick void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {
63061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
64061da546Spatrick for (const auto &bp_sp : m_breakpoints)
65061da546Spatrick bp_sp->RemoveInvalidLocations(arch);
66061da546Spatrick }
67061da546Spatrick
SetEnabledAll(bool enabled)68061da546Spatrick void BreakpointList::SetEnabledAll(bool enabled) {
69061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
70061da546Spatrick for (const auto &bp_sp : m_breakpoints)
71061da546Spatrick bp_sp->SetEnabled(enabled);
72061da546Spatrick }
73061da546Spatrick
SetEnabledAllowed(bool enabled)74061da546Spatrick void BreakpointList::SetEnabledAllowed(bool enabled) {
75061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
76061da546Spatrick for (const auto &bp_sp : m_breakpoints)
77061da546Spatrick if (bp_sp->AllowDisable())
78061da546Spatrick bp_sp->SetEnabled(enabled);
79061da546Spatrick }
80061da546Spatrick
RemoveAll(bool notify)81061da546Spatrick void BreakpointList::RemoveAll(bool notify) {
82061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
83061da546Spatrick ClearAllBreakpointSites();
84061da546Spatrick
85061da546Spatrick if (notify) {
86061da546Spatrick for (const auto &bp_sp : m_breakpoints)
87061da546Spatrick NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
88061da546Spatrick }
89061da546Spatrick
90061da546Spatrick m_breakpoints.clear();
91061da546Spatrick }
92061da546Spatrick
RemoveAllowed(bool notify)93061da546Spatrick void BreakpointList::RemoveAllowed(bool notify) {
94061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
95061da546Spatrick
96061da546Spatrick for (const auto &bp_sp : m_breakpoints) {
97061da546Spatrick if (bp_sp->AllowDelete())
98061da546Spatrick bp_sp->ClearAllBreakpointSites();
99061da546Spatrick if (notify)
100061da546Spatrick NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
101061da546Spatrick }
102061da546Spatrick
103*f6aab3d8Srobert llvm::erase_if(m_breakpoints,
104*f6aab3d8Srobert [&](const BreakpointSP &bp) { return bp->AllowDelete(); });
105061da546Spatrick }
106061da546Spatrick
107061da546Spatrick BreakpointList::bp_collection::iterator
GetBreakpointIDIterator(break_id_t break_id)108061da546Spatrick BreakpointList::GetBreakpointIDIterator(break_id_t break_id) {
109061da546Spatrick return std::find_if(
110061da546Spatrick m_breakpoints.begin(), m_breakpoints.end(),
111061da546Spatrick [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
112061da546Spatrick }
113061da546Spatrick
114061da546Spatrick BreakpointList::bp_collection::const_iterator
GetBreakpointIDConstIterator(break_id_t break_id) const115061da546Spatrick BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {
116061da546Spatrick return std::find_if(
117061da546Spatrick m_breakpoints.begin(), m_breakpoints.end(),
118061da546Spatrick [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
119061da546Spatrick }
120061da546Spatrick
FindBreakpointByID(break_id_t break_id) const121061da546Spatrick BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const {
122061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
123061da546Spatrick
124061da546Spatrick auto it = GetBreakpointIDConstIterator(break_id);
125061da546Spatrick if (it != m_breakpoints.end())
126061da546Spatrick return *it;
127061da546Spatrick return {};
128061da546Spatrick }
129061da546Spatrick
130061da546Spatrick llvm::Expected<std::vector<lldb::BreakpointSP>>
FindBreakpointsByName(const char * name)131061da546Spatrick BreakpointList::FindBreakpointsByName(const char *name) {
132061da546Spatrick if (!name)
133061da546Spatrick return llvm::createStringError(llvm::errc::invalid_argument,
134061da546Spatrick "FindBreakpointsByName requires a name");
135061da546Spatrick
136061da546Spatrick Status error;
137061da546Spatrick if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))
138061da546Spatrick return error.ToError();
139061da546Spatrick
140061da546Spatrick std::vector<lldb::BreakpointSP> matching_bps;
141061da546Spatrick for (BreakpointSP bkpt_sp : Breakpoints()) {
142061da546Spatrick if (bkpt_sp->MatchesName(name)) {
143061da546Spatrick matching_bps.push_back(bkpt_sp);
144061da546Spatrick }
145061da546Spatrick }
146061da546Spatrick
147061da546Spatrick return matching_bps;
148061da546Spatrick }
149061da546Spatrick
Dump(Stream * s) const150061da546Spatrick void BreakpointList::Dump(Stream *s) const {
151061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
152061da546Spatrick s->Printf("%p: ", static_cast<const void *>(this));
153061da546Spatrick s->Indent();
154061da546Spatrick s->Printf("BreakpointList with %u Breakpoints:\n",
155061da546Spatrick (uint32_t)m_breakpoints.size());
156061da546Spatrick s->IndentMore();
157061da546Spatrick for (const auto &bp_sp : m_breakpoints)
158061da546Spatrick bp_sp->Dump(s);
159061da546Spatrick s->IndentLess();
160061da546Spatrick }
161061da546Spatrick
GetBreakpointAtIndex(size_t i) const162061da546Spatrick BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
163061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
164061da546Spatrick if (i < m_breakpoints.size())
165061da546Spatrick return m_breakpoints[i];
166061da546Spatrick return {};
167061da546Spatrick }
168061da546Spatrick
UpdateBreakpoints(ModuleList & module_list,bool added,bool delete_locations)169061da546Spatrick void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,
170061da546Spatrick bool delete_locations) {
171061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
172061da546Spatrick for (const auto &bp_sp : m_breakpoints)
173061da546Spatrick bp_sp->ModulesChanged(module_list, added, delete_locations);
174061da546Spatrick }
175061da546Spatrick
UpdateBreakpointsWhenModuleIsReplaced(ModuleSP old_module_sp,ModuleSP new_module_sp)176061da546Spatrick void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(
177061da546Spatrick ModuleSP old_module_sp, ModuleSP new_module_sp) {
178061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
179061da546Spatrick for (const auto &bp_sp : m_breakpoints)
180061da546Spatrick bp_sp->ModuleReplaced(old_module_sp, new_module_sp);
181061da546Spatrick }
182061da546Spatrick
ClearAllBreakpointSites()183061da546Spatrick void BreakpointList::ClearAllBreakpointSites() {
184061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_mutex);
185061da546Spatrick for (const auto &bp_sp : m_breakpoints)
186061da546Spatrick bp_sp->ClearAllBreakpointSites();
187061da546Spatrick }
188061da546Spatrick
ResetHitCounts()189*f6aab3d8Srobert void BreakpointList::ResetHitCounts() {
190*f6aab3d8Srobert std::lock_guard<std::recursive_mutex> guard(m_mutex);
191*f6aab3d8Srobert for (const auto &bp_sp : m_breakpoints)
192*f6aab3d8Srobert bp_sp->ResetHitCount();
193*f6aab3d8Srobert }
194*f6aab3d8Srobert
GetListMutex(std::unique_lock<std::recursive_mutex> & lock)195061da546Spatrick void BreakpointList::GetListMutex(
196061da546Spatrick std::unique_lock<std::recursive_mutex> &lock) {
197061da546Spatrick lock = std::unique_lock<std::recursive_mutex>(m_mutex);
198061da546Spatrick }
199