BreakpointSiteList.cpp revision 341825
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/Utility/Stream.h" 17#include <algorithm> 18 19using namespace lldb; 20using namespace lldb_private; 21 22BreakpointSiteList::BreakpointSiteList() : m_mutex(), m_bp_site_list() {} 23 24BreakpointSiteList::~BreakpointSiteList() {} 25 26// Add breakpoint site to the list. However, if the element already exists in 27// the list, then we don't add it, and return LLDB_INVALID_BREAK_ID. 28 29lldb::break_id_t BreakpointSiteList::Add(const BreakpointSiteSP &bp) { 30 lldb::addr_t bp_site_load_addr = bp->GetLoadAddress(); 31 std::lock_guard<std::recursive_mutex> guard(m_mutex); 32 collection::iterator iter = m_bp_site_list.find(bp_site_load_addr); 33 34 if (iter == m_bp_site_list.end()) { 35 m_bp_site_list.insert(iter, collection::value_type(bp_site_load_addr, bp)); 36 return bp->GetID(); 37 } else { 38 return LLDB_INVALID_BREAK_ID; 39 } 40} 41 42bool BreakpointSiteList::ShouldStop(StoppointCallbackContext *context, 43 lldb::break_id_t site_id) { 44 BreakpointSiteSP site_sp(FindByID(site_id)); 45 if (site_sp) { 46 // Let the BreakpointSite decide if it should stop here (could not have 47 // reached it's target hit count yet, or it could have a callback that 48 // decided it shouldn't stop (shared library loads/unloads). 49 return site_sp->ShouldStop(context); 50 } 51 // We should stop here since this BreakpointSite isn't valid anymore or it 52 // doesn't exist. 53 return true; 54} 55lldb::break_id_t BreakpointSiteList::FindIDByAddress(lldb::addr_t addr) { 56 BreakpointSiteSP bp = FindByAddress(addr); 57 if (bp) { 58 // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" 59 // PRIx64 " ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID()); 60 return bp.get()->GetID(); 61 } 62 // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" 63 // PRIx64 64 // " ) => NONE", __FUNCTION__, (uint64_t)addr); 65 return LLDB_INVALID_BREAK_ID; 66} 67 68bool 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 78bool 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 88class BreakpointSiteIDMatches { 89public: 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 96private: 97 const lldb::break_id_t m_break_id; 98}; 99 100BreakpointSiteList::collection::iterator 101BreakpointSiteList::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 108BreakpointSiteList::collection::const_iterator 109BreakpointSiteList::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 116BreakpointSiteSP 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 126const BreakpointSiteSP 127BreakpointSiteList::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 137BreakpointSiteSP 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 146bool 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 156void 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 169void 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 176bool 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 189 // the range. So we grab the breakpoint prior to the lower bound, and check 190 // that that + its byte size isn't in our range. 191 if (lower != m_bp_site_list.begin()) { 192 collection::const_iterator prev_pos = lower; 193 prev_pos--; 194 const BreakpointSiteSP &prev_bp = (*prev_pos).second; 195 if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound) 196 bp_site_list.Add(prev_bp); 197 } 198 199 upper = m_bp_site_list.upper_bound(upper_bound); 200 201 for (pos = lower; pos != upper; pos++) { 202 bp_site_list.Add((*pos).second); 203 } 204 return true; 205} 206