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