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 16using namespace lldb; 17using namespace lldb_private; 18 19// BreakpointLocationCollection constructor 20BreakpointLocationCollection::BreakpointLocationCollection() 21 : m_break_loc_collection(), m_collection_mutex() {} 22 23// Destructor 24BreakpointLocationCollection::~BreakpointLocationCollection() {} 25 26void 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 34bool 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 45class BreakpointIDPairMatches { 46public: 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 56private: 57 const lldb::break_id_t m_break_id; 58 const lldb::break_id_t m_break_loc_id; 59}; 60 61BreakpointLocationCollection::collection::iterator 62BreakpointLocationCollection::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 70BreakpointLocationCollection::collection::const_iterator 71BreakpointLocationCollection::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 79BreakpointLocationSP 80BreakpointLocationCollection::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 90const 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 101BreakpointLocationSP 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 110const BreakpointLocationSP 111BreakpointLocationCollection::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 120bool 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 137bool 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 149bool 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 165void 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 178BreakpointLocationCollection &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