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