Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Breakpoint/WatchpointList.cpp
39587 views
1
//===-- WatchpointList.cpp ------------------------------------------------===//
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/WatchpointList.h"
10
#include "lldb/Breakpoint/Watchpoint.h"
11
12
using namespace lldb;
13
using namespace lldb_private;
14
15
WatchpointList::WatchpointList() = default;
16
17
WatchpointList::~WatchpointList() = default;
18
19
// Add a watchpoint to the list.
20
lldb::watch_id_t WatchpointList::Add(const WatchpointSP &wp_sp, bool notify) {
21
std::lock_guard<std::recursive_mutex> guard(m_mutex);
22
wp_sp->SetID(++m_next_wp_id);
23
m_watchpoints.push_back(wp_sp);
24
if (notify) {
25
if (wp_sp->GetTarget().EventTypeHasListeners(
26
Target::eBroadcastBitWatchpointChanged)) {
27
auto data_sp = std::make_shared<Watchpoint::WatchpointEventData>(
28
eWatchpointEventTypeAdded, wp_sp);
29
wp_sp->GetTarget().BroadcastEvent(Target::eBroadcastBitWatchpointChanged,
30
data_sp);
31
}
32
}
33
return wp_sp->GetID();
34
}
35
36
void WatchpointList::Dump(Stream *s) const {
37
DumpWithLevel(s, lldb::eDescriptionLevelBrief);
38
}
39
40
void WatchpointList::DumpWithLevel(
41
Stream *s, lldb::DescriptionLevel description_level) const {
42
std::lock_guard<std::recursive_mutex> guard(m_mutex);
43
s->Printf("%p: ", static_cast<const void *>(this));
44
// s->Indent();
45
s->Printf("WatchpointList with %" PRIu64 " Watchpoints:\n",
46
(uint64_t)m_watchpoints.size());
47
s->IndentMore();
48
wp_collection::const_iterator pos, end = m_watchpoints.end();
49
for (pos = m_watchpoints.begin(); pos != end; ++pos)
50
(*pos)->DumpWithLevel(s, description_level);
51
s->IndentLess();
52
}
53
54
const WatchpointSP WatchpointList::FindByAddress(lldb::addr_t addr) const {
55
WatchpointSP wp_sp;
56
std::lock_guard<std::recursive_mutex> guard(m_mutex);
57
if (!m_watchpoints.empty()) {
58
wp_collection::const_iterator pos, end = m_watchpoints.end();
59
for (pos = m_watchpoints.begin(); pos != end; ++pos) {
60
lldb::addr_t wp_addr = (*pos)->GetLoadAddress();
61
uint32_t wp_bytesize = (*pos)->GetByteSize();
62
if ((wp_addr <= addr) && ((wp_addr + wp_bytesize) > addr)) {
63
wp_sp = *pos;
64
break;
65
}
66
}
67
}
68
69
return wp_sp;
70
}
71
72
const WatchpointSP WatchpointList::FindBySpec(std::string spec) const {
73
WatchpointSP wp_sp;
74
std::lock_guard<std::recursive_mutex> guard(m_mutex);
75
if (!m_watchpoints.empty()) {
76
wp_collection::const_iterator pos, end = m_watchpoints.end();
77
for (pos = m_watchpoints.begin(); pos != end; ++pos)
78
if ((*pos)->GetWatchSpec() == spec) {
79
wp_sp = *pos;
80
break;
81
}
82
}
83
84
return wp_sp;
85
}
86
87
class WatchpointIDMatches {
88
public:
89
WatchpointIDMatches(lldb::watch_id_t watch_id) : m_watch_id(watch_id) {}
90
91
bool operator()(const WatchpointSP &wp) const {
92
return m_watch_id == wp->GetID();
93
}
94
95
private:
96
const lldb::watch_id_t m_watch_id;
97
};
98
99
WatchpointList::wp_collection::iterator
100
WatchpointList::GetIDIterator(lldb::watch_id_t watch_id) {
101
return std::find_if(m_watchpoints.begin(),
102
m_watchpoints.end(), // Search full range
103
WatchpointIDMatches(watch_id)); // Predicate
104
}
105
106
WatchpointList::wp_collection::const_iterator
107
WatchpointList::GetIDConstIterator(lldb::watch_id_t watch_id) const {
108
return std::find_if(m_watchpoints.begin(),
109
m_watchpoints.end(), // Search full range
110
WatchpointIDMatches(watch_id)); // Predicate
111
}
112
113
WatchpointSP WatchpointList::FindByID(lldb::watch_id_t watch_id) const {
114
WatchpointSP wp_sp;
115
std::lock_guard<std::recursive_mutex> guard(m_mutex);
116
wp_collection::const_iterator pos = GetIDConstIterator(watch_id);
117
if (pos != m_watchpoints.end())
118
wp_sp = *pos;
119
120
return wp_sp;
121
}
122
123
lldb::watch_id_t WatchpointList::FindIDByAddress(lldb::addr_t addr) {
124
WatchpointSP wp_sp = FindByAddress(addr);
125
if (wp_sp) {
126
return wp_sp->GetID();
127
}
128
return LLDB_INVALID_WATCH_ID;
129
}
130
131
lldb::watch_id_t WatchpointList::FindIDBySpec(std::string spec) {
132
WatchpointSP wp_sp = FindBySpec(spec);
133
if (wp_sp) {
134
return wp_sp->GetID();
135
}
136
return LLDB_INVALID_WATCH_ID;
137
}
138
139
WatchpointSP WatchpointList::GetByIndex(uint32_t i) {
140
std::lock_guard<std::recursive_mutex> guard(m_mutex);
141
WatchpointSP wp_sp;
142
if (i < m_watchpoints.size()) {
143
wp_collection::const_iterator pos = m_watchpoints.begin();
144
std::advance(pos, i);
145
wp_sp = *pos;
146
}
147
return wp_sp;
148
}
149
150
const WatchpointSP WatchpointList::GetByIndex(uint32_t i) const {
151
std::lock_guard<std::recursive_mutex> guard(m_mutex);
152
WatchpointSP wp_sp;
153
if (i < m_watchpoints.size()) {
154
wp_collection::const_iterator pos = m_watchpoints.begin();
155
std::advance(pos, i);
156
wp_sp = *pos;
157
}
158
return wp_sp;
159
}
160
161
std::vector<lldb::watch_id_t> WatchpointList::GetWatchpointIDs() const {
162
std::vector<lldb::watch_id_t> IDs;
163
wp_collection::const_iterator pos, end = m_watchpoints.end();
164
for (pos = m_watchpoints.begin(); pos != end; ++pos)
165
IDs.push_back((*pos)->GetID());
166
return IDs;
167
}
168
169
bool WatchpointList::Remove(lldb::watch_id_t watch_id, bool notify) {
170
std::lock_guard<std::recursive_mutex> guard(m_mutex);
171
wp_collection::iterator pos = GetIDIterator(watch_id);
172
if (pos != m_watchpoints.end()) {
173
WatchpointSP wp_sp = *pos;
174
if (notify) {
175
if (wp_sp->GetTarget().EventTypeHasListeners(
176
Target::eBroadcastBitWatchpointChanged)) {
177
auto data_sp = std::make_shared<Watchpoint::WatchpointEventData>(
178
eWatchpointEventTypeRemoved, wp_sp);
179
wp_sp->GetTarget().BroadcastEvent(
180
Target::eBroadcastBitWatchpointChanged, data_sp);
181
}
182
}
183
m_watchpoints.erase(pos);
184
return true;
185
}
186
return false;
187
}
188
189
uint32_t WatchpointList::GetHitCount() const {
190
uint32_t hit_count = 0;
191
std::lock_guard<std::recursive_mutex> guard(m_mutex);
192
wp_collection::const_iterator pos, end = m_watchpoints.end();
193
for (pos = m_watchpoints.begin(); pos != end; ++pos)
194
hit_count += (*pos)->GetHitCount();
195
return hit_count;
196
}
197
198
bool WatchpointList::ShouldStop(StoppointCallbackContext *context,
199
lldb::watch_id_t watch_id) {
200
201
WatchpointSP wp_sp = FindByID(watch_id);
202
if (wp_sp) {
203
// Let the Watchpoint decide if it should stop here (could not have reached
204
// it's target hit count yet, or it could have a callback that decided it
205
// shouldn't stop.
206
return wp_sp->ShouldStop(context);
207
}
208
// We should stop here since this Watchpoint isn't valid anymore or it
209
// doesn't exist.
210
return true;
211
}
212
213
void WatchpointList::GetDescription(Stream *s, lldb::DescriptionLevel level) {
214
std::lock_guard<std::recursive_mutex> guard(m_mutex);
215
wp_collection::iterator pos, end = m_watchpoints.end();
216
217
for (pos = m_watchpoints.begin(); pos != end; ++pos) {
218
s->Printf(" ");
219
(*pos)->Dump(s);
220
}
221
}
222
223
void WatchpointList::SetEnabledAll(bool enabled) {
224
std::lock_guard<std::recursive_mutex> guard(m_mutex);
225
226
wp_collection::iterator pos, end = m_watchpoints.end();
227
for (pos = m_watchpoints.begin(); pos != end; ++pos)
228
(*pos)->SetEnabled(enabled);
229
}
230
231
void WatchpointList::RemoveAll(bool notify) {
232
std::lock_guard<std::recursive_mutex> guard(m_mutex);
233
if (notify) {
234
235
{
236
wp_collection::iterator pos, end = m_watchpoints.end();
237
for (pos = m_watchpoints.begin(); pos != end; ++pos) {
238
if ((*pos)->GetTarget().EventTypeHasListeners(
239
Target::eBroadcastBitBreakpointChanged)) {
240
auto data_sp = std::make_shared<Watchpoint::WatchpointEventData>(
241
eWatchpointEventTypeRemoved, *pos);
242
(*pos)->GetTarget().BroadcastEvent(
243
Target::eBroadcastBitWatchpointChanged, data_sp);
244
}
245
}
246
}
247
}
248
m_watchpoints.clear();
249
}
250
251
void WatchpointList::GetListMutex(
252
std::unique_lock<std::recursive_mutex> &lock) {
253
lock = std::unique_lock<std::recursive_mutex>(m_mutex);
254
}
255
256