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