1cfca06d7SDimitry Andric //===-- BreakpointLocationCollection.cpp ----------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/Breakpoint/BreakpointLocationCollection.h"
10f034231aSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
11f034231aSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
1214f1b3e8SDimitry Andric #include "lldb/Core/ModuleList.h"
13f034231aSEd Maste #include "lldb/Target/Thread.h"
14f034231aSEd Maste #include "lldb/Target/ThreadSpec.h"
15f034231aSEd Maste
16f034231aSEd Maste using namespace lldb;
17f034231aSEd Maste using namespace lldb_private;
18f034231aSEd Maste
19f034231aSEd Maste // BreakpointLocationCollection constructor
20145449b1SDimitry Andric BreakpointLocationCollection::BreakpointLocationCollection() = default;
21f034231aSEd Maste
22f034231aSEd Maste // Destructor
23344a3780SDimitry Andric BreakpointLocationCollection::~BreakpointLocationCollection() = default;
24f034231aSEd Maste
Add(const BreakpointLocationSP & bp_loc)2514f1b3e8SDimitry Andric void BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc) {
26f3fbd1c0SDimitry Andric std::lock_guard<std::mutex> guard(m_collection_mutex);
2714f1b3e8SDimitry Andric BreakpointLocationSP old_bp_loc =
2814f1b3e8SDimitry Andric FindByIDPair(bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
29f034231aSEd Maste if (!old_bp_loc.get())
30f034231aSEd Maste m_break_loc_collection.push_back(bp_loc);
31f034231aSEd Maste }
32f034231aSEd Maste
Remove(lldb::break_id_t bp_id,lldb::break_id_t bp_loc_id)3314f1b3e8SDimitry Andric bool BreakpointLocationCollection::Remove(lldb::break_id_t bp_id,
3414f1b3e8SDimitry Andric lldb::break_id_t bp_loc_id) {
35f3fbd1c0SDimitry Andric std::lock_guard<std::mutex> guard(m_collection_mutex);
36f034231aSEd Maste collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id); // Predicate
3714f1b3e8SDimitry Andric if (pos != m_break_loc_collection.end()) {
38f034231aSEd Maste m_break_loc_collection.erase(pos);
39f034231aSEd Maste return true;
40f034231aSEd Maste }
41f034231aSEd Maste return false;
42f034231aSEd Maste }
43f034231aSEd Maste
4414f1b3e8SDimitry Andric class BreakpointIDPairMatches {
45f034231aSEd Maste public:
BreakpointIDPairMatches(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)4614f1b3e8SDimitry Andric BreakpointIDPairMatches(lldb::break_id_t break_id,
4714f1b3e8SDimitry Andric lldb::break_id_t break_loc_id)
4814f1b3e8SDimitry Andric : m_break_id(break_id), m_break_loc_id(break_loc_id) {}
49f034231aSEd Maste
operator ()(const BreakpointLocationSP & bp_loc) const5014f1b3e8SDimitry Andric bool operator()(const BreakpointLocationSP &bp_loc) const {
5114f1b3e8SDimitry Andric return m_break_id == bp_loc->GetBreakpoint().GetID() &&
5214f1b3e8SDimitry Andric m_break_loc_id == bp_loc->GetID();
53f034231aSEd Maste }
54f034231aSEd Maste
55f034231aSEd Maste private:
56f034231aSEd Maste const lldb::break_id_t m_break_id;
57f034231aSEd Maste const lldb::break_id_t m_break_loc_id;
58f034231aSEd Maste };
59f034231aSEd Maste
60f034231aSEd Maste BreakpointLocationCollection::collection::iterator
GetIDPairIterator(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)6114f1b3e8SDimitry Andric BreakpointLocationCollection::GetIDPairIterator(lldb::break_id_t break_id,
6214f1b3e8SDimitry Andric lldb::break_id_t break_loc_id) {
6314f1b3e8SDimitry Andric return std::find_if(
6414f1b3e8SDimitry Andric m_break_loc_collection.begin(),
6514f1b3e8SDimitry Andric m_break_loc_collection.end(), // Search full range
66f034231aSEd Maste BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
67f034231aSEd Maste }
68f034231aSEd Maste
69f034231aSEd Maste BreakpointLocationCollection::collection::const_iterator
GetIDPairConstIterator(lldb::break_id_t break_id,lldb::break_id_t break_loc_id) const7014f1b3e8SDimitry Andric BreakpointLocationCollection::GetIDPairConstIterator(
7114f1b3e8SDimitry Andric lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
7214f1b3e8SDimitry Andric return std::find_if(
7314f1b3e8SDimitry Andric m_break_loc_collection.begin(),
7414f1b3e8SDimitry Andric m_break_loc_collection.end(), // Search full range
75f034231aSEd Maste BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
76f034231aSEd Maste }
77f034231aSEd Maste
78f034231aSEd Maste BreakpointLocationSP
FindByIDPair(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)7914f1b3e8SDimitry Andric BreakpointLocationCollection::FindByIDPair(lldb::break_id_t break_id,
8014f1b3e8SDimitry Andric lldb::break_id_t break_loc_id) {
81f034231aSEd Maste BreakpointLocationSP stop_sp;
82f034231aSEd Maste collection::iterator pos = GetIDPairIterator(break_id, break_loc_id);
83f034231aSEd Maste if (pos != m_break_loc_collection.end())
84f034231aSEd Maste stop_sp = *pos;
85f034231aSEd Maste
86f034231aSEd Maste return stop_sp;
87f034231aSEd Maste }
88f034231aSEd Maste
FindByIDPair(lldb::break_id_t break_id,lldb::break_id_t break_loc_id) const8914f1b3e8SDimitry Andric const BreakpointLocationSP BreakpointLocationCollection::FindByIDPair(
9014f1b3e8SDimitry Andric lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
91f034231aSEd Maste BreakpointLocationSP stop_sp;
9214f1b3e8SDimitry Andric collection::const_iterator pos =
9314f1b3e8SDimitry Andric GetIDPairConstIterator(break_id, break_loc_id);
94f034231aSEd Maste if (pos != m_break_loc_collection.end())
95f034231aSEd Maste stop_sp = *pos;
96f034231aSEd Maste
97f034231aSEd Maste return stop_sp;
98f034231aSEd Maste }
99f034231aSEd Maste
GetByIndex(size_t i)10014f1b3e8SDimitry Andric BreakpointLocationSP BreakpointLocationCollection::GetByIndex(size_t i) {
101f3fbd1c0SDimitry Andric std::lock_guard<std::mutex> guard(m_collection_mutex);
102f034231aSEd Maste BreakpointLocationSP stop_sp;
103f034231aSEd Maste if (i < m_break_loc_collection.size())
104f034231aSEd Maste stop_sp = m_break_loc_collection[i];
105f034231aSEd Maste
106f034231aSEd Maste return stop_sp;
107f034231aSEd Maste }
108f034231aSEd Maste
109f034231aSEd Maste const BreakpointLocationSP
GetByIndex(size_t i) const11014f1b3e8SDimitry Andric BreakpointLocationCollection::GetByIndex(size_t i) const {
111f3fbd1c0SDimitry Andric std::lock_guard<std::mutex> guard(m_collection_mutex);
112f034231aSEd Maste BreakpointLocationSP stop_sp;
113f034231aSEd Maste if (i < m_break_loc_collection.size())
114f034231aSEd Maste stop_sp = m_break_loc_collection[i];
115f034231aSEd Maste
116f034231aSEd Maste return stop_sp;
117f034231aSEd Maste }
118f034231aSEd Maste
ShouldStop(StoppointCallbackContext * context)11914f1b3e8SDimitry Andric bool BreakpointLocationCollection::ShouldStop(
12014f1b3e8SDimitry Andric StoppointCallbackContext *context) {
121f034231aSEd Maste bool shouldStop = false;
1225e95aa85SEd Maste size_t i = 0;
1235e95aa85SEd Maste size_t prev_size = GetSize();
12414f1b3e8SDimitry Andric while (i < prev_size) {
125145449b1SDimitry Andric // ShouldStop can remove the breakpoint from the list, or even delete
126145449b1SDimitry Andric // it, so we should
127145449b1SDimitry Andric BreakpointLocationSP cur_loc_sp = GetByIndex(i);
128145449b1SDimitry Andric BreakpointSP keep_bkpt_alive_sp = cur_loc_sp->GetBreakpoint().shared_from_this();
129145449b1SDimitry Andric if (cur_loc_sp->ShouldStop(context))
130f034231aSEd Maste shouldStop = true;
1315e95aa85SEd Maste
1325e95aa85SEd Maste if (prev_size == GetSize())
1335e95aa85SEd Maste i++;
1345e95aa85SEd Maste prev_size = GetSize();
135f034231aSEd Maste }
136f034231aSEd Maste return shouldStop;
137f034231aSEd Maste }
138f034231aSEd Maste
ValidForThisThread(Thread & thread)139344a3780SDimitry Andric bool BreakpointLocationCollection::ValidForThisThread(Thread &thread) {
140f3fbd1c0SDimitry Andric std::lock_guard<std::mutex> guard(m_collection_mutex);
14114f1b3e8SDimitry Andric collection::iterator pos, begin = m_break_loc_collection.begin(),
142f034231aSEd Maste end = m_break_loc_collection.end();
143f034231aSEd Maste
14414f1b3e8SDimitry Andric for (pos = begin; pos != end; ++pos) {
145f034231aSEd Maste if ((*pos)->ValidForThisThread(thread))
146f034231aSEd Maste return true;
147f034231aSEd Maste }
148f034231aSEd Maste return false;
149f034231aSEd Maste }
150f034231aSEd Maste
IsInternal() const15114f1b3e8SDimitry Andric bool BreakpointLocationCollection::IsInternal() const {
152f3fbd1c0SDimitry Andric std::lock_guard<std::mutex> guard(m_collection_mutex);
15314f1b3e8SDimitry Andric collection::const_iterator pos, begin = m_break_loc_collection.begin(),
154f034231aSEd Maste end = m_break_loc_collection.end();
155f034231aSEd Maste
156f034231aSEd Maste bool is_internal = true;
157f034231aSEd Maste
15814f1b3e8SDimitry Andric for (pos = begin; pos != end; ++pos) {
15914f1b3e8SDimitry Andric if (!(*pos)->GetBreakpoint().IsInternal()) {
160f034231aSEd Maste is_internal = false;
161f034231aSEd Maste break;
162f034231aSEd Maste }
163f034231aSEd Maste }
164f034231aSEd Maste return is_internal;
165f034231aSEd Maste }
166f034231aSEd Maste
GetDescription(Stream * s,lldb::DescriptionLevel level)16714f1b3e8SDimitry Andric void BreakpointLocationCollection::GetDescription(
16814f1b3e8SDimitry Andric Stream *s, lldb::DescriptionLevel level) {
169f3fbd1c0SDimitry Andric std::lock_guard<std::mutex> guard(m_collection_mutex);
17014f1b3e8SDimitry Andric collection::iterator pos, begin = m_break_loc_collection.begin(),
171f034231aSEd Maste end = m_break_loc_collection.end();
172f034231aSEd Maste
17314f1b3e8SDimitry Andric for (pos = begin; pos != end; ++pos) {
174f034231aSEd Maste if (pos != begin)
175f034231aSEd Maste s->PutChar(' ');
176f034231aSEd Maste (*pos)->GetDescription(s, level);
177f034231aSEd Maste }
178f034231aSEd Maste }
1795f29bb8aSDimitry Andric
operator =(const BreakpointLocationCollection & rhs)1805f29bb8aSDimitry Andric BreakpointLocationCollection &BreakpointLocationCollection::operator=(
1815f29bb8aSDimitry Andric const BreakpointLocationCollection &rhs) {
1825f29bb8aSDimitry Andric if (this != &rhs) {
1835f29bb8aSDimitry Andric std::lock(m_collection_mutex, rhs.m_collection_mutex);
1845f29bb8aSDimitry Andric std::lock_guard<std::mutex> lhs_guard(m_collection_mutex, std::adopt_lock);
1855f29bb8aSDimitry Andric std::lock_guard<std::mutex> rhs_guard(rhs.m_collection_mutex, std::adopt_lock);
1865f29bb8aSDimitry Andric m_break_loc_collection = rhs.m_break_loc_collection;
1875f29bb8aSDimitry Andric }
1885f29bb8aSDimitry Andric return *this;
1895f29bb8aSDimitry Andric }
190