1 //===-- BreakpointSiteList.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/BreakpointSiteList.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/Stream.h" 17 #include <algorithm> 18 19 using namespace lldb; 20 using namespace lldb_private; 21 22 BreakpointSiteList::BreakpointSiteList() : m_mutex(), m_bp_site_list() {} 23 24 BreakpointSiteList::~BreakpointSiteList() {} 25 26 // Add breakpoint site to the list. However, if the element already exists in 27 // the 28 // list, then we don't add it, and return LLDB_INVALID_BREAK_ID. 29 30 lldb::break_id_t BreakpointSiteList::Add(const BreakpointSiteSP &bp) { 31 lldb::addr_t bp_site_load_addr = bp->GetLoadAddress(); 32 std::lock_guard<std::recursive_mutex> guard(m_mutex); 33 collection::iterator iter = m_bp_site_list.find(bp_site_load_addr); 34 35 if (iter == m_bp_site_list.end()) { 36 m_bp_site_list.insert(iter, collection::value_type(bp_site_load_addr, bp)); 37 return bp->GetID(); 38 } else { 39 return LLDB_INVALID_BREAK_ID; 40 } 41 } 42 43 bool BreakpointSiteList::ShouldStop(StoppointCallbackContext *context, 44 lldb::break_id_t site_id) { 45 BreakpointSiteSP site_sp(FindByID(site_id)); 46 if (site_sp) { 47 // Let the BreakpointSite decide if it should stop here (could not have 48 // reached it's target hit count yet, or it could have a callback 49 // that decided it shouldn't stop (shared library loads/unloads). 50 return site_sp->ShouldStop(context); 51 } 52 // We should stop here since this BreakpointSite isn't valid anymore or it 53 // doesn't exist. 54 return true; 55 } 56 lldb::break_id_t BreakpointSiteList::FindIDByAddress(lldb::addr_t addr) { 57 BreakpointSiteSP bp = FindByAddress(addr); 58 if (bp) { 59 // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" 60 // PRIx64 " ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID()); 61 return bp.get()->GetID(); 62 } 63 // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" PRIx64 64 // " ) => NONE", __FUNCTION__, (uint64_t)addr); 65 return LLDB_INVALID_BREAK_ID; 66 } 67 68 bool BreakpointSiteList::Remove(lldb::break_id_t break_id) { 69 std::lock_guard<std::recursive_mutex> guard(m_mutex); 70 collection::iterator pos = GetIDIterator(break_id); // Predicate 71 if (pos != m_bp_site_list.end()) { 72 m_bp_site_list.erase(pos); 73 return true; 74 } 75 return false; 76 } 77 78 bool BreakpointSiteList::RemoveByAddress(lldb::addr_t address) { 79 std::lock_guard<std::recursive_mutex> guard(m_mutex); 80 collection::iterator pos = m_bp_site_list.find(address); 81 if (pos != m_bp_site_list.end()) { 82 m_bp_site_list.erase(pos); 83 return true; 84 } 85 return false; 86 } 87 88 class BreakpointSiteIDMatches { 89 public: 90 BreakpointSiteIDMatches(lldb::break_id_t break_id) : m_break_id(break_id) {} 91 92 bool operator()(std::pair<lldb::addr_t, BreakpointSiteSP> val_pair) const { 93 return m_break_id == val_pair.second.get()->GetID(); 94 } 95 96 private: 97 const lldb::break_id_t m_break_id; 98 }; 99 100 BreakpointSiteList::collection::iterator 101 BreakpointSiteList::GetIDIterator(lldb::break_id_t break_id) { 102 std::lock_guard<std::recursive_mutex> guard(m_mutex); 103 return std::find_if(m_bp_site_list.begin(), 104 m_bp_site_list.end(), // Search full range 105 BreakpointSiteIDMatches(break_id)); // Predicate 106 } 107 108 BreakpointSiteList::collection::const_iterator 109 BreakpointSiteList::GetIDConstIterator(lldb::break_id_t break_id) const { 110 std::lock_guard<std::recursive_mutex> guard(m_mutex); 111 return std::find_if(m_bp_site_list.begin(), 112 m_bp_site_list.end(), // Search full range 113 BreakpointSiteIDMatches(break_id)); // Predicate 114 } 115 116 BreakpointSiteSP BreakpointSiteList::FindByID(lldb::break_id_t break_id) { 117 std::lock_guard<std::recursive_mutex> guard(m_mutex); 118 BreakpointSiteSP stop_sp; 119 collection::iterator pos = GetIDIterator(break_id); 120 if (pos != m_bp_site_list.end()) 121 stop_sp = pos->second; 122 123 return stop_sp; 124 } 125 126 const BreakpointSiteSP 127 BreakpointSiteList::FindByID(lldb::break_id_t break_id) const { 128 std::lock_guard<std::recursive_mutex> guard(m_mutex); 129 BreakpointSiteSP stop_sp; 130 collection::const_iterator pos = GetIDConstIterator(break_id); 131 if (pos != m_bp_site_list.end()) 132 stop_sp = pos->second; 133 134 return stop_sp; 135 } 136 137 BreakpointSiteSP BreakpointSiteList::FindByAddress(lldb::addr_t addr) { 138 BreakpointSiteSP found_sp; 139 std::lock_guard<std::recursive_mutex> guard(m_mutex); 140 collection::iterator iter = m_bp_site_list.find(addr); 141 if (iter != m_bp_site_list.end()) 142 found_sp = iter->second; 143 return found_sp; 144 } 145 146 bool BreakpointSiteList::BreakpointSiteContainsBreakpoint( 147 lldb::break_id_t bp_site_id, lldb::break_id_t bp_id) { 148 std::lock_guard<std::recursive_mutex> guard(m_mutex); 149 collection::const_iterator pos = GetIDConstIterator(bp_site_id); 150 if (pos != m_bp_site_list.end()) 151 return pos->second->IsBreakpointAtThisSite(bp_id); 152 153 return false; 154 } 155 156 void BreakpointSiteList::Dump(Stream *s) const { 157 s->Printf("%p: ", static_cast<const void *>(this)); 158 // s->Indent(); 159 s->Printf("BreakpointSiteList with %u BreakpointSites:\n", 160 (uint32_t)m_bp_site_list.size()); 161 s->IndentMore(); 162 collection::const_iterator pos; 163 collection::const_iterator end = m_bp_site_list.end(); 164 for (pos = m_bp_site_list.begin(); pos != end; ++pos) 165 pos->second.get()->Dump(s); 166 s->IndentLess(); 167 } 168 169 void BreakpointSiteList::ForEach( 170 std::function<void(BreakpointSite *)> const &callback) { 171 std::lock_guard<std::recursive_mutex> guard(m_mutex); 172 for (auto pair : m_bp_site_list) 173 callback(pair.second.get()); 174 } 175 176 bool BreakpointSiteList::FindInRange(lldb::addr_t lower_bound, 177 lldb::addr_t upper_bound, 178 BreakpointSiteList &bp_site_list) const { 179 if (lower_bound > upper_bound) 180 return false; 181 182 std::lock_guard<std::recursive_mutex> guard(m_mutex); 183 collection::const_iterator lower, upper, pos; 184 lower = m_bp_site_list.lower_bound(lower_bound); 185 if (lower == m_bp_site_list.end() || (*lower).first >= upper_bound) 186 return false; 187 188 // This is one tricky bit. The breakpoint might overlap the bottom end of the 189 // range. So we grab the 190 // breakpoint prior to the lower bound, and check that that + its byte size 191 // isn't in our range. 192 if (lower != m_bp_site_list.begin()) { 193 collection::const_iterator prev_pos = lower; 194 prev_pos--; 195 const BreakpointSiteSP &prev_bp = (*prev_pos).second; 196 if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound) 197 bp_site_list.Add(prev_bp); 198 } 199 200 upper = m_bp_site_list.upper_bound(upper_bound); 201 202 for (pos = lower; pos != upper; pos++) { 203 bp_site_list.Add((*pos).second); 204 } 205 return true; 206 } 207