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() : 23 m_bp_site_list() 24 { 25 } 26 27 BreakpointSiteList::~BreakpointSiteList() 28 { 29 } 30 31 // Add breakpoint site to the list. However, if the element already exists in the 32 // list, then we don't add it, and return LLDB_INVALID_BREAK_ID. 33 34 lldb::break_id_t 35 BreakpointSiteList::Add(const BreakpointSiteSP &bp) 36 { 37 lldb::addr_t bp_site_load_addr = bp->GetLoadAddress(); 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 collection::iterator pos = GetIDIterator(break_id); // Predicate 83 if (pos != m_bp_site_list.end()) 84 { 85 m_bp_site_list.erase(pos); 86 return true; 87 } 88 return false; 89 } 90 91 bool 92 BreakpointSiteList::RemoveByAddress (lldb::addr_t address) 93 { 94 collection::iterator pos = m_bp_site_list.find(address); 95 if (pos != m_bp_site_list.end()) 96 { 97 m_bp_site_list.erase(pos); 98 return true; 99 } 100 return false; 101 } 102 103 class BreakpointSiteIDMatches 104 { 105 public: 106 BreakpointSiteIDMatches (lldb::break_id_t break_id) : 107 m_break_id(break_id) 108 { 109 } 110 111 bool operator() (std::pair <lldb::addr_t, BreakpointSiteSP> val_pair) const 112 { 113 return m_break_id == val_pair.second.get()->GetID(); 114 } 115 116 private: 117 const lldb::break_id_t m_break_id; 118 }; 119 120 BreakpointSiteList::collection::iterator 121 BreakpointSiteList::GetIDIterator (lldb::break_id_t break_id) 122 { 123 return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range 124 BreakpointSiteIDMatches(break_id)); // Predicate 125 } 126 127 BreakpointSiteList::collection::const_iterator 128 BreakpointSiteList::GetIDConstIterator (lldb::break_id_t break_id) const 129 { 130 return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range 131 BreakpointSiteIDMatches(break_id)); // Predicate 132 } 133 134 BreakpointSiteSP 135 BreakpointSiteList::FindByID (lldb::break_id_t break_id) 136 { 137 BreakpointSiteSP stop_sp; 138 collection::iterator pos = GetIDIterator(break_id); 139 if (pos != m_bp_site_list.end()) 140 stop_sp = pos->second; 141 142 return stop_sp; 143 } 144 145 const BreakpointSiteSP 146 BreakpointSiteList::FindByID (lldb::break_id_t break_id) const 147 { 148 BreakpointSiteSP stop_sp; 149 collection::const_iterator pos = GetIDConstIterator(break_id); 150 if (pos != m_bp_site_list.end()) 151 stop_sp = pos->second; 152 153 return stop_sp; 154 } 155 156 BreakpointSiteSP 157 BreakpointSiteList::FindByAddress (lldb::addr_t addr) 158 { 159 BreakpointSiteSP found_sp; 160 161 collection::iterator iter = m_bp_site_list.find(addr); 162 if (iter != m_bp_site_list.end()) 163 found_sp = iter->second; 164 return found_sp; 165 } 166 167 bool 168 BreakpointSiteList::BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id) 169 { 170 collection::const_iterator pos = GetIDConstIterator(bp_site_id); 171 if (pos != m_bp_site_list.end()) 172 pos->second->IsBreakpointAtThisSite (bp_id); 173 174 return false; 175 } 176 177 void 178 BreakpointSiteList::Dump (Stream *s) const 179 { 180 s->Printf("%p: ", this); 181 //s->Indent(); 182 s->Printf("BreakpointSiteList with %u BreakpointSites:\n", (uint32_t)m_bp_site_list.size()); 183 s->IndentMore(); 184 collection::const_iterator pos; 185 collection::const_iterator end = m_bp_site_list.end(); 186 for (pos = m_bp_site_list.begin(); pos != end; ++pos) 187 pos->second.get()->Dump(s); 188 s->IndentLess(); 189 } 190 191 192 BreakpointSiteSP 193 BreakpointSiteList::GetByIndex (uint32_t i) 194 { 195 BreakpointSiteSP stop_sp; 196 collection::iterator end = m_bp_site_list.end(); 197 collection::iterator pos; 198 uint32_t curr_i = 0; 199 for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) 200 { 201 if (curr_i == i) 202 stop_sp = pos->second; 203 } 204 return stop_sp; 205 } 206 207 const BreakpointSiteSP 208 BreakpointSiteList::GetByIndex (uint32_t i) const 209 { 210 BreakpointSiteSP stop_sp; 211 collection::const_iterator end = m_bp_site_list.end(); 212 collection::const_iterator pos; 213 uint32_t curr_i = 0; 214 for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) 215 { 216 if (curr_i == i) 217 stop_sp = pos->second; 218 } 219 return stop_sp; 220 } 221 222 bool 223 BreakpointSiteList::FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const 224 { 225 226 if (lower_bound > upper_bound) 227 return false; 228 229 collection::const_iterator lower, upper, pos; 230 lower = m_bp_site_list.lower_bound(lower_bound); 231 if (lower == m_bp_site_list.end() 232 || (*lower).first >= upper_bound) 233 return false; 234 235 // This is one tricky bit. The breakpoint might overlap the bottom end of the range. So we grab the 236 // breakpoint prior to the lower bound, and check that that + its byte size isn't in our range. 237 if (lower != m_bp_site_list.begin()) 238 { 239 collection::const_iterator prev_pos = lower; 240 prev_pos--; 241 const BreakpointSiteSP &prev_bp = (*prev_pos).second; 242 if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound) 243 bp_site_list.Add (prev_bp); 244 245 } 246 247 upper = m_bp_site_list.upper_bound(upper_bound); 248 249 for (pos = lower; pos != upper; pos++) 250 { 251 bp_site_list.Add ((*pos).second); 252 } 253 return true; 254 } 255 256 257 void 258 BreakpointSiteList::SetEnabledForAll (const bool enabled, const lldb::break_id_t except_id) 259 { 260 collection::iterator end = m_bp_site_list.end(); 261 collection::iterator pos; 262 for (pos = m_bp_site_list.begin(); pos != end; ++pos) 263 { 264 if (except_id != LLDB_INVALID_BREAK_ID && except_id != pos->second->GetID()) 265 pos->second->SetEnabled (enabled); 266 else 267 pos->second->SetEnabled (!enabled); 268 } 269 } 270 271 const BreakpointSiteList::collection * 272 BreakpointSiteList::GetMap () 273 { 274 return &m_bp_site_list; 275 } 276