| //===-- WatchpointList.cpp --------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| |
| // C Includes |
| // C++ Includes |
| // Other libraries and framework includes |
| // Project includes |
| #include "lldb/Breakpoint/WatchpointList.h" |
| #include "lldb/Breakpoint/Watchpoint.h" |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| WatchpointList::WatchpointList() : |
| m_watchpoints (), |
| m_mutex (Mutex::eMutexTypeRecursive), |
| m_next_wp_id (0) |
| { |
| } |
| |
| WatchpointList::~WatchpointList() |
| { |
| } |
| |
| // Add a watchpoint to the list. |
| lldb::watch_id_t |
| WatchpointList::Add (const WatchpointSP &wp_sp) |
| { |
| Mutex::Locker locker (m_mutex); |
| wp_sp->SetID(++m_next_wp_id); |
| m_watchpoints.push_back(wp_sp); |
| return wp_sp->GetID(); |
| } |
| |
| void |
| WatchpointList::Dump (Stream *s) const |
| { |
| DumpWithLevel(s, lldb::eDescriptionLevelBrief); |
| } |
| |
| void |
| WatchpointList::DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const |
| { |
| Mutex::Locker locker (m_mutex); |
| s->Printf("%p: ", this); |
| //s->Indent(); |
| s->Printf("WatchpointList with %zu Watchpoints:\n", |
| m_watchpoints.size()); |
| s->IndentMore(); |
| wp_collection::const_iterator pos, end = m_watchpoints.end(); |
| for (pos = m_watchpoints.begin(); pos != end; ++pos) |
| (*pos)->DumpWithLevel(s, description_level); |
| s->IndentLess(); |
| } |
| |
| const WatchpointSP |
| WatchpointList::FindByAddress (lldb::addr_t addr) const |
| { |
| WatchpointSP wp_sp; |
| Mutex::Locker locker (m_mutex); |
| if (!m_watchpoints.empty()) |
| { |
| wp_collection::const_iterator pos, end = m_watchpoints.end(); |
| for (pos = m_watchpoints.begin(); pos != end; ++pos) |
| if ((*pos)->GetLoadAddress() == addr) { |
| wp_sp = *pos; |
| break; |
| } |
| } |
| |
| return wp_sp; |
| } |
| |
| const WatchpointSP |
| WatchpointList::FindBySpec (std::string spec) const |
| { |
| WatchpointSP wp_sp; |
| Mutex::Locker locker (m_mutex); |
| if (!m_watchpoints.empty()) |
| { |
| wp_collection::const_iterator pos, end = m_watchpoints.end(); |
| for (pos = m_watchpoints.begin(); pos != end; ++pos) |
| if ((*pos)->GetWatchSpec() == spec) { |
| wp_sp = *pos; |
| break; |
| } |
| } |
| |
| return wp_sp; |
| } |
| |
| class WatchpointIDMatches |
| { |
| public: |
| WatchpointIDMatches (lldb::watch_id_t watch_id) : |
| m_watch_id(watch_id) |
| { |
| } |
| |
| bool operator() (const WatchpointSP &wp) const |
| { |
| return m_watch_id == wp->GetID(); |
| } |
| |
| private: |
| const lldb::watch_id_t m_watch_id; |
| }; |
| |
| WatchpointList::wp_collection::iterator |
| WatchpointList::GetIDIterator (lldb::watch_id_t watch_id) |
| { |
| return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range |
| WatchpointIDMatches(watch_id)); // Predicate |
| } |
| |
| WatchpointList::wp_collection::const_iterator |
| WatchpointList::GetIDConstIterator (lldb::watch_id_t watch_id) const |
| { |
| return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range |
| WatchpointIDMatches(watch_id)); // Predicate |
| } |
| |
| WatchpointSP |
| WatchpointList::FindByID (lldb::watch_id_t watch_id) const |
| { |
| WatchpointSP wp_sp; |
| Mutex::Locker locker (m_mutex); |
| wp_collection::const_iterator pos = GetIDConstIterator(watch_id); |
| if (pos != m_watchpoints.end()) |
| wp_sp = *pos; |
| |
| return wp_sp; |
| } |
| |
| lldb::watch_id_t |
| WatchpointList::FindIDByAddress (lldb::addr_t addr) |
| { |
| WatchpointSP wp_sp = FindByAddress (addr); |
| if (wp_sp) |
| { |
| return wp_sp->GetID(); |
| } |
| return LLDB_INVALID_WATCH_ID; |
| } |
| |
| lldb::watch_id_t |
| WatchpointList::FindIDBySpec (std::string spec) |
| { |
| WatchpointSP wp_sp = FindBySpec (spec); |
| if (wp_sp) |
| { |
| return wp_sp->GetID(); |
| } |
| return LLDB_INVALID_WATCH_ID; |
| } |
| |
| WatchpointSP |
| WatchpointList::GetByIndex (uint32_t i) |
| { |
| Mutex::Locker locker (m_mutex); |
| WatchpointSP wp_sp; |
| if (i < m_watchpoints.size()) |
| { |
| wp_collection::const_iterator pos = m_watchpoints.begin(); |
| std::advance(pos, i); |
| wp_sp = *pos; |
| } |
| return wp_sp; |
| } |
| |
| const WatchpointSP |
| WatchpointList::GetByIndex (uint32_t i) const |
| { |
| Mutex::Locker locker (m_mutex); |
| WatchpointSP wp_sp; |
| if (i < m_watchpoints.size()) |
| { |
| wp_collection::const_iterator pos = m_watchpoints.begin(); |
| std::advance(pos, i); |
| wp_sp = *pos; |
| } |
| return wp_sp; |
| } |
| |
| std::vector<lldb::watch_id_t> |
| WatchpointList::GetWatchpointIDs() const |
| { |
| std::vector<lldb::watch_id_t> IDs; |
| wp_collection::const_iterator pos, end = m_watchpoints.end(); |
| for (pos = m_watchpoints.begin(); pos != end; ++pos) |
| IDs.push_back((*pos)->GetID()); |
| return IDs; |
| } |
| |
| bool |
| WatchpointList::Remove (lldb::watch_id_t watch_id) |
| { |
| Mutex::Locker locker (m_mutex); |
| wp_collection::iterator pos = GetIDIterator(watch_id); |
| if (pos != m_watchpoints.end()) |
| { |
| m_watchpoints.erase(pos); |
| return true; |
| } |
| return false; |
| } |
| |
| uint32_t |
| WatchpointList::GetHitCount () const |
| { |
| uint32_t hit_count = 0; |
| Mutex::Locker locker (m_mutex); |
| wp_collection::const_iterator pos, end = m_watchpoints.end(); |
| for (pos = m_watchpoints.begin(); pos != end; ++pos) |
| hit_count += (*pos)->GetHitCount(); |
| return hit_count; |
| } |
| |
| bool |
| WatchpointList::ShouldStop (StoppointCallbackContext *context, lldb::watch_id_t watch_id) |
| { |
| |
| WatchpointSP wp_sp = FindByID (watch_id); |
| if (wp_sp) |
| { |
| // Let the Watchpoint decide if it should stop here (could not have |
| // reached it's target hit count yet, or it could have a callback |
| // that decided it shouldn't stop. |
| return wp_sp->ShouldStop (context); |
| } |
| // We should stop here since this Watchpoint isn't valid anymore or it |
| // doesn't exist. |
| return true; |
| } |
| |
| void |
| WatchpointList::GetDescription (Stream *s, lldb::DescriptionLevel level) |
| { |
| Mutex::Locker locker (m_mutex); |
| wp_collection::iterator pos, end = m_watchpoints.end(); |
| |
| for (pos = m_watchpoints.begin(); pos != end; ++pos) |
| { |
| s->Printf(" "); |
| (*pos)->Dump(s); |
| } |
| } |
| |
| void |
| WatchpointList::SetEnabledAll (bool enabled) |
| { |
| Mutex::Locker locker(m_mutex); |
| |
| wp_collection::iterator pos, end = m_watchpoints.end(); |
| for (pos = m_watchpoints.begin(); pos != end; ++pos) |
| (*pos)->SetEnabled (enabled); |
| } |
| |
| void |
| WatchpointList::RemoveAll () |
| { |
| Mutex::Locker locker(m_mutex); |
| m_watchpoints.clear(); |
| } |
| |
| void |
| WatchpointList::GetListMutex (Mutex::Locker &locker) |
| { |
| return locker.Reset (m_mutex.GetMutex()); |
| } |