1 //===-- BreakpointLocationCollection.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/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 20 BreakpointLocationCollection::BreakpointLocationCollection() 21 : m_break_loc_collection(), m_collection_mutex() {} 22 23 // Destructor 24 BreakpointLocationCollection::~BreakpointLocationCollection() = default; 25 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 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: 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 51 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 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 71 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 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 90 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 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 111 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 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 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 149 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 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 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