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() = default; 21 22 // Destructor 23 BreakpointLocationCollection::~BreakpointLocationCollection() = default; 24 25 void BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc) { 26 std::lock_guard<std::mutex> guard(m_collection_mutex); 27 BreakpointLocationSP old_bp_loc = 28 FindByIDPair(bp_loc->GetBreakpoint().GetID(), bp_loc->GetID()); 29 if (!old_bp_loc.get()) 30 m_break_loc_collection.push_back(bp_loc); 31 } 32 33 bool BreakpointLocationCollection::Remove(lldb::break_id_t bp_id, 34 lldb::break_id_t bp_loc_id) { 35 std::lock_guard<std::mutex> guard(m_collection_mutex); 36 collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id); // Predicate 37 if (pos != m_break_loc_collection.end()) { 38 m_break_loc_collection.erase(pos); 39 return true; 40 } 41 return false; 42 } 43 44 class BreakpointIDPairMatches { 45 public: 46 BreakpointIDPairMatches(lldb::break_id_t break_id, 47 lldb::break_id_t break_loc_id) 48 : m_break_id(break_id), m_break_loc_id(break_loc_id) {} 49 50 bool operator()(const BreakpointLocationSP &bp_loc) const { 51 return m_break_id == bp_loc->GetBreakpoint().GetID() && 52 m_break_loc_id == bp_loc->GetID(); 53 } 54 55 private: 56 const lldb::break_id_t m_break_id; 57 const lldb::break_id_t m_break_loc_id; 58 }; 59 60 BreakpointLocationCollection::collection::iterator 61 BreakpointLocationCollection::GetIDPairIterator(lldb::break_id_t break_id, 62 lldb::break_id_t break_loc_id) { 63 return std::find_if( 64 m_break_loc_collection.begin(), 65 m_break_loc_collection.end(), // Search full range 66 BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate 67 } 68 69 BreakpointLocationCollection::collection::const_iterator 70 BreakpointLocationCollection::GetIDPairConstIterator( 71 lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const { 72 return std::find_if( 73 m_break_loc_collection.begin(), 74 m_break_loc_collection.end(), // Search full range 75 BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate 76 } 77 78 BreakpointLocationSP 79 BreakpointLocationCollection::FindByIDPair(lldb::break_id_t break_id, 80 lldb::break_id_t break_loc_id) { 81 BreakpointLocationSP stop_sp; 82 collection::iterator pos = GetIDPairIterator(break_id, break_loc_id); 83 if (pos != m_break_loc_collection.end()) 84 stop_sp = *pos; 85 86 return stop_sp; 87 } 88 89 const BreakpointLocationSP BreakpointLocationCollection::FindByIDPair( 90 lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const { 91 BreakpointLocationSP stop_sp; 92 collection::const_iterator pos = 93 GetIDPairConstIterator(break_id, break_loc_id); 94 if (pos != m_break_loc_collection.end()) 95 stop_sp = *pos; 96 97 return stop_sp; 98 } 99 100 BreakpointLocationSP BreakpointLocationCollection::GetByIndex(size_t i) { 101 std::lock_guard<std::mutex> guard(m_collection_mutex); 102 BreakpointLocationSP stop_sp; 103 if (i < m_break_loc_collection.size()) 104 stop_sp = m_break_loc_collection[i]; 105 106 return stop_sp; 107 } 108 109 const BreakpointLocationSP 110 BreakpointLocationCollection::GetByIndex(size_t i) const { 111 std::lock_guard<std::mutex> guard(m_collection_mutex); 112 BreakpointLocationSP stop_sp; 113 if (i < m_break_loc_collection.size()) 114 stop_sp = m_break_loc_collection[i]; 115 116 return stop_sp; 117 } 118 119 bool BreakpointLocationCollection::ShouldStop( 120 StoppointCallbackContext *context) { 121 bool shouldStop = false; 122 size_t i = 0; 123 size_t prev_size = GetSize(); 124 while (i < prev_size) { 125 // ShouldStop can remove the breakpoint from the list, or even delete 126 // it, so we should 127 BreakpointLocationSP cur_loc_sp = GetByIndex(i); 128 BreakpointSP keep_bkpt_alive_sp = cur_loc_sp->GetBreakpoint().shared_from_this(); 129 if (cur_loc_sp->ShouldStop(context)) 130 shouldStop = true; 131 132 if (prev_size == GetSize()) 133 i++; 134 prev_size = GetSize(); 135 } 136 return shouldStop; 137 } 138 139 bool BreakpointLocationCollection::ValidForThisThread(Thread &thread) { 140 std::lock_guard<std::mutex> guard(m_collection_mutex); 141 collection::iterator pos, begin = m_break_loc_collection.begin(), 142 end = m_break_loc_collection.end(); 143 144 for (pos = begin; pos != end; ++pos) { 145 if ((*pos)->ValidForThisThread(thread)) 146 return true; 147 } 148 return false; 149 } 150 151 bool BreakpointLocationCollection::IsInternal() const { 152 std::lock_guard<std::mutex> guard(m_collection_mutex); 153 collection::const_iterator pos, begin = m_break_loc_collection.begin(), 154 end = m_break_loc_collection.end(); 155 156 bool is_internal = true; 157 158 for (pos = begin; pos != end; ++pos) { 159 if (!(*pos)->GetBreakpoint().IsInternal()) { 160 is_internal = false; 161 break; 162 } 163 } 164 return is_internal; 165 } 166 167 void BreakpointLocationCollection::GetDescription( 168 Stream *s, lldb::DescriptionLevel level) { 169 std::lock_guard<std::mutex> guard(m_collection_mutex); 170 collection::iterator pos, begin = m_break_loc_collection.begin(), 171 end = m_break_loc_collection.end(); 172 173 for (pos = begin; pos != end; ++pos) { 174 if (pos != begin) 175 s->PutChar(' '); 176 (*pos)->GetDescription(s, level); 177 } 178 } 179 180 BreakpointLocationCollection &BreakpointLocationCollection::operator=( 181 const BreakpointLocationCollection &rhs) { 182 if (this != &rhs) { 183 std::lock(m_collection_mutex, rhs.m_collection_mutex); 184 std::lock_guard<std::mutex> lhs_guard(m_collection_mutex, std::adopt_lock); 185 std::lock_guard<std::mutex> rhs_guard(rhs.m_collection_mutex, std::adopt_lock); 186 m_break_loc_collection = rhs.m_break_loc_collection; 187 } 188 return *this; 189 } 190