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