1dda28197Spatrick //===-- BreakpointLocationCollection.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/BreakpointLocationCollection.h"
10061da546Spatrick #include "lldb/Breakpoint/Breakpoint.h"
11061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
12061da546Spatrick #include "lldb/Core/ModuleList.h"
13061da546Spatrick #include "lldb/Target/Thread.h"
14061da546Spatrick #include "lldb/Target/ThreadSpec.h"
15061da546Spatrick
16061da546Spatrick using namespace lldb;
17061da546Spatrick using namespace lldb_private;
18061da546Spatrick
19061da546Spatrick // BreakpointLocationCollection constructor
20*f6aab3d8Srobert BreakpointLocationCollection::BreakpointLocationCollection() = default;
21061da546Spatrick
22061da546Spatrick // Destructor
23be691f3bSpatrick BreakpointLocationCollection::~BreakpointLocationCollection() = default;
24061da546Spatrick
Add(const BreakpointLocationSP & bp_loc)25061da546Spatrick void BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc) {
26061da546Spatrick std::lock_guard<std::mutex> guard(m_collection_mutex);
27061da546Spatrick BreakpointLocationSP old_bp_loc =
28061da546Spatrick FindByIDPair(bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
29061da546Spatrick if (!old_bp_loc.get())
30061da546Spatrick m_break_loc_collection.push_back(bp_loc);
31061da546Spatrick }
32061da546Spatrick
Remove(lldb::break_id_t bp_id,lldb::break_id_t bp_loc_id)33061da546Spatrick bool BreakpointLocationCollection::Remove(lldb::break_id_t bp_id,
34061da546Spatrick lldb::break_id_t bp_loc_id) {
35061da546Spatrick std::lock_guard<std::mutex> guard(m_collection_mutex);
36061da546Spatrick collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id); // Predicate
37061da546Spatrick if (pos != m_break_loc_collection.end()) {
38061da546Spatrick m_break_loc_collection.erase(pos);
39061da546Spatrick return true;
40061da546Spatrick }
41061da546Spatrick return false;
42061da546Spatrick }
43061da546Spatrick
44061da546Spatrick class BreakpointIDPairMatches {
45061da546Spatrick public:
BreakpointIDPairMatches(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)46061da546Spatrick BreakpointIDPairMatches(lldb::break_id_t break_id,
47061da546Spatrick lldb::break_id_t break_loc_id)
48061da546Spatrick : m_break_id(break_id), m_break_loc_id(break_loc_id) {}
49061da546Spatrick
operator ()(const BreakpointLocationSP & bp_loc) const50061da546Spatrick bool operator()(const BreakpointLocationSP &bp_loc) const {
51061da546Spatrick return m_break_id == bp_loc->GetBreakpoint().GetID() &&
52061da546Spatrick m_break_loc_id == bp_loc->GetID();
53061da546Spatrick }
54061da546Spatrick
55061da546Spatrick private:
56061da546Spatrick const lldb::break_id_t m_break_id;
57061da546Spatrick const lldb::break_id_t m_break_loc_id;
58061da546Spatrick };
59061da546Spatrick
60061da546Spatrick BreakpointLocationCollection::collection::iterator
GetIDPairIterator(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)61061da546Spatrick BreakpointLocationCollection::GetIDPairIterator(lldb::break_id_t break_id,
62061da546Spatrick lldb::break_id_t break_loc_id) {
63061da546Spatrick return std::find_if(
64061da546Spatrick m_break_loc_collection.begin(),
65061da546Spatrick m_break_loc_collection.end(), // Search full range
66061da546Spatrick BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
67061da546Spatrick }
68061da546Spatrick
69061da546Spatrick BreakpointLocationCollection::collection::const_iterator
GetIDPairConstIterator(lldb::break_id_t break_id,lldb::break_id_t break_loc_id) const70061da546Spatrick BreakpointLocationCollection::GetIDPairConstIterator(
71061da546Spatrick lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
72061da546Spatrick return std::find_if(
73061da546Spatrick m_break_loc_collection.begin(),
74061da546Spatrick m_break_loc_collection.end(), // Search full range
75061da546Spatrick BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
76061da546Spatrick }
77061da546Spatrick
78061da546Spatrick BreakpointLocationSP
FindByIDPair(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)79061da546Spatrick BreakpointLocationCollection::FindByIDPair(lldb::break_id_t break_id,
80061da546Spatrick lldb::break_id_t break_loc_id) {
81061da546Spatrick BreakpointLocationSP stop_sp;
82061da546Spatrick collection::iterator pos = GetIDPairIterator(break_id, break_loc_id);
83061da546Spatrick if (pos != m_break_loc_collection.end())
84061da546Spatrick stop_sp = *pos;
85061da546Spatrick
86061da546Spatrick return stop_sp;
87061da546Spatrick }
88061da546Spatrick
FindByIDPair(lldb::break_id_t break_id,lldb::break_id_t break_loc_id) const89061da546Spatrick const BreakpointLocationSP BreakpointLocationCollection::FindByIDPair(
90061da546Spatrick lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
91061da546Spatrick BreakpointLocationSP stop_sp;
92061da546Spatrick collection::const_iterator pos =
93061da546Spatrick GetIDPairConstIterator(break_id, break_loc_id);
94061da546Spatrick if (pos != m_break_loc_collection.end())
95061da546Spatrick stop_sp = *pos;
96061da546Spatrick
97061da546Spatrick return stop_sp;
98061da546Spatrick }
99061da546Spatrick
GetByIndex(size_t i)100061da546Spatrick BreakpointLocationSP BreakpointLocationCollection::GetByIndex(size_t i) {
101061da546Spatrick std::lock_guard<std::mutex> guard(m_collection_mutex);
102061da546Spatrick BreakpointLocationSP stop_sp;
103061da546Spatrick if (i < m_break_loc_collection.size())
104061da546Spatrick stop_sp = m_break_loc_collection[i];
105061da546Spatrick
106061da546Spatrick return stop_sp;
107061da546Spatrick }
108061da546Spatrick
109061da546Spatrick const BreakpointLocationSP
GetByIndex(size_t i) const110061da546Spatrick BreakpointLocationCollection::GetByIndex(size_t i) const {
111061da546Spatrick std::lock_guard<std::mutex> guard(m_collection_mutex);
112061da546Spatrick BreakpointLocationSP stop_sp;
113061da546Spatrick if (i < m_break_loc_collection.size())
114061da546Spatrick stop_sp = m_break_loc_collection[i];
115061da546Spatrick
116061da546Spatrick return stop_sp;
117061da546Spatrick }
118061da546Spatrick
ShouldStop(StoppointCallbackContext * context)119061da546Spatrick bool BreakpointLocationCollection::ShouldStop(
120061da546Spatrick StoppointCallbackContext *context) {
121061da546Spatrick bool shouldStop = false;
122061da546Spatrick size_t i = 0;
123061da546Spatrick size_t prev_size = GetSize();
124061da546Spatrick while (i < prev_size) {
125*f6aab3d8Srobert // ShouldStop can remove the breakpoint from the list, or even delete
126*f6aab3d8Srobert // it, so we should
127*f6aab3d8Srobert BreakpointLocationSP cur_loc_sp = GetByIndex(i);
128*f6aab3d8Srobert BreakpointSP keep_bkpt_alive_sp = cur_loc_sp->GetBreakpoint().shared_from_this();
129*f6aab3d8Srobert if (cur_loc_sp->ShouldStop(context))
130061da546Spatrick shouldStop = true;
131061da546Spatrick
132061da546Spatrick if (prev_size == GetSize())
133061da546Spatrick i++;
134061da546Spatrick prev_size = GetSize();
135061da546Spatrick }
136061da546Spatrick return shouldStop;
137061da546Spatrick }
138061da546Spatrick
ValidForThisThread(Thread & thread)139be691f3bSpatrick bool BreakpointLocationCollection::ValidForThisThread(Thread &thread) {
140061da546Spatrick std::lock_guard<std::mutex> guard(m_collection_mutex);
141061da546Spatrick collection::iterator pos, begin = m_break_loc_collection.begin(),
142061da546Spatrick end = m_break_loc_collection.end();
143061da546Spatrick
144061da546Spatrick for (pos = begin; pos != end; ++pos) {
145061da546Spatrick if ((*pos)->ValidForThisThread(thread))
146061da546Spatrick return true;
147061da546Spatrick }
148061da546Spatrick return false;
149061da546Spatrick }
150061da546Spatrick
IsInternal() const151061da546Spatrick bool BreakpointLocationCollection::IsInternal() const {
152061da546Spatrick std::lock_guard<std::mutex> guard(m_collection_mutex);
153061da546Spatrick collection::const_iterator pos, begin = m_break_loc_collection.begin(),
154061da546Spatrick end = m_break_loc_collection.end();
155061da546Spatrick
156061da546Spatrick bool is_internal = true;
157061da546Spatrick
158061da546Spatrick for (pos = begin; pos != end; ++pos) {
159061da546Spatrick if (!(*pos)->GetBreakpoint().IsInternal()) {
160061da546Spatrick is_internal = false;
161061da546Spatrick break;
162061da546Spatrick }
163061da546Spatrick }
164061da546Spatrick return is_internal;
165061da546Spatrick }
166061da546Spatrick
GetDescription(Stream * s,lldb::DescriptionLevel level)167061da546Spatrick void BreakpointLocationCollection::GetDescription(
168061da546Spatrick Stream *s, lldb::DescriptionLevel level) {
169061da546Spatrick std::lock_guard<std::mutex> guard(m_collection_mutex);
170061da546Spatrick collection::iterator pos, begin = m_break_loc_collection.begin(),
171061da546Spatrick end = m_break_loc_collection.end();
172061da546Spatrick
173061da546Spatrick for (pos = begin; pos != end; ++pos) {
174061da546Spatrick if (pos != begin)
175061da546Spatrick s->PutChar(' ');
176061da546Spatrick (*pos)->GetDescription(s, level);
177061da546Spatrick }
178061da546Spatrick }
179061da546Spatrick
operator =(const BreakpointLocationCollection & rhs)180061da546Spatrick BreakpointLocationCollection &BreakpointLocationCollection::operator=(
181061da546Spatrick const BreakpointLocationCollection &rhs) {
182061da546Spatrick if (this != &rhs) {
183061da546Spatrick std::lock(m_collection_mutex, rhs.m_collection_mutex);
184061da546Spatrick std::lock_guard<std::mutex> lhs_guard(m_collection_mutex, std::adopt_lock);
185061da546Spatrick std::lock_guard<std::mutex> rhs_guard(rhs.m_collection_mutex, std::adopt_lock);
186061da546Spatrick m_break_loc_collection = rhs.m_break_loc_collection;
187061da546Spatrick }
188061da546Spatrick return *this;
189061da546Spatrick }
190