180814287SRaphael Isemann //===-- BreakpointLocationCollection.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/BreakpointLocationCollection.h"
104e78f606SGreg Clayton #include "lldb/Breakpoint/Breakpoint.h"
1130fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
12b9c1b51eSKate Stone #include "lldb/Core/ModuleList.h"
131b54c88cSJim Ingham #include "lldb/Target/Thread.h"
141b54c88cSJim Ingham #include "lldb/Target/ThreadSpec.h"
1530fdc8d8SChris Lattner 
1630fdc8d8SChris Lattner using namespace lldb;
1730fdc8d8SChris Lattner using namespace lldb_private;
1830fdc8d8SChris Lattner 
1930fdc8d8SChris Lattner // BreakpointLocationCollection constructor
20ee4b6cf5SKazu Hirata BreakpointLocationCollection::BreakpointLocationCollection() = default;
2130fdc8d8SChris Lattner 
2230fdc8d8SChris Lattner // Destructor
23fd2433e1SJonas Devlieghere BreakpointLocationCollection::~BreakpointLocationCollection() = default;
2430fdc8d8SChris Lattner 
Add(const BreakpointLocationSP & bp_loc)25b9c1b51eSKate Stone void BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc) {
261cf8f593SJim Ingham   std::lock_guard<std::mutex> guard(m_collection_mutex);
27b9c1b51eSKate Stone   BreakpointLocationSP old_bp_loc =
28b9c1b51eSKate Stone       FindByIDPair(bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
2930fdc8d8SChris Lattner   if (!old_bp_loc.get())
3030fdc8d8SChris Lattner     m_break_loc_collection.push_back(bp_loc);
3130fdc8d8SChris Lattner }
3230fdc8d8SChris Lattner 
Remove(lldb::break_id_t bp_id,lldb::break_id_t bp_loc_id)33b9c1b51eSKate Stone bool BreakpointLocationCollection::Remove(lldb::break_id_t bp_id,
34b9c1b51eSKate Stone                                           lldb::break_id_t bp_loc_id) {
351cf8f593SJim Ingham   std::lock_guard<std::mutex> guard(m_collection_mutex);
3630fdc8d8SChris Lattner   collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id); // Predicate
37b9c1b51eSKate Stone   if (pos != m_break_loc_collection.end()) {
3830fdc8d8SChris Lattner     m_break_loc_collection.erase(pos);
3930fdc8d8SChris Lattner     return true;
4030fdc8d8SChris Lattner   }
4130fdc8d8SChris Lattner   return false;
4230fdc8d8SChris Lattner }
4330fdc8d8SChris Lattner 
44b9c1b51eSKate Stone class BreakpointIDPairMatches {
4530fdc8d8SChris Lattner public:
BreakpointIDPairMatches(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)46b9c1b51eSKate Stone   BreakpointIDPairMatches(lldb::break_id_t break_id,
47b9c1b51eSKate Stone                           lldb::break_id_t break_loc_id)
48b9c1b51eSKate Stone       : m_break_id(break_id), m_break_loc_id(break_loc_id) {}
4930fdc8d8SChris Lattner 
operator ()(const BreakpointLocationSP & bp_loc) const50b9c1b51eSKate Stone   bool operator()(const BreakpointLocationSP &bp_loc) const {
51b9c1b51eSKate Stone     return m_break_id == bp_loc->GetBreakpoint().GetID() &&
52b9c1b51eSKate Stone            m_break_loc_id == bp_loc->GetID();
5330fdc8d8SChris Lattner   }
5430fdc8d8SChris Lattner 
5530fdc8d8SChris Lattner private:
56c982c768SGreg Clayton   const lldb::break_id_t m_break_id;
57c982c768SGreg Clayton   const lldb::break_id_t m_break_loc_id;
5830fdc8d8SChris Lattner };
5930fdc8d8SChris Lattner 
6030fdc8d8SChris Lattner BreakpointLocationCollection::collection::iterator
GetIDPairIterator(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)61b9c1b51eSKate Stone BreakpointLocationCollection::GetIDPairIterator(lldb::break_id_t break_id,
62b9c1b51eSKate Stone                                                 lldb::break_id_t break_loc_id) {
63b9c1b51eSKate Stone   return std::find_if(
64b9c1b51eSKate Stone       m_break_loc_collection.begin(),
65b9c1b51eSKate Stone       m_break_loc_collection.end(),                     // Search full range
6630fdc8d8SChris Lattner       BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
6730fdc8d8SChris Lattner }
6830fdc8d8SChris Lattner 
6930fdc8d8SChris Lattner BreakpointLocationCollection::collection::const_iterator
GetIDPairConstIterator(lldb::break_id_t break_id,lldb::break_id_t break_loc_id) const70b9c1b51eSKate Stone BreakpointLocationCollection::GetIDPairConstIterator(
71b9c1b51eSKate Stone     lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
72b9c1b51eSKate Stone   return std::find_if(
73b9c1b51eSKate Stone       m_break_loc_collection.begin(),
74b9c1b51eSKate Stone       m_break_loc_collection.end(),                     // Search full range
7530fdc8d8SChris Lattner       BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
7630fdc8d8SChris Lattner }
7730fdc8d8SChris Lattner 
7830fdc8d8SChris Lattner BreakpointLocationSP
FindByIDPair(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)79b9c1b51eSKate Stone BreakpointLocationCollection::FindByIDPair(lldb::break_id_t break_id,
80b9c1b51eSKate Stone                                            lldb::break_id_t break_loc_id) {
8130fdc8d8SChris Lattner   BreakpointLocationSP stop_sp;
8230fdc8d8SChris Lattner   collection::iterator pos = GetIDPairIterator(break_id, break_loc_id);
8330fdc8d8SChris Lattner   if (pos != m_break_loc_collection.end())
8430fdc8d8SChris Lattner     stop_sp = *pos;
8530fdc8d8SChris Lattner 
8630fdc8d8SChris Lattner   return stop_sp;
8730fdc8d8SChris Lattner }
8830fdc8d8SChris Lattner 
FindByIDPair(lldb::break_id_t break_id,lldb::break_id_t break_loc_id) const89b9c1b51eSKate Stone const BreakpointLocationSP BreakpointLocationCollection::FindByIDPair(
90b9c1b51eSKate Stone     lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
9130fdc8d8SChris Lattner   BreakpointLocationSP stop_sp;
92b9c1b51eSKate Stone   collection::const_iterator pos =
93b9c1b51eSKate Stone       GetIDPairConstIterator(break_id, break_loc_id);
9430fdc8d8SChris Lattner   if (pos != m_break_loc_collection.end())
9530fdc8d8SChris Lattner     stop_sp = *pos;
9630fdc8d8SChris Lattner 
9730fdc8d8SChris Lattner   return stop_sp;
9830fdc8d8SChris Lattner }
9930fdc8d8SChris Lattner 
GetByIndex(size_t i)100b9c1b51eSKate Stone BreakpointLocationSP BreakpointLocationCollection::GetByIndex(size_t i) {
1011cf8f593SJim Ingham   std::lock_guard<std::mutex> guard(m_collection_mutex);
10230fdc8d8SChris Lattner   BreakpointLocationSP stop_sp;
103c982c768SGreg Clayton   if (i < m_break_loc_collection.size())
10430fdc8d8SChris Lattner     stop_sp = m_break_loc_collection[i];
10530fdc8d8SChris Lattner 
10630fdc8d8SChris Lattner   return stop_sp;
10730fdc8d8SChris Lattner }
10830fdc8d8SChris Lattner 
10930fdc8d8SChris Lattner const BreakpointLocationSP
GetByIndex(size_t i) const110b9c1b51eSKate Stone BreakpointLocationCollection::GetByIndex(size_t i) const {
1111cf8f593SJim Ingham   std::lock_guard<std::mutex> guard(m_collection_mutex);
11230fdc8d8SChris Lattner   BreakpointLocationSP stop_sp;
113c982c768SGreg Clayton   if (i < m_break_loc_collection.size())
11430fdc8d8SChris Lattner     stop_sp = m_break_loc_collection[i];
11530fdc8d8SChris Lattner 
11630fdc8d8SChris Lattner   return stop_sp;
11730fdc8d8SChris Lattner }
11830fdc8d8SChris Lattner 
ShouldStop(StoppointCallbackContext * context)119b9c1b51eSKate Stone bool BreakpointLocationCollection::ShouldStop(
120b9c1b51eSKate Stone     StoppointCallbackContext *context) {
12130fdc8d8SChris Lattner   bool shouldStop = false;
122729dcfb7STamas Berghammer   size_t i = 0;
123729dcfb7STamas Berghammer   size_t prev_size = GetSize();
124b9c1b51eSKate Stone   while (i < prev_size) {
125*635f03feSJim Ingham     // ShouldStop can remove the breakpoint from the list, or even delete
126*635f03feSJim Ingham     // it, so we should
127*635f03feSJim Ingham     BreakpointLocationSP cur_loc_sp = GetByIndex(i);
128*635f03feSJim Ingham     BreakpointSP keep_bkpt_alive_sp = cur_loc_sp->GetBreakpoint().shared_from_this();
129*635f03feSJim Ingham     if (cur_loc_sp->ShouldStop(context))
13030fdc8d8SChris Lattner       shouldStop = true;
131729dcfb7STamas Berghammer 
132729dcfb7STamas Berghammer     if (prev_size == GetSize())
133729dcfb7STamas Berghammer       i++;
134729dcfb7STamas Berghammer     prev_size = GetSize();
13530fdc8d8SChris Lattner   }
13630fdc8d8SChris Lattner   return shouldStop;
13730fdc8d8SChris Lattner }
13830fdc8d8SChris Lattner 
ValidForThisThread(Thread & thread)139cfb96d84SJim Ingham bool BreakpointLocationCollection::ValidForThisThread(Thread &thread) {
1401cf8f593SJim Ingham   std::lock_guard<std::mutex> guard(m_collection_mutex);
141b9c1b51eSKate Stone   collection::iterator pos, begin = m_break_loc_collection.begin(),
1421b54c88cSJim Ingham                             end = m_break_loc_collection.end();
1431b54c88cSJim Ingham 
144b9c1b51eSKate Stone   for (pos = begin; pos != end; ++pos) {
1451b54c88cSJim Ingham     if ((*pos)->ValidForThisThread(thread))
1461b54c88cSJim Ingham       return true;
1471b54c88cSJim Ingham   }
1481b54c88cSJim Ingham   return false;
1491b54c88cSJim Ingham }
1501b54c88cSJim Ingham 
IsInternal() const151b9c1b51eSKate Stone bool BreakpointLocationCollection::IsInternal() const {
1521cf8f593SJim Ingham   std::lock_guard<std::mutex> guard(m_collection_mutex);
153b9c1b51eSKate Stone   collection::const_iterator pos, begin = m_break_loc_collection.begin(),
1542995077dSJim Ingham                                   end = m_break_loc_collection.end();
1552995077dSJim Ingham 
1562995077dSJim Ingham   bool is_internal = true;
1572995077dSJim Ingham 
158b9c1b51eSKate Stone   for (pos = begin; pos != end; ++pos) {
159b9c1b51eSKate Stone     if (!(*pos)->GetBreakpoint().IsInternal()) {
1602995077dSJim Ingham       is_internal = false;
1612995077dSJim Ingham       break;
1622995077dSJim Ingham     }
1632995077dSJim Ingham   }
1642995077dSJim Ingham   return is_internal;
1652995077dSJim Ingham }
1661b54c88cSJim Ingham 
GetDescription(Stream * s,lldb::DescriptionLevel level)167b9c1b51eSKate Stone void BreakpointLocationCollection::GetDescription(
168b9c1b51eSKate Stone     Stream *s, lldb::DescriptionLevel level) {
1691cf8f593SJim Ingham   std::lock_guard<std::mutex> guard(m_collection_mutex);
170b9c1b51eSKate Stone   collection::iterator pos, begin = m_break_loc_collection.begin(),
17130fdc8d8SChris Lattner                             end = m_break_loc_collection.end();
17230fdc8d8SChris Lattner 
173b9c1b51eSKate Stone   for (pos = begin; pos != end; ++pos) {
17430fdc8d8SChris Lattner     if (pos != begin)
17530fdc8d8SChris Lattner       s->PutChar(' ');
17630fdc8d8SChris Lattner     (*pos)->GetDescription(s, level);
17730fdc8d8SChris Lattner   }
17830fdc8d8SChris Lattner }
1791432b978SJim Ingham 
operator =(const BreakpointLocationCollection & rhs)1801432b978SJim Ingham BreakpointLocationCollection &BreakpointLocationCollection::operator=(
1811432b978SJim Ingham     const BreakpointLocationCollection &rhs) {
1821432b978SJim Ingham   if (this != &rhs) {
183cdd4892fSJim Ingham       std::lock(m_collection_mutex, rhs.m_collection_mutex);
184cdd4892fSJim Ingham       std::lock_guard<std::mutex> lhs_guard(m_collection_mutex, std::adopt_lock);
185cdd4892fSJim Ingham       std::lock_guard<std::mutex> rhs_guard(rhs.m_collection_mutex, std::adopt_lock);
1861432b978SJim Ingham       m_break_loc_collection = rhs.m_break_loc_collection;
1871432b978SJim Ingham   }
1881432b978SJim Ingham   return *this;
1891432b978SJim Ingham }
190