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_address_to_watchpoint (), 23 m_mutex (Mutex::eMutexTypeRecursive) 24 { 25 } 26 27 WatchpointList::~WatchpointList() 28 { 29 } 30 31 // Add watchpoint loc to the list. However, if the element already exists in the 32 // list, then replace it with the input one. 33 34 lldb::watch_id_t 35 WatchpointList::Add (const WatchpointSP &wp_sp) 36 { 37 Mutex::Locker locker (m_mutex); 38 lldb::addr_t wp_addr = wp_sp->GetLoadAddress(); 39 addr_map::iterator iter = m_address_to_watchpoint.find(wp_addr); 40 41 if (iter == m_address_to_watchpoint.end()) 42 m_address_to_watchpoint.insert(iter, addr_map::value_type(wp_addr, wp_sp)); 43 else 44 m_address_to_watchpoint[wp_addr] = wp_sp; 45 46 return wp_sp->GetID(); 47 } 48 49 void 50 WatchpointList::Dump (Stream *s) const 51 { 52 DumpWithLevel(s, lldb::eDescriptionLevelBrief); 53 } 54 55 void 56 WatchpointList::DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const 57 { 58 Mutex::Locker locker (m_mutex); 59 s->Printf("%p: ", this); 60 //s->Indent(); 61 s->Printf("WatchpointList with %zu Watchpoints:\n", 62 m_address_to_watchpoint.size()); 63 s->IndentMore(); 64 addr_map::const_iterator pos, end = m_address_to_watchpoint.end(); 65 for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos) 66 pos->second->DumpWithLevel(s, description_level); 67 s->IndentLess(); 68 } 69 70 const WatchpointSP 71 WatchpointList::FindByAddress (lldb::addr_t addr) const 72 { 73 WatchpointSP wp_sp; 74 Mutex::Locker locker (m_mutex); 75 if (!m_address_to_watchpoint.empty()) 76 { 77 addr_map::const_iterator pos = m_address_to_watchpoint.find (addr); 78 if (pos != m_address_to_watchpoint.end()) 79 wp_sp = pos->second; 80 } 81 82 return wp_sp; 83 } 84 85 class WatchpointIDMatches 86 { 87 public: 88 WatchpointIDMatches (lldb::watch_id_t watch_id) : 89 m_watch_id(watch_id) 90 { 91 } 92 93 bool operator() (std::pair <lldb::addr_t, WatchpointSP> val_pair) const 94 { 95 return m_watch_id == val_pair.second.get()->GetID(); 96 } 97 98 private: 99 const lldb::watch_id_t m_watch_id; 100 }; 101 102 WatchpointList::addr_map::iterator 103 WatchpointList::GetIDIterator (lldb::watch_id_t watch_id) 104 { 105 return std::find_if(m_address_to_watchpoint.begin(), m_address_to_watchpoint.end(), // Search full range 106 WatchpointIDMatches(watch_id)); // Predicate 107 } 108 109 WatchpointList::addr_map::const_iterator 110 WatchpointList::GetIDConstIterator (lldb::watch_id_t watch_id) const 111 { 112 return std::find_if(m_address_to_watchpoint.begin(), m_address_to_watchpoint.end(), // Search full range 113 WatchpointIDMatches(watch_id)); // Predicate 114 } 115 116 WatchpointSP 117 WatchpointList::FindByID (lldb::watch_id_t watch_id) const 118 { 119 WatchpointSP wp_sp; 120 Mutex::Locker locker (m_mutex); 121 addr_map::const_iterator pos = GetIDConstIterator(watch_id); 122 if (pos != m_address_to_watchpoint.end()) 123 wp_sp = pos->second; 124 125 return wp_sp; 126 } 127 128 lldb::watch_id_t 129 WatchpointList::FindIDByAddress (lldb::addr_t addr) 130 { 131 WatchpointSP wp_sp = FindByAddress (addr); 132 if (wp_sp) 133 { 134 return wp_sp->GetID(); 135 } 136 return LLDB_INVALID_WATCH_ID; 137 } 138 139 WatchpointSP 140 WatchpointList::GetByIndex (uint32_t i) 141 { 142 Mutex::Locker locker (m_mutex); 143 WatchpointSP wp_sp; 144 if (i < m_address_to_watchpoint.size()) 145 { 146 addr_map::const_iterator pos = m_address_to_watchpoint.begin(); 147 std::advance(pos, i); 148 wp_sp = pos->second; 149 } 150 return wp_sp; 151 } 152 153 const WatchpointSP 154 WatchpointList::GetByIndex (uint32_t i) const 155 { 156 Mutex::Locker locker (m_mutex); 157 WatchpointSP wp_sp; 158 if (i < m_address_to_watchpoint.size()) 159 { 160 addr_map::const_iterator pos = m_address_to_watchpoint.begin(); 161 std::advance(pos, i); 162 wp_sp = pos->second; 163 } 164 return wp_sp; 165 } 166 167 bool 168 WatchpointList::Remove (lldb::watch_id_t watch_id) 169 { 170 Mutex::Locker locker (m_mutex); 171 addr_map::iterator pos = GetIDIterator(watch_id); 172 if (pos != m_address_to_watchpoint.end()) 173 { 174 m_address_to_watchpoint.erase(pos); 175 return true; 176 } 177 return false; 178 } 179 180 uint32_t 181 WatchpointList::GetHitCount () const 182 { 183 uint32_t hit_count = 0; 184 Mutex::Locker locker (m_mutex); 185 addr_map::const_iterator pos, end = m_address_to_watchpoint.end(); 186 for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos) 187 hit_count += pos->second->GetHitCount(); 188 return hit_count; 189 } 190 191 bool 192 WatchpointList::ShouldStop (StoppointCallbackContext *context, lldb::watch_id_t watch_id) 193 { 194 195 WatchpointSP wp_sp = FindByID (watch_id); 196 if (wp_sp) 197 { 198 // Let the Watchpoint decide if it should stop here (could not have 199 // reached it's target hit count yet, or it could have a callback 200 // that decided it shouldn't stop. 201 return wp_sp->ShouldStop (context); 202 } 203 // We should stop here since this Watchpoint isn't valid anymore or it 204 // doesn't exist. 205 return true; 206 } 207 208 void 209 WatchpointList::GetDescription (Stream *s, lldb::DescriptionLevel level) 210 { 211 Mutex::Locker locker (m_mutex); 212 addr_map::iterator pos, end = m_address_to_watchpoint.end(); 213 214 for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos) 215 { 216 s->Printf(" "); 217 pos->second->Dump(s); 218 } 219 } 220 221 void 222 WatchpointList::SetEnabledAll (bool enabled) 223 { 224 Mutex::Locker locker(m_mutex); 225 226 addr_map::iterator pos, end = m_address_to_watchpoint.end(); 227 for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos) 228 pos->second->SetEnabled (enabled); 229 } 230 231 void 232 WatchpointList::RemoveAll () 233 { 234 Mutex::Locker locker(m_mutex); 235 m_address_to_watchpoint.clear(); 236 } 237 238 void 239 WatchpointList::GetListMutex (Mutex::Locker &locker) 240 { 241 return locker.Reset (m_mutex.GetMutex()); 242 } 243