1 //===-- BreakpointLocationCollection.cpp ------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "lldb/Breakpoint/BreakpointLocationCollection.h"
10 #include "lldb/Breakpoint/Breakpoint.h"
11 #include "lldb/Breakpoint/BreakpointLocation.h"
12 #include "lldb/Core/ModuleList.h"
13 #include "lldb/Target/Thread.h"
14 #include "lldb/Target/ThreadSpec.h"
15
16 using namespace lldb;
17 using namespace lldb_private;
18
19 // BreakpointLocationCollection constructor
BreakpointLocationCollection()20 BreakpointLocationCollection::BreakpointLocationCollection()
21 : m_break_loc_collection(), m_collection_mutex() {}
22
23 // Destructor
~BreakpointLocationCollection()24 BreakpointLocationCollection::~BreakpointLocationCollection() {}
25
Add(const BreakpointLocationSP & bp_loc)26 void BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc) {
27 std::lock_guard<std::mutex> guard(m_collection_mutex);
28 BreakpointLocationSP old_bp_loc =
29 FindByIDPair(bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
30 if (!old_bp_loc.get())
31 m_break_loc_collection.push_back(bp_loc);
32 }
33
Remove(lldb::break_id_t bp_id,lldb::break_id_t bp_loc_id)34 bool BreakpointLocationCollection::Remove(lldb::break_id_t bp_id,
35 lldb::break_id_t bp_loc_id) {
36 std::lock_guard<std::mutex> guard(m_collection_mutex);
37 collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id); // Predicate
38 if (pos != m_break_loc_collection.end()) {
39 m_break_loc_collection.erase(pos);
40 return true;
41 }
42 return false;
43 }
44
45 class BreakpointIDPairMatches {
46 public:
BreakpointIDPairMatches(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)47 BreakpointIDPairMatches(lldb::break_id_t break_id,
48 lldb::break_id_t break_loc_id)
49 : m_break_id(break_id), m_break_loc_id(break_loc_id) {}
50
operator ()(const BreakpointLocationSP & bp_loc) const51 bool operator()(const BreakpointLocationSP &bp_loc) const {
52 return m_break_id == bp_loc->GetBreakpoint().GetID() &&
53 m_break_loc_id == bp_loc->GetID();
54 }
55
56 private:
57 const lldb::break_id_t m_break_id;
58 const lldb::break_id_t m_break_loc_id;
59 };
60
61 BreakpointLocationCollection::collection::iterator
GetIDPairIterator(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)62 BreakpointLocationCollection::GetIDPairIterator(lldb::break_id_t break_id,
63 lldb::break_id_t break_loc_id) {
64 return std::find_if(
65 m_break_loc_collection.begin(),
66 m_break_loc_collection.end(), // Search full range
67 BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
68 }
69
70 BreakpointLocationCollection::collection::const_iterator
GetIDPairConstIterator(lldb::break_id_t break_id,lldb::break_id_t break_loc_id) const71 BreakpointLocationCollection::GetIDPairConstIterator(
72 lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
73 return std::find_if(
74 m_break_loc_collection.begin(),
75 m_break_loc_collection.end(), // Search full range
76 BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
77 }
78
79 BreakpointLocationSP
FindByIDPair(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)80 BreakpointLocationCollection::FindByIDPair(lldb::break_id_t break_id,
81 lldb::break_id_t break_loc_id) {
82 BreakpointLocationSP stop_sp;
83 collection::iterator pos = GetIDPairIterator(break_id, break_loc_id);
84 if (pos != m_break_loc_collection.end())
85 stop_sp = *pos;
86
87 return stop_sp;
88 }
89
FindByIDPair(lldb::break_id_t break_id,lldb::break_id_t break_loc_id) const90 const BreakpointLocationSP BreakpointLocationCollection::FindByIDPair(
91 lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
92 BreakpointLocationSP stop_sp;
93 collection::const_iterator pos =
94 GetIDPairConstIterator(break_id, break_loc_id);
95 if (pos != m_break_loc_collection.end())
96 stop_sp = *pos;
97
98 return stop_sp;
99 }
100
GetByIndex(size_t i)101 BreakpointLocationSP BreakpointLocationCollection::GetByIndex(size_t i) {
102 std::lock_guard<std::mutex> guard(m_collection_mutex);
103 BreakpointLocationSP stop_sp;
104 if (i < m_break_loc_collection.size())
105 stop_sp = m_break_loc_collection[i];
106
107 return stop_sp;
108 }
109
110 const BreakpointLocationSP
GetByIndex(size_t i) const111 BreakpointLocationCollection::GetByIndex(size_t i) const {
112 std::lock_guard<std::mutex> guard(m_collection_mutex);
113 BreakpointLocationSP stop_sp;
114 if (i < m_break_loc_collection.size())
115 stop_sp = m_break_loc_collection[i];
116
117 return stop_sp;
118 }
119
ShouldStop(StoppointCallbackContext * context)120 bool BreakpointLocationCollection::ShouldStop(
121 StoppointCallbackContext *context) {
122 bool shouldStop = false;
123 size_t i = 0;
124 size_t prev_size = GetSize();
125 while (i < prev_size) {
126 // ShouldStop can remove the breakpoint from the list
127 if (GetByIndex(i)->ShouldStop(context))
128 shouldStop = true;
129
130 if (prev_size == GetSize())
131 i++;
132 prev_size = GetSize();
133 }
134 return shouldStop;
135 }
136
ValidForThisThread(Thread * thread)137 bool BreakpointLocationCollection::ValidForThisThread(Thread *thread) {
138 std::lock_guard<std::mutex> guard(m_collection_mutex);
139 collection::iterator pos, begin = m_break_loc_collection.begin(),
140 end = m_break_loc_collection.end();
141
142 for (pos = begin; pos != end; ++pos) {
143 if ((*pos)->ValidForThisThread(thread))
144 return true;
145 }
146 return false;
147 }
148
IsInternal() const149 bool BreakpointLocationCollection::IsInternal() const {
150 std::lock_guard<std::mutex> guard(m_collection_mutex);
151 collection::const_iterator pos, begin = m_break_loc_collection.begin(),
152 end = m_break_loc_collection.end();
153
154 bool is_internal = true;
155
156 for (pos = begin; pos != end; ++pos) {
157 if (!(*pos)->GetBreakpoint().IsInternal()) {
158 is_internal = false;
159 break;
160 }
161 }
162 return is_internal;
163 }
164
GetDescription(Stream * s,lldb::DescriptionLevel level)165 void BreakpointLocationCollection::GetDescription(
166 Stream *s, lldb::DescriptionLevel level) {
167 std::lock_guard<std::mutex> guard(m_collection_mutex);
168 collection::iterator pos, begin = m_break_loc_collection.begin(),
169 end = m_break_loc_collection.end();
170
171 for (pos = begin; pos != end; ++pos) {
172 if (pos != begin)
173 s->PutChar(' ');
174 (*pos)->GetDescription(s, level);
175 }
176 }
177
operator =(const BreakpointLocationCollection & rhs)178 BreakpointLocationCollection &BreakpointLocationCollection::operator=(
179 const BreakpointLocationCollection &rhs) {
180 if (this != &rhs) {
181 std::lock(m_collection_mutex, rhs.m_collection_mutex);
182 std::lock_guard<std::mutex> lhs_guard(m_collection_mutex, std::adopt_lock);
183 std::lock_guard<std::mutex> rhs_guard(rhs.m_collection_mutex, std::adopt_lock);
184 m_break_loc_collection = rhs.m_break_loc_collection;
185 }
186 return *this;
187 }
188