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 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 23 WatchpointResource::~WatchpointResource() { 24 std::lock_guard<std::mutex> guard(m_constituents_mutex); 25 m_constituents.clear(); 26 } 27 28 addr_t WatchpointResource::GetLoadAddress() const { return m_addr; } 29 30 size_t WatchpointResource::GetByteSize() const { return m_size; } 31 32 bool WatchpointResource::WatchpointResourceRead() const { return m_watch_read; } 33 34 bool WatchpointResource::WatchpointResourceWrite() const { 35 return m_watch_write; 36 } 37 38 void WatchpointResource::SetType(bool read, bool write) { 39 m_watch_read = read; 40 m_watch_write = write; 41 } 42 43 wp_resource_id_t WatchpointResource::GetID() const { return m_id; } 44 45 void WatchpointResource::SetID(wp_resource_id_t id) { m_id = id; } 46 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 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 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 66 size_t WatchpointResource::GetNumberOfConstituents() { 67 std::lock_guard<std::mutex> guard(m_constituents_mutex); 68 return m_constituents.size(); 69 } 70 71 bool WatchpointResource::ConstituentsContains(const WatchpointSP &wp_sp) { 72 return ConstituentsContains(wp_sp.get()); 73 } 74 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 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 93 WatchpointResource::CopyConstituentsList() { 94 std::lock_guard<std::mutex> guard(m_constituents_mutex); 95 return m_constituents; 96 } 97 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 117 void WatchpointResource::Dump(Stream *s) const { 118 return; // LWP_TODO 119 } 120 121 wp_resource_id_t WatchpointResource::GetNextID() { 122 static wp_resource_id_t g_next_id = 0; 123 return ++g_next_id; 124 } 125