180814287SRaphael Isemann //===-- BreakpointList.cpp ------------------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner
930fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointList.h"
1030fdc8d8SChris Lattner
119fed0d85SGreg Clayton #include "lldb/Target/Target.h"
1230fdc8d8SChris Lattner
1395b2e516SJoseph Tremoulet #include "llvm/Support/Errc.h"
1495b2e516SJoseph Tremoulet
1530fdc8d8SChris Lattner using namespace lldb;
1630fdc8d8SChris Lattner using namespace lldb_private;
1730fdc8d8SChris Lattner
NotifyChange(const BreakpointSP & bp,BreakpointEventType event)18dadbb45fSJonas Devlieghere static void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) {
19dadbb45fSJonas Devlieghere Target &target = bp->GetTarget();
20dadbb45fSJonas Devlieghere if (target.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
21dadbb45fSJonas Devlieghere target.BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
22dadbb45fSJonas Devlieghere new Breakpoint::BreakpointEventData(event, bp));
23dadbb45fSJonas Devlieghere }
24dadbb45fSJonas Devlieghere
BreakpointList(bool is_internal)25bb19a13cSSaleem Abdulrasool BreakpointList::BreakpointList(bool is_internal)
26*ee4b6cf5SKazu Hirata : m_next_break_id(0), m_is_internal(is_internal) {}
2730fdc8d8SChris Lattner
28fd2433e1SJonas Devlieghere BreakpointList::~BreakpointList() = default;
2930fdc8d8SChris Lattner
Add(BreakpointSP & bp_sp,bool notify)30b9c1b51eSKate Stone break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
31bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
32dadbb45fSJonas Devlieghere
3330fdc8d8SChris Lattner // Internal breakpoint IDs are negative, normal ones are positive
349fed0d85SGreg Clayton bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);
359fed0d85SGreg Clayton
369fed0d85SGreg Clayton m_breakpoints.push_back(bp_sp);
37dadbb45fSJonas Devlieghere
38dadbb45fSJonas Devlieghere if (notify)
39dadbb45fSJonas Devlieghere NotifyChange(bp_sp, eBreakpointEventTypeAdded);
40dadbb45fSJonas Devlieghere
419fed0d85SGreg Clayton return bp_sp->GetID();
4230fdc8d8SChris Lattner }
4330fdc8d8SChris Lattner
Remove(break_id_t break_id,bool notify)44b9c1b51eSKate Stone bool BreakpointList::Remove(break_id_t break_id, bool notify) {
45bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
46dadbb45fSJonas Devlieghere
47dadbb45fSJonas Devlieghere auto it = std::find_if(
48dadbb45fSJonas Devlieghere m_breakpoints.begin(), m_breakpoints.end(),
49dadbb45fSJonas Devlieghere [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
50dadbb45fSJonas Devlieghere
51dadbb45fSJonas Devlieghere if (it == m_breakpoints.end())
5230fdc8d8SChris Lattner return false;
53dadbb45fSJonas Devlieghere
54dadbb45fSJonas Devlieghere if (notify)
55dadbb45fSJonas Devlieghere NotifyChange(*it, eBreakpointEventTypeRemoved);
56dadbb45fSJonas Devlieghere
57dadbb45fSJonas Devlieghere m_breakpoints.erase(it);
58dadbb45fSJonas Devlieghere
59dadbb45fSJonas Devlieghere return true;
6030fdc8d8SChris Lattner }
6130fdc8d8SChris Lattner
RemoveInvalidLocations(const ArchSpec & arch)62b9c1b51eSKate Stone void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {
63bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
64b35db639SGreg Clayton for (const auto &bp_sp : m_breakpoints)
65b35db639SGreg Clayton bp_sp->RemoveInvalidLocations(arch);
66b35db639SGreg Clayton }
67b35db639SGreg Clayton
SetEnabledAll(bool enabled)68b9c1b51eSKate Stone void BreakpointList::SetEnabledAll(bool enabled) {
69bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
70b35db639SGreg Clayton for (const auto &bp_sp : m_breakpoints)
71b35db639SGreg Clayton bp_sp->SetEnabled(enabled);
7230fdc8d8SChris Lattner }
7330fdc8d8SChris Lattner
SetEnabledAllowed(bool enabled)74b842f2ecSJim Ingham void BreakpointList::SetEnabledAllowed(bool enabled) {
75b842f2ecSJim Ingham std::lock_guard<std::recursive_mutex> guard(m_mutex);
76b842f2ecSJim Ingham for (const auto &bp_sp : m_breakpoints)
77b842f2ecSJim Ingham if (bp_sp->AllowDisable())
78b842f2ecSJim Ingham bp_sp->SetEnabled(enabled);
79b842f2ecSJim Ingham }
80b842f2ecSJim Ingham
RemoveAll(bool notify)81b9c1b51eSKate Stone void BreakpointList::RemoveAll(bool notify) {
82bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
8330fdc8d8SChris Lattner ClearAllBreakpointSites();
8430fdc8d8SChris Lattner
85b9c1b51eSKate Stone if (notify) {
86dadbb45fSJonas Devlieghere for (const auto &bp_sp : m_breakpoints)
87dadbb45fSJonas Devlieghere NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
881b5792e5SJim Ingham }
89dadbb45fSJonas Devlieghere
90dadbb45fSJonas Devlieghere m_breakpoints.clear();
9130fdc8d8SChris Lattner }
9230fdc8d8SChris Lattner
RemoveAllowed(bool notify)93b842f2ecSJim Ingham void BreakpointList::RemoveAllowed(bool notify) {
94b842f2ecSJim Ingham std::lock_guard<std::recursive_mutex> guard(m_mutex);
95b842f2ecSJim Ingham
96dadbb45fSJonas Devlieghere for (const auto &bp_sp : m_breakpoints) {
97dadbb45fSJonas Devlieghere if (bp_sp->AllowDelete())
98dadbb45fSJonas Devlieghere bp_sp->ClearAllBreakpointSites();
99dadbb45fSJonas Devlieghere if (notify)
100dadbb45fSJonas Devlieghere NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
101b842f2ecSJim Ingham }
102b842f2ecSJim Ingham
1038568ca78SKazu Hirata llvm::erase_if(m_breakpoints,
1048568ca78SKazu Hirata [&](const BreakpointSP &bp) { return bp->AllowDelete(); });
10530fdc8d8SChris Lattner }
10630fdc8d8SChris Lattner
10730fdc8d8SChris Lattner BreakpointList::bp_collection::iterator
GetBreakpointIDIterator(break_id_t break_id)108b9c1b51eSKate Stone BreakpointList::GetBreakpointIDIterator(break_id_t break_id) {
109dadbb45fSJonas Devlieghere return std::find_if(
110dadbb45fSJonas Devlieghere m_breakpoints.begin(), m_breakpoints.end(),
111dadbb45fSJonas Devlieghere [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
11230fdc8d8SChris Lattner }
11330fdc8d8SChris Lattner
11430fdc8d8SChris Lattner BreakpointList::bp_collection::const_iterator
GetBreakpointIDConstIterator(break_id_t break_id) const115b9c1b51eSKate Stone BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {
116dadbb45fSJonas Devlieghere return std::find_if(
117dadbb45fSJonas Devlieghere m_breakpoints.begin(), m_breakpoints.end(),
118dadbb45fSJonas Devlieghere [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
11930fdc8d8SChris Lattner }
12030fdc8d8SChris Lattner
FindBreakpointByID(break_id_t break_id) const121dadbb45fSJonas Devlieghere BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const {
122bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
12330fdc8d8SChris Lattner
124dadbb45fSJonas Devlieghere auto it = GetBreakpointIDConstIterator(break_id);
125dadbb45fSJonas Devlieghere if (it != m_breakpoints.end())
126dadbb45fSJonas Devlieghere return *it;
127dadbb45fSJonas Devlieghere return {};
12830fdc8d8SChris Lattner }
12930fdc8d8SChris Lattner
13095b2e516SJoseph Tremoulet llvm::Expected<std::vector<lldb::BreakpointSP>>
FindBreakpointsByName(const char * name)13195b2e516SJoseph Tremoulet BreakpointList::FindBreakpointsByName(const char *name) {
132ff9a91eaSJim Ingham if (!name)
13395b2e516SJoseph Tremoulet return llvm::createStringError(llvm::errc::invalid_argument,
13495b2e516SJoseph Tremoulet "FindBreakpointsByName requires a name");
135ff9a91eaSJim Ingham
13695b2e516SJoseph Tremoulet Status error;
137ff9a91eaSJim Ingham if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))
13895b2e516SJoseph Tremoulet return error.ToError();
139ff9a91eaSJim Ingham
14095b2e516SJoseph Tremoulet std::vector<lldb::BreakpointSP> matching_bps;
141ff9a91eaSJim Ingham for (BreakpointSP bkpt_sp : Breakpoints()) {
142ff9a91eaSJim Ingham if (bkpt_sp->MatchesName(name)) {
14395b2e516SJoseph Tremoulet matching_bps.push_back(bkpt_sp);
144ff9a91eaSJim Ingham }
145ff9a91eaSJim Ingham }
146dadbb45fSJonas Devlieghere
14795b2e516SJoseph Tremoulet return matching_bps;
148ff9a91eaSJim Ingham }
149ff9a91eaSJim Ingham
Dump(Stream * s) const150b9c1b51eSKate Stone void BreakpointList::Dump(Stream *s) const {
151bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
152324a1036SSaleem Abdulrasool s->Printf("%p: ", static_cast<const void *>(this));
15330fdc8d8SChris Lattner s->Indent();
154b9c1b51eSKate Stone s->Printf("BreakpointList with %u Breakpoints:\n",
155b9c1b51eSKate Stone (uint32_t)m_breakpoints.size());
15630fdc8d8SChris Lattner s->IndentMore();
157b35db639SGreg Clayton for (const auto &bp_sp : m_breakpoints)
158b35db639SGreg Clayton bp_sp->Dump(s);
15930fdc8d8SChris Lattner s->IndentLess();
16030fdc8d8SChris Lattner }
16130fdc8d8SChris Lattner
GetBreakpointAtIndex(size_t i) const162dadbb45fSJonas Devlieghere BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
163bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
164dadbb45fSJonas Devlieghere if (i < m_breakpoints.size())
165dadbb45fSJonas Devlieghere return m_breakpoints[i];
166dadbb45fSJonas Devlieghere return {};
16730fdc8d8SChris Lattner }
16830fdc8d8SChris Lattner
UpdateBreakpoints(ModuleList & module_list,bool added,bool delete_locations)169b9c1b51eSKate Stone void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,
170b9c1b51eSKate Stone bool delete_locations) {
171bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
172b35db639SGreg Clayton for (const auto &bp_sp : m_breakpoints)
173b35db639SGreg Clayton bp_sp->ModulesChanged(module_list, added, delete_locations);
17430fdc8d8SChris Lattner }
17530fdc8d8SChris Lattner
UpdateBreakpointsWhenModuleIsReplaced(ModuleSP old_module_sp,ModuleSP new_module_sp)176b9c1b51eSKate Stone void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(
177b9c1b51eSKate Stone ModuleSP old_module_sp, ModuleSP new_module_sp) {
178bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
179b35db639SGreg Clayton for (const auto &bp_sp : m_breakpoints)
180b35db639SGreg Clayton bp_sp->ModuleReplaced(old_module_sp, new_module_sp);
1814a94c910SJim Ingham }
1824a94c910SJim Ingham
ClearAllBreakpointSites()183b9c1b51eSKate Stone void BreakpointList::ClearAllBreakpointSites() {
184bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex);
185b35db639SGreg Clayton for (const auto &bp_sp : m_breakpoints)
186b35db639SGreg Clayton bp_sp->ClearAllBreakpointSites();
18730fdc8d8SChris Lattner }
1881b54c88cSJim Ingham
GetListMutex(std::unique_lock<std::recursive_mutex> & lock)189b9c1b51eSKate Stone void BreakpointList::GetListMutex(
190b9c1b51eSKate Stone std::unique_lock<std::recursive_mutex> &lock) {
191bb19a13cSSaleem Abdulrasool lock = std::unique_lock<std::recursive_mutex>(m_mutex);
1921b54c88cSJim Ingham }
193