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