1//===-- WatchpointList.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 11// C Includes 12// C++ Includes 13// Other libraries and framework includes 14// Project includes 15#include "lldb/Breakpoint/WatchpointList.h" 16#include "lldb/Breakpoint/Watchpoint.h" 17 18using namespace lldb; 19using namespace lldb_private; 20 21WatchpointList::WatchpointList() : 22 m_watchpoints (), 23 m_mutex (Mutex::eMutexTypeRecursive), 24 m_next_wp_id (0) 25{ 26} 27 28WatchpointList::~WatchpointList() 29{ 30} 31 32// Add a watchpoint to the list. 33lldb::watch_id_t 34WatchpointList::Add (const WatchpointSP &wp_sp, bool notify) 35{ 36 Mutex::Locker locker (m_mutex); 37 wp_sp->SetID(++m_next_wp_id); 38 m_watchpoints.push_back(wp_sp); 39 if (notify) 40 { 41 if (wp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged)) 42 wp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, 43 new Watchpoint::WatchpointEventData (eWatchpointEventTypeAdded, wp_sp)); 44 } 45 return wp_sp->GetID(); 46} 47 48void 49WatchpointList::Dump (Stream *s) const 50{ 51 DumpWithLevel(s, lldb::eDescriptionLevelBrief); 52} 53 54void 55WatchpointList::DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const 56{ 57 Mutex::Locker locker (m_mutex); 58 s->Printf("%p: ", this); 59 //s->Indent(); 60 s->Printf("WatchpointList with %" PRIu64 " Watchpoints:\n", 61 (uint64_t)m_watchpoints.size()); 62 s->IndentMore(); 63 wp_collection::const_iterator pos, end = m_watchpoints.end(); 64 for (pos = m_watchpoints.begin(); pos != end; ++pos) 65 (*pos)->DumpWithLevel(s, description_level); 66 s->IndentLess(); 67} 68 69const WatchpointSP 70WatchpointList::FindByAddress (lldb::addr_t addr) const 71{ 72 WatchpointSP wp_sp; 73 Mutex::Locker locker (m_mutex); 74 if (!m_watchpoints.empty()) 75 { 76 wp_collection::const_iterator pos, end = m_watchpoints.end(); 77 for (pos = m_watchpoints.begin(); pos != end; ++pos) 78 if ((*pos)->GetLoadAddress() == addr) { 79 wp_sp = *pos; 80 break; 81 } 82 } 83 84 return wp_sp; 85} 86 87const WatchpointSP 88WatchpointList::FindBySpec (std::string spec) const 89{ 90 WatchpointSP wp_sp; 91 Mutex::Locker locker (m_mutex); 92 if (!m_watchpoints.empty()) 93 { 94 wp_collection::const_iterator pos, end = m_watchpoints.end(); 95 for (pos = m_watchpoints.begin(); pos != end; ++pos) 96 if ((*pos)->GetWatchSpec() == spec) { 97 wp_sp = *pos; 98 break; 99 } 100 } 101 102 return wp_sp; 103} 104 105class WatchpointIDMatches 106{ 107public: 108 WatchpointIDMatches (lldb::watch_id_t watch_id) : 109 m_watch_id(watch_id) 110 { 111 } 112 113 bool operator() (const WatchpointSP &wp) const 114 { 115 return m_watch_id == wp->GetID(); 116 } 117 118private: 119 const lldb::watch_id_t m_watch_id; 120}; 121 122WatchpointList::wp_collection::iterator 123WatchpointList::GetIDIterator (lldb::watch_id_t watch_id) 124{ 125 return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range 126 WatchpointIDMatches(watch_id)); // Predicate 127} 128 129WatchpointList::wp_collection::const_iterator 130WatchpointList::GetIDConstIterator (lldb::watch_id_t watch_id) const 131{ 132 return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range 133 WatchpointIDMatches(watch_id)); // Predicate 134} 135 136WatchpointSP 137WatchpointList::FindByID (lldb::watch_id_t watch_id) const 138{ 139 WatchpointSP wp_sp; 140 Mutex::Locker locker (m_mutex); 141 wp_collection::const_iterator pos = GetIDConstIterator(watch_id); 142 if (pos != m_watchpoints.end()) 143 wp_sp = *pos; 144 145 return wp_sp; 146} 147 148lldb::watch_id_t 149WatchpointList::FindIDByAddress (lldb::addr_t addr) 150{ 151 WatchpointSP wp_sp = FindByAddress (addr); 152 if (wp_sp) 153 { 154 return wp_sp->GetID(); 155 } 156 return LLDB_INVALID_WATCH_ID; 157} 158 159lldb::watch_id_t 160WatchpointList::FindIDBySpec (std::string spec) 161{ 162 WatchpointSP wp_sp = FindBySpec (spec); 163 if (wp_sp) 164 { 165 return wp_sp->GetID(); 166 } 167 return LLDB_INVALID_WATCH_ID; 168} 169 170WatchpointSP 171WatchpointList::GetByIndex (uint32_t i) 172{ 173 Mutex::Locker locker (m_mutex); 174 WatchpointSP wp_sp; 175 if (i < m_watchpoints.size()) 176 { 177 wp_collection::const_iterator pos = m_watchpoints.begin(); 178 std::advance(pos, i); 179 wp_sp = *pos; 180 } 181 return wp_sp; 182} 183 184const WatchpointSP 185WatchpointList::GetByIndex (uint32_t i) const 186{ 187 Mutex::Locker locker (m_mutex); 188 WatchpointSP wp_sp; 189 if (i < m_watchpoints.size()) 190 { 191 wp_collection::const_iterator pos = m_watchpoints.begin(); 192 std::advance(pos, i); 193 wp_sp = *pos; 194 } 195 return wp_sp; 196} 197 198std::vector<lldb::watch_id_t> 199WatchpointList::GetWatchpointIDs() const 200{ 201 std::vector<lldb::watch_id_t> IDs; 202 wp_collection::const_iterator pos, end = m_watchpoints.end(); 203 for (pos = m_watchpoints.begin(); pos != end; ++pos) 204 IDs.push_back((*pos)->GetID()); 205 return IDs; 206} 207 208bool 209WatchpointList::Remove (lldb::watch_id_t watch_id, bool notify) 210{ 211 Mutex::Locker locker (m_mutex); 212 wp_collection::iterator pos = GetIDIterator(watch_id); 213 if (pos != m_watchpoints.end()) 214 { 215 WatchpointSP wp_sp = *pos; 216 if (notify) 217 { 218 if (wp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged)) 219 wp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, 220 new Watchpoint::WatchpointEventData (eWatchpointEventTypeRemoved, wp_sp)); 221 } 222 m_watchpoints.erase(pos); 223 return true; 224 } 225 return false; 226} 227 228uint32_t 229WatchpointList::GetHitCount () const 230{ 231 uint32_t hit_count = 0; 232 Mutex::Locker locker (m_mutex); 233 wp_collection::const_iterator pos, end = m_watchpoints.end(); 234 for (pos = m_watchpoints.begin(); pos != end; ++pos) 235 hit_count += (*pos)->GetHitCount(); 236 return hit_count; 237} 238 239bool 240WatchpointList::ShouldStop (StoppointCallbackContext *context, lldb::watch_id_t watch_id) 241{ 242 243 WatchpointSP wp_sp = FindByID (watch_id); 244 if (wp_sp) 245 { 246 // Let the Watchpoint decide if it should stop here (could not have 247 // reached it's target hit count yet, or it could have a callback 248 // that decided it shouldn't stop. 249 return wp_sp->ShouldStop (context); 250 } 251 // We should stop here since this Watchpoint isn't valid anymore or it 252 // doesn't exist. 253 return true; 254} 255 256void 257WatchpointList::GetDescription (Stream *s, lldb::DescriptionLevel level) 258{ 259 Mutex::Locker locker (m_mutex); 260 wp_collection::iterator pos, end = m_watchpoints.end(); 261 262 for (pos = m_watchpoints.begin(); pos != end; ++pos) 263 { 264 s->Printf(" "); 265 (*pos)->Dump(s); 266 } 267} 268 269void 270WatchpointList::SetEnabledAll (bool enabled) 271{ 272 Mutex::Locker locker(m_mutex); 273 274 wp_collection::iterator pos, end = m_watchpoints.end(); 275 for (pos = m_watchpoints.begin(); pos != end; ++pos) 276 (*pos)->SetEnabled (enabled); 277} 278 279void 280WatchpointList::RemoveAll (bool notify) 281{ 282 Mutex::Locker locker(m_mutex); 283 if (notify) 284 { 285 286 { 287 wp_collection::iterator pos, end = m_watchpoints.end(); 288 for (pos = m_watchpoints.begin(); pos != end; ++pos) 289 { 290 if ((*pos)->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) 291 { 292 (*pos)->GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, 293 new Watchpoint::WatchpointEventData (eWatchpointEventTypeRemoved, 294 *pos)); 295 } 296 } 297 } 298 } 299 m_watchpoints.clear(); 300} 301 302void 303WatchpointList::GetListMutex (Mutex::Locker &locker) 304{ 305 return locker.Lock (m_mutex); 306} 307