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