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