1 //===-- BreakpointLocationCollection.cpp ------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Breakpoint/BreakpointLocationCollection.h" 11 #include "lldb/Breakpoint/Breakpoint.h" 12 #include "lldb/Breakpoint/BreakpointLocation.h" 13 #include "lldb/Core/ModuleList.h" 14 #include "lldb/Target/Thread.h" 15 #include "lldb/Target/ThreadSpec.h" 16 17 using namespace lldb; 18 using namespace lldb_private; 19 20 //---------------------------------------------------------------------- 21 // BreakpointLocationCollection constructor 22 //---------------------------------------------------------------------- 23 BreakpointLocationCollection::BreakpointLocationCollection() 24 : m_break_loc_collection(), m_collection_mutex() {} 25 26 //---------------------------------------------------------------------- 27 // Destructor 28 //---------------------------------------------------------------------- 29 BreakpointLocationCollection::~BreakpointLocationCollection() {} 30 31 void BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc) { 32 std::lock_guard<std::mutex> guard(m_collection_mutex); 33 BreakpointLocationSP old_bp_loc = 34 FindByIDPair(bp_loc->GetBreakpoint().GetID(), bp_loc->GetID()); 35 if (!old_bp_loc.get()) 36 m_break_loc_collection.push_back(bp_loc); 37 } 38 39 bool BreakpointLocationCollection::Remove(lldb::break_id_t bp_id, 40 lldb::break_id_t bp_loc_id) { 41 std::lock_guard<std::mutex> guard(m_collection_mutex); 42 collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id); // Predicate 43 if (pos != m_break_loc_collection.end()) { 44 m_break_loc_collection.erase(pos); 45 return true; 46 } 47 return false; 48 } 49 50 class BreakpointIDPairMatches { 51 public: 52 BreakpointIDPairMatches(lldb::break_id_t break_id, 53 lldb::break_id_t break_loc_id) 54 : m_break_id(break_id), m_break_loc_id(break_loc_id) {} 55 56 bool operator()(const BreakpointLocationSP &bp_loc) const { 57 return m_break_id == bp_loc->GetBreakpoint().GetID() && 58 m_break_loc_id == bp_loc->GetID(); 59 } 60 61 private: 62 const lldb::break_id_t m_break_id; 63 const lldb::break_id_t m_break_loc_id; 64 }; 65 66 BreakpointLocationCollection::collection::iterator 67 BreakpointLocationCollection::GetIDPairIterator(lldb::break_id_t break_id, 68 lldb::break_id_t break_loc_id) { 69 return std::find_if( 70 m_break_loc_collection.begin(), 71 m_break_loc_collection.end(), // Search full range 72 BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate 73 } 74 75 BreakpointLocationCollection::collection::const_iterator 76 BreakpointLocationCollection::GetIDPairConstIterator( 77 lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const { 78 return std::find_if( 79 m_break_loc_collection.begin(), 80 m_break_loc_collection.end(), // Search full range 81 BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate 82 } 83 84 BreakpointLocationSP 85 BreakpointLocationCollection::FindByIDPair(lldb::break_id_t break_id, 86 lldb::break_id_t break_loc_id) { 87 BreakpointLocationSP stop_sp; 88 collection::iterator pos = GetIDPairIterator(break_id, break_loc_id); 89 if (pos != m_break_loc_collection.end()) 90 stop_sp = *pos; 91 92 return stop_sp; 93 } 94 95 const BreakpointLocationSP BreakpointLocationCollection::FindByIDPair( 96 lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const { 97 BreakpointLocationSP stop_sp; 98 collection::const_iterator pos = 99 GetIDPairConstIterator(break_id, break_loc_id); 100 if (pos != m_break_loc_collection.end()) 101 stop_sp = *pos; 102 103 return stop_sp; 104 } 105 106 BreakpointLocationSP BreakpointLocationCollection::GetByIndex(size_t i) { 107 std::lock_guard<std::mutex> guard(m_collection_mutex); 108 BreakpointLocationSP stop_sp; 109 if (i < m_break_loc_collection.size()) 110 stop_sp = m_break_loc_collection[i]; 111 112 return stop_sp; 113 } 114 115 const BreakpointLocationSP 116 BreakpointLocationCollection::GetByIndex(size_t i) const { 117 std::lock_guard<std::mutex> guard(m_collection_mutex); 118 BreakpointLocationSP stop_sp; 119 if (i < m_break_loc_collection.size()) 120 stop_sp = m_break_loc_collection[i]; 121 122 return stop_sp; 123 } 124 125 bool BreakpointLocationCollection::ShouldStop( 126 StoppointCallbackContext *context) { 127 bool shouldStop = false; 128 size_t i = 0; 129 size_t prev_size = GetSize(); 130 while (i < prev_size) { 131 // ShouldStop can remove the breakpoint from the list 132 if (GetByIndex(i)->ShouldStop(context)) 133 shouldStop = true; 134 135 if (prev_size == GetSize()) 136 i++; 137 prev_size = GetSize(); 138 } 139 return shouldStop; 140 } 141 142 bool BreakpointLocationCollection::ValidForThisThread(Thread *thread) { 143 std::lock_guard<std::mutex> guard(m_collection_mutex); 144 collection::iterator pos, begin = m_break_loc_collection.begin(), 145 end = m_break_loc_collection.end(); 146 147 for (pos = begin; pos != end; ++pos) { 148 if ((*pos)->ValidForThisThread(thread)) 149 return true; 150 } 151 return false; 152 } 153 154 bool BreakpointLocationCollection::IsInternal() const { 155 std::lock_guard<std::mutex> guard(m_collection_mutex); 156 collection::const_iterator pos, begin = m_break_loc_collection.begin(), 157 end = m_break_loc_collection.end(); 158 159 bool is_internal = true; 160 161 for (pos = begin; pos != end; ++pos) { 162 if (!(*pos)->GetBreakpoint().IsInternal()) { 163 is_internal = false; 164 break; 165 } 166 } 167 return is_internal; 168 } 169 170 void BreakpointLocationCollection::GetDescription( 171 Stream *s, lldb::DescriptionLevel level) { 172 std::lock_guard<std::mutex> guard(m_collection_mutex); 173 collection::iterator pos, begin = m_break_loc_collection.begin(), 174 end = m_break_loc_collection.end(); 175 176 for (pos = begin; pos != end; ++pos) { 177 if (pos != begin) 178 s->PutChar(' '); 179 (*pos)->GetDescription(s, level); 180 } 181 } 182