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 18 using namespace lldb; 19 using namespace lldb_private; 20 21 WatchpointList::WatchpointList() : 22 m_watchpoints (), 23 m_mutex (Mutex::eMutexTypeRecursive), 24 m_next_wp_id (0) 25 { 26 } 27 28 WatchpointList::~WatchpointList() 29 { 30 } 31 32 // Add a watchpoint to the list. 33 lldb::watch_id_t 34 WatchpointList::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 48 void 49 WatchpointList::Dump (Stream *s) const 50 { 51 DumpWithLevel(s, lldb::eDescriptionLevelBrief); 52 } 53 54 void 55 WatchpointList::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 69 const WatchpointSP 70 WatchpointList::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 87 const WatchpointSP 88 WatchpointList::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 105 class WatchpointIDMatches 106 { 107 public: 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 118 private: 119 const lldb::watch_id_t m_watch_id; 120 }; 121 122 WatchpointList::wp_collection::iterator 123 WatchpointList::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 129 WatchpointList::wp_collection::const_iterator 130 WatchpointList::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 136 WatchpointSP 137 WatchpointList::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 148 lldb::watch_id_t 149 WatchpointList::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 159 lldb::watch_id_t 160 WatchpointList::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 170 WatchpointSP 171 WatchpointList::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 184 const WatchpointSP 185 WatchpointList::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 198 std::vector<lldb::watch_id_t> 199 WatchpointList::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 208 bool 209 WatchpointList::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 228 uint32_t 229 WatchpointList::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 239 bool 240 WatchpointList::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 256 void 257 WatchpointList::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 269 void 270 WatchpointList::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 279 void 280 WatchpointList::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 302 void 303 WatchpointList::GetListMutex (Mutex::Locker &locker) 304 { 305 return locker.Lock (m_mutex); 306 } 307