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.8llx ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID()); 73 return bp.get()->GetID(); 74 } 75 //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8llx ) => 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 void 168 BreakpointSiteList::Dump (Stream *s) const 169 { 170 s->Printf("%p: ", this); 171 //s->Indent(); 172 s->Printf("BreakpointSiteList with %u BreakpointSites:\n", (uint32_t)m_bp_site_list.size()); 173 s->IndentMore(); 174 collection::const_iterator pos; 175 collection::const_iterator end = m_bp_site_list.end(); 176 for (pos = m_bp_site_list.begin(); pos != end; ++pos) 177 pos->second.get()->Dump(s); 178 s->IndentLess(); 179 } 180 181 182 BreakpointSiteSP 183 BreakpointSiteList::GetByIndex (uint32_t i) 184 { 185 BreakpointSiteSP stop_sp; 186 collection::iterator end = m_bp_site_list.end(); 187 collection::iterator pos; 188 uint32_t curr_i = 0; 189 for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) 190 { 191 if (curr_i == i) 192 stop_sp = pos->second; 193 } 194 return stop_sp; 195 } 196 197 const BreakpointSiteSP 198 BreakpointSiteList::GetByIndex (uint32_t i) const 199 { 200 BreakpointSiteSP stop_sp; 201 collection::const_iterator end = m_bp_site_list.end(); 202 collection::const_iterator pos; 203 uint32_t curr_i = 0; 204 for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) 205 { 206 if (curr_i == i) 207 stop_sp = pos->second; 208 } 209 return stop_sp; 210 } 211 212 bool 213 BreakpointSiteList::FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const 214 { 215 216 if (lower_bound > upper_bound) 217 return false; 218 219 collection::const_iterator lower, upper, pos; 220 lower = m_bp_site_list.lower_bound(lower_bound); 221 if (lower == m_bp_site_list.end() 222 || (*lower).first >= upper_bound) 223 return false; 224 225 // This is one tricky bit. The breakpoint might overlap the bottom end of the range. So we grab the 226 // breakpoint prior to the lower bound, and check that that + its byte size isn't in our range. 227 if (lower != m_bp_site_list.begin()) 228 { 229 collection::const_iterator prev_pos = lower; 230 prev_pos--; 231 const BreakpointSiteSP &prev_bp = (*prev_pos).second; 232 if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound) 233 bp_site_list.Add (prev_bp); 234 235 } 236 237 upper = m_bp_site_list.upper_bound(upper_bound); 238 239 for (pos = lower; pos != upper; pos++) 240 { 241 bp_site_list.Add ((*pos).second); 242 } 243 return true; 244 } 245 246 247 void 248 BreakpointSiteList::SetEnabledForAll (const bool enabled, const lldb::break_id_t except_id) 249 { 250 collection::iterator end = m_bp_site_list.end(); 251 collection::iterator pos; 252 for (pos = m_bp_site_list.begin(); pos != end; ++pos) 253 { 254 if (except_id != LLDB_INVALID_BREAK_ID && except_id != pos->second->GetID()) 255 pos->second->SetEnabled (enabled); 256 else 257 pos->second->SetEnabled (!enabled); 258 } 259 } 260 261 const BreakpointSiteList::collection * 262 BreakpointSiteList::GetMap () 263 { 264 return &m_bp_site_list; 265 } 266