1 //===-- WatchpointResource.cpp --------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <assert.h>
10 
11 #include "lldb/Breakpoint/WatchpointResource.h"
12 
13 #include <algorithm>
14 
15 using namespace lldb;
16 using namespace lldb_private;
17 
WatchpointResource(lldb::addr_t addr,size_t size,bool read,bool write)18 WatchpointResource::WatchpointResource(lldb::addr_t addr, size_t size,
19                                        bool read, bool write)
20     : m_id(GetNextID()), m_addr(addr), m_size(size),
21       m_watch_read(read), m_watch_write(write) {}
22 
~WatchpointResource()23 WatchpointResource::~WatchpointResource() {
24   std::lock_guard<std::mutex> guard(m_constituents_mutex);
25   m_constituents.clear();
26 }
27 
GetLoadAddress() const28 addr_t WatchpointResource::GetLoadAddress() const { return m_addr; }
29 
GetByteSize() const30 size_t WatchpointResource::GetByteSize() const { return m_size; }
31 
WatchpointResourceRead() const32 bool WatchpointResource::WatchpointResourceRead() const { return m_watch_read; }
33 
WatchpointResourceWrite() const34 bool WatchpointResource::WatchpointResourceWrite() const {
35   return m_watch_write;
36 }
37 
SetType(bool read,bool write)38 void WatchpointResource::SetType(bool read, bool write) {
39   m_watch_read = read;
40   m_watch_write = write;
41 }
42 
GetID() const43 wp_resource_id_t WatchpointResource::GetID() const { return m_id; }
44 
SetID(wp_resource_id_t id)45 void WatchpointResource::SetID(wp_resource_id_t id) { m_id = id; }
46 
Contains(addr_t addr)47 bool WatchpointResource::Contains(addr_t addr) {
48   if (addr >= m_addr && addr < m_addr + m_size)
49     return true;
50   return false;
51 }
52 
AddConstituent(const WatchpointSP & wp_sp)53 void WatchpointResource::AddConstituent(const WatchpointSP &wp_sp) {
54   std::lock_guard<std::mutex> guard(m_constituents_mutex);
55   m_constituents.push_back(wp_sp);
56 }
57 
RemoveConstituent(WatchpointSP & wp_sp)58 void WatchpointResource::RemoveConstituent(WatchpointSP &wp_sp) {
59   std::lock_guard<std::mutex> guard(m_constituents_mutex);
60   const auto &it =
61       std::find(m_constituents.begin(), m_constituents.end(), wp_sp);
62   if (it != m_constituents.end())
63     m_constituents.erase(it);
64 }
65 
GetNumberOfConstituents()66 size_t WatchpointResource::GetNumberOfConstituents() {
67   std::lock_guard<std::mutex> guard(m_constituents_mutex);
68   return m_constituents.size();
69 }
70 
ConstituentsContains(const WatchpointSP & wp_sp)71 bool WatchpointResource::ConstituentsContains(const WatchpointSP &wp_sp) {
72   return ConstituentsContains(wp_sp.get());
73 }
74 
ConstituentsContains(const Watchpoint * wp)75 bool WatchpointResource::ConstituentsContains(const Watchpoint *wp) {
76   std::lock_guard<std::mutex> guard(m_constituents_mutex);
77   WatchpointCollection::const_iterator match =
78       std::find_if(m_constituents.begin(), m_constituents.end(),
79                    [&wp](const WatchpointSP &x) { return x.get() == wp; });
80   return match != m_constituents.end();
81 }
82 
GetConstituentAtIndex(size_t idx)83 WatchpointSP WatchpointResource::GetConstituentAtIndex(size_t idx) {
84   std::lock_guard<std::mutex> guard(m_constituents_mutex);
85   assert(idx < m_constituents.size());
86   if (idx >= m_constituents.size())
87     return {};
88 
89   return m_constituents[idx];
90 }
91 
92 WatchpointResource::WatchpointCollection
CopyConstituentsList()93 WatchpointResource::CopyConstituentsList() {
94   std::lock_guard<std::mutex> guard(m_constituents_mutex);
95   return m_constituents;
96 }
97 
ShouldStop(StoppointCallbackContext * context)98 bool WatchpointResource::ShouldStop(StoppointCallbackContext *context) {
99   // LWP_TODO: Need to poll all Watchpoint constituents and see if
100   // we should stop, like BreakpointSites do.
101 #if 0
102   m_hit_counter.Increment();
103   // ShouldStop can do a lot of work, and might even come back and hit
104   // this breakpoint site again.  So don't hold the m_constituents_mutex the
105   // whole while.  Instead make a local copy of the collection and call
106   // ShouldStop on the copy.
107   WatchpointResourceCollection constituents_copy;
108   {
109     std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
110     constituents_copy = m_constituents;
111   }
112   return constituents_copy.ShouldStop(context);
113 #endif
114   return true;
115 }
116 
Dump(Stream * s) const117 void WatchpointResource::Dump(Stream *s) const {
118   return; // LWP_TODO
119 }
120 
GetNextID()121 wp_resource_id_t WatchpointResource::GetNextID() {
122   static wp_resource_id_t g_next_id = 0;
123   return ++g_next_id;
124 }
125