1254721Semaste//===-- WatchpointList.cpp --------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste 11254721Semaste// C Includes 12254721Semaste// C++ Includes 13254721Semaste// Other libraries and framework includes 14254721Semaste// Project includes 15254721Semaste#include "lldb/Breakpoint/WatchpointList.h" 16254721Semaste#include "lldb/Breakpoint/Watchpoint.h" 17254721Semaste 18254721Semasteusing namespace lldb; 19254721Semasteusing namespace lldb_private; 20254721Semaste 21254721SemasteWatchpointList::WatchpointList() : 22254721Semaste m_watchpoints (), 23254721Semaste m_mutex (Mutex::eMutexTypeRecursive), 24254721Semaste m_next_wp_id (0) 25254721Semaste{ 26254721Semaste} 27254721Semaste 28254721SemasteWatchpointList::~WatchpointList() 29254721Semaste{ 30254721Semaste} 31254721Semaste 32254721Semaste// Add a watchpoint to the list. 33254721Semastelldb::watch_id_t 34254721SemasteWatchpointList::Add (const WatchpointSP &wp_sp, bool notify) 35254721Semaste{ 36254721Semaste Mutex::Locker locker (m_mutex); 37254721Semaste wp_sp->SetID(++m_next_wp_id); 38254721Semaste m_watchpoints.push_back(wp_sp); 39254721Semaste if (notify) 40254721Semaste { 41254721Semaste if (wp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged)) 42254721Semaste wp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, 43254721Semaste new Watchpoint::WatchpointEventData (eWatchpointEventTypeAdded, wp_sp)); 44254721Semaste } 45254721Semaste return wp_sp->GetID(); 46254721Semaste} 47254721Semaste 48254721Semastevoid 49254721SemasteWatchpointList::Dump (Stream *s) const 50254721Semaste{ 51254721Semaste DumpWithLevel(s, lldb::eDescriptionLevelBrief); 52254721Semaste} 53254721Semaste 54254721Semastevoid 55254721SemasteWatchpointList::DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const 56254721Semaste{ 57254721Semaste Mutex::Locker locker (m_mutex); 58254721Semaste s->Printf("%p: ", this); 59254721Semaste //s->Indent(); 60254721Semaste s->Printf("WatchpointList with %" PRIu64 " Watchpoints:\n", 61254721Semaste (uint64_t)m_watchpoints.size()); 62254721Semaste s->IndentMore(); 63254721Semaste wp_collection::const_iterator pos, end = m_watchpoints.end(); 64254721Semaste for (pos = m_watchpoints.begin(); pos != end; ++pos) 65254721Semaste (*pos)->DumpWithLevel(s, description_level); 66254721Semaste s->IndentLess(); 67254721Semaste} 68254721Semaste 69254721Semasteconst WatchpointSP 70254721SemasteWatchpointList::FindByAddress (lldb::addr_t addr) const 71254721Semaste{ 72254721Semaste WatchpointSP wp_sp; 73254721Semaste Mutex::Locker locker (m_mutex); 74254721Semaste if (!m_watchpoints.empty()) 75254721Semaste { 76254721Semaste wp_collection::const_iterator pos, end = m_watchpoints.end(); 77254721Semaste for (pos = m_watchpoints.begin(); pos != end; ++pos) 78254721Semaste if ((*pos)->GetLoadAddress() == addr) { 79254721Semaste wp_sp = *pos; 80254721Semaste break; 81254721Semaste } 82254721Semaste } 83254721Semaste 84254721Semaste return wp_sp; 85254721Semaste} 86254721Semaste 87254721Semasteconst WatchpointSP 88254721SemasteWatchpointList::FindBySpec (std::string spec) const 89254721Semaste{ 90254721Semaste WatchpointSP wp_sp; 91254721Semaste Mutex::Locker locker (m_mutex); 92254721Semaste if (!m_watchpoints.empty()) 93254721Semaste { 94254721Semaste wp_collection::const_iterator pos, end = m_watchpoints.end(); 95254721Semaste for (pos = m_watchpoints.begin(); pos != end; ++pos) 96254721Semaste if ((*pos)->GetWatchSpec() == spec) { 97254721Semaste wp_sp = *pos; 98254721Semaste break; 99254721Semaste } 100254721Semaste } 101254721Semaste 102254721Semaste return wp_sp; 103254721Semaste} 104254721Semaste 105254721Semasteclass WatchpointIDMatches 106254721Semaste{ 107254721Semastepublic: 108254721Semaste WatchpointIDMatches (lldb::watch_id_t watch_id) : 109254721Semaste m_watch_id(watch_id) 110254721Semaste { 111254721Semaste } 112254721Semaste 113254721Semaste bool operator() (const WatchpointSP &wp) const 114254721Semaste { 115254721Semaste return m_watch_id == wp->GetID(); 116254721Semaste } 117254721Semaste 118254721Semasteprivate: 119254721Semaste const lldb::watch_id_t m_watch_id; 120254721Semaste}; 121254721Semaste 122254721SemasteWatchpointList::wp_collection::iterator 123254721SemasteWatchpointList::GetIDIterator (lldb::watch_id_t watch_id) 124254721Semaste{ 125254721Semaste return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range 126254721Semaste WatchpointIDMatches(watch_id)); // Predicate 127254721Semaste} 128254721Semaste 129254721SemasteWatchpointList::wp_collection::const_iterator 130254721SemasteWatchpointList::GetIDConstIterator (lldb::watch_id_t watch_id) const 131254721Semaste{ 132254721Semaste return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range 133254721Semaste WatchpointIDMatches(watch_id)); // Predicate 134254721Semaste} 135254721Semaste 136254721SemasteWatchpointSP 137254721SemasteWatchpointList::FindByID (lldb::watch_id_t watch_id) const 138254721Semaste{ 139254721Semaste WatchpointSP wp_sp; 140254721Semaste Mutex::Locker locker (m_mutex); 141254721Semaste wp_collection::const_iterator pos = GetIDConstIterator(watch_id); 142254721Semaste if (pos != m_watchpoints.end()) 143254721Semaste wp_sp = *pos; 144254721Semaste 145254721Semaste return wp_sp; 146254721Semaste} 147254721Semaste 148254721Semastelldb::watch_id_t 149254721SemasteWatchpointList::FindIDByAddress (lldb::addr_t addr) 150254721Semaste{ 151254721Semaste WatchpointSP wp_sp = FindByAddress (addr); 152254721Semaste if (wp_sp) 153254721Semaste { 154254721Semaste return wp_sp->GetID(); 155254721Semaste } 156254721Semaste return LLDB_INVALID_WATCH_ID; 157254721Semaste} 158254721Semaste 159254721Semastelldb::watch_id_t 160254721SemasteWatchpointList::FindIDBySpec (std::string spec) 161254721Semaste{ 162254721Semaste WatchpointSP wp_sp = FindBySpec (spec); 163254721Semaste if (wp_sp) 164254721Semaste { 165254721Semaste return wp_sp->GetID(); 166254721Semaste } 167254721Semaste return LLDB_INVALID_WATCH_ID; 168254721Semaste} 169254721Semaste 170254721SemasteWatchpointSP 171254721SemasteWatchpointList::GetByIndex (uint32_t i) 172254721Semaste{ 173254721Semaste Mutex::Locker locker (m_mutex); 174254721Semaste WatchpointSP wp_sp; 175254721Semaste if (i < m_watchpoints.size()) 176254721Semaste { 177254721Semaste wp_collection::const_iterator pos = m_watchpoints.begin(); 178254721Semaste std::advance(pos, i); 179254721Semaste wp_sp = *pos; 180254721Semaste } 181254721Semaste return wp_sp; 182254721Semaste} 183254721Semaste 184254721Semasteconst WatchpointSP 185254721SemasteWatchpointList::GetByIndex (uint32_t i) const 186254721Semaste{ 187254721Semaste Mutex::Locker locker (m_mutex); 188254721Semaste WatchpointSP wp_sp; 189254721Semaste if (i < m_watchpoints.size()) 190254721Semaste { 191254721Semaste wp_collection::const_iterator pos = m_watchpoints.begin(); 192254721Semaste std::advance(pos, i); 193254721Semaste wp_sp = *pos; 194254721Semaste } 195254721Semaste return wp_sp; 196254721Semaste} 197254721Semaste 198254721Semastestd::vector<lldb::watch_id_t> 199254721SemasteWatchpointList::GetWatchpointIDs() const 200254721Semaste{ 201254721Semaste std::vector<lldb::watch_id_t> IDs; 202254721Semaste wp_collection::const_iterator pos, end = m_watchpoints.end(); 203254721Semaste for (pos = m_watchpoints.begin(); pos != end; ++pos) 204254721Semaste IDs.push_back((*pos)->GetID()); 205254721Semaste return IDs; 206254721Semaste} 207254721Semaste 208254721Semastebool 209254721SemasteWatchpointList::Remove (lldb::watch_id_t watch_id, bool notify) 210254721Semaste{ 211254721Semaste Mutex::Locker locker (m_mutex); 212254721Semaste wp_collection::iterator pos = GetIDIterator(watch_id); 213254721Semaste if (pos != m_watchpoints.end()) 214254721Semaste { 215254721Semaste WatchpointSP wp_sp = *pos; 216254721Semaste if (notify) 217254721Semaste { 218254721Semaste if (wp_sp->GetTarget().EventTypeHasListeners(Target::eBroadcastBitWatchpointChanged)) 219254721Semaste wp_sp->GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, 220254721Semaste new Watchpoint::WatchpointEventData (eWatchpointEventTypeRemoved, wp_sp)); 221254721Semaste } 222254721Semaste m_watchpoints.erase(pos); 223254721Semaste return true; 224254721Semaste } 225254721Semaste return false; 226254721Semaste} 227254721Semaste 228254721Semasteuint32_t 229254721SemasteWatchpointList::GetHitCount () const 230254721Semaste{ 231254721Semaste uint32_t hit_count = 0; 232254721Semaste Mutex::Locker locker (m_mutex); 233254721Semaste wp_collection::const_iterator pos, end = m_watchpoints.end(); 234254721Semaste for (pos = m_watchpoints.begin(); pos != end; ++pos) 235254721Semaste hit_count += (*pos)->GetHitCount(); 236254721Semaste return hit_count; 237254721Semaste} 238254721Semaste 239254721Semastebool 240254721SemasteWatchpointList::ShouldStop (StoppointCallbackContext *context, lldb::watch_id_t watch_id) 241254721Semaste{ 242254721Semaste 243254721Semaste WatchpointSP wp_sp = FindByID (watch_id); 244254721Semaste if (wp_sp) 245254721Semaste { 246254721Semaste // Let the Watchpoint decide if it should stop here (could not have 247254721Semaste // reached it's target hit count yet, or it could have a callback 248254721Semaste // that decided it shouldn't stop. 249254721Semaste return wp_sp->ShouldStop (context); 250254721Semaste } 251254721Semaste // We should stop here since this Watchpoint isn't valid anymore or it 252254721Semaste // doesn't exist. 253254721Semaste return true; 254254721Semaste} 255254721Semaste 256254721Semastevoid 257254721SemasteWatchpointList::GetDescription (Stream *s, lldb::DescriptionLevel level) 258254721Semaste{ 259254721Semaste Mutex::Locker locker (m_mutex); 260254721Semaste wp_collection::iterator pos, end = m_watchpoints.end(); 261254721Semaste 262254721Semaste for (pos = m_watchpoints.begin(); pos != end; ++pos) 263254721Semaste { 264254721Semaste s->Printf(" "); 265254721Semaste (*pos)->Dump(s); 266254721Semaste } 267254721Semaste} 268254721Semaste 269254721Semastevoid 270254721SemasteWatchpointList::SetEnabledAll (bool enabled) 271254721Semaste{ 272254721Semaste Mutex::Locker locker(m_mutex); 273254721Semaste 274254721Semaste wp_collection::iterator pos, end = m_watchpoints.end(); 275254721Semaste for (pos = m_watchpoints.begin(); pos != end; ++pos) 276254721Semaste (*pos)->SetEnabled (enabled); 277254721Semaste} 278254721Semaste 279254721Semastevoid 280254721SemasteWatchpointList::RemoveAll (bool notify) 281254721Semaste{ 282254721Semaste Mutex::Locker locker(m_mutex); 283254721Semaste if (notify) 284254721Semaste { 285254721Semaste 286254721Semaste { 287254721Semaste wp_collection::iterator pos, end = m_watchpoints.end(); 288254721Semaste for (pos = m_watchpoints.begin(); pos != end; ++pos) 289254721Semaste { 290254721Semaste if ((*pos)->GetTarget().EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) 291254721Semaste { 292254721Semaste (*pos)->GetTarget().BroadcastEvent (Target::eBroadcastBitWatchpointChanged, 293254721Semaste new Watchpoint::WatchpointEventData (eWatchpointEventTypeRemoved, 294254721Semaste *pos)); 295254721Semaste } 296254721Semaste } 297254721Semaste } 298254721Semaste } 299254721Semaste m_watchpoints.clear(); 300254721Semaste} 301254721Semaste 302254721Semastevoid 303254721SemasteWatchpointList::GetListMutex (Mutex::Locker &locker) 304254721Semaste{ 305254721Semaste return locker.Lock (m_mutex); 306254721Semaste} 307