15f757f3fSDimitry Andric //===-- WatchpointResource.cpp --------------------------------------------===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric 95f757f3fSDimitry Andric #include <assert.h> 105f757f3fSDimitry Andric 115f757f3fSDimitry Andric #include "lldb/Breakpoint/WatchpointResource.h" 12*0fca6ea1SDimitry Andric #include "lldb/Utility/Stream.h" 135f757f3fSDimitry Andric 145f757f3fSDimitry Andric #include <algorithm> 155f757f3fSDimitry Andric 165f757f3fSDimitry Andric using namespace lldb; 175f757f3fSDimitry Andric using namespace lldb_private; 185f757f3fSDimitry Andric 195f757f3fSDimitry Andric WatchpointResource::WatchpointResource(lldb::addr_t addr, size_t size, 205f757f3fSDimitry Andric bool read, bool write) 215f757f3fSDimitry Andric : m_id(GetNextID()), m_addr(addr), m_size(size), 225f757f3fSDimitry Andric m_watch_read(read), m_watch_write(write) {} 235f757f3fSDimitry Andric 245f757f3fSDimitry Andric WatchpointResource::~WatchpointResource() { 255f757f3fSDimitry Andric std::lock_guard<std::mutex> guard(m_constituents_mutex); 265f757f3fSDimitry Andric m_constituents.clear(); 275f757f3fSDimitry Andric } 285f757f3fSDimitry Andric 295f757f3fSDimitry Andric addr_t WatchpointResource::GetLoadAddress() const { return m_addr; } 305f757f3fSDimitry Andric 315f757f3fSDimitry Andric size_t WatchpointResource::GetByteSize() const { return m_size; } 325f757f3fSDimitry Andric 335f757f3fSDimitry Andric bool WatchpointResource::WatchpointResourceRead() const { return m_watch_read; } 345f757f3fSDimitry Andric 355f757f3fSDimitry Andric bool WatchpointResource::WatchpointResourceWrite() const { 365f757f3fSDimitry Andric return m_watch_write; 375f757f3fSDimitry Andric } 385f757f3fSDimitry Andric 395f757f3fSDimitry Andric void WatchpointResource::SetType(bool read, bool write) { 405f757f3fSDimitry Andric m_watch_read = read; 415f757f3fSDimitry Andric m_watch_write = write; 425f757f3fSDimitry Andric } 435f757f3fSDimitry Andric 445f757f3fSDimitry Andric wp_resource_id_t WatchpointResource::GetID() const { return m_id; } 455f757f3fSDimitry Andric 465f757f3fSDimitry Andric bool WatchpointResource::Contains(addr_t addr) { 475f757f3fSDimitry Andric if (addr >= m_addr && addr < m_addr + m_size) 485f757f3fSDimitry Andric return true; 495f757f3fSDimitry Andric return false; 505f757f3fSDimitry Andric } 515f757f3fSDimitry Andric 525f757f3fSDimitry Andric void WatchpointResource::AddConstituent(const WatchpointSP &wp_sp) { 535f757f3fSDimitry Andric std::lock_guard<std::mutex> guard(m_constituents_mutex); 545f757f3fSDimitry Andric m_constituents.push_back(wp_sp); 555f757f3fSDimitry Andric } 565f757f3fSDimitry Andric 575f757f3fSDimitry Andric void WatchpointResource::RemoveConstituent(WatchpointSP &wp_sp) { 585f757f3fSDimitry Andric std::lock_guard<std::mutex> guard(m_constituents_mutex); 595f757f3fSDimitry Andric const auto &it = 605f757f3fSDimitry Andric std::find(m_constituents.begin(), m_constituents.end(), wp_sp); 615f757f3fSDimitry Andric if (it != m_constituents.end()) 625f757f3fSDimitry Andric m_constituents.erase(it); 635f757f3fSDimitry Andric } 645f757f3fSDimitry Andric 655f757f3fSDimitry Andric size_t WatchpointResource::GetNumberOfConstituents() { 665f757f3fSDimitry Andric std::lock_guard<std::mutex> guard(m_constituents_mutex); 675f757f3fSDimitry Andric return m_constituents.size(); 685f757f3fSDimitry Andric } 695f757f3fSDimitry Andric 705f757f3fSDimitry Andric bool WatchpointResource::ConstituentsContains(const WatchpointSP &wp_sp) { 715f757f3fSDimitry Andric return ConstituentsContains(wp_sp.get()); 725f757f3fSDimitry Andric } 735f757f3fSDimitry Andric 745f757f3fSDimitry Andric bool WatchpointResource::ConstituentsContains(const Watchpoint *wp) { 755f757f3fSDimitry Andric std::lock_guard<std::mutex> guard(m_constituents_mutex); 765f757f3fSDimitry Andric WatchpointCollection::const_iterator match = 775f757f3fSDimitry Andric std::find_if(m_constituents.begin(), m_constituents.end(), 785f757f3fSDimitry Andric [&wp](const WatchpointSP &x) { return x.get() == wp; }); 795f757f3fSDimitry Andric return match != m_constituents.end(); 805f757f3fSDimitry Andric } 815f757f3fSDimitry Andric 825f757f3fSDimitry Andric WatchpointSP WatchpointResource::GetConstituentAtIndex(size_t idx) { 835f757f3fSDimitry Andric std::lock_guard<std::mutex> guard(m_constituents_mutex); 845f757f3fSDimitry Andric assert(idx < m_constituents.size()); 855f757f3fSDimitry Andric if (idx >= m_constituents.size()) 865f757f3fSDimitry Andric return {}; 875f757f3fSDimitry Andric 885f757f3fSDimitry Andric return m_constituents[idx]; 895f757f3fSDimitry Andric } 905f757f3fSDimitry Andric 915f757f3fSDimitry Andric WatchpointResource::WatchpointCollection 925f757f3fSDimitry Andric WatchpointResource::CopyConstituentsList() { 935f757f3fSDimitry Andric std::lock_guard<std::mutex> guard(m_constituents_mutex); 945f757f3fSDimitry Andric return m_constituents; 955f757f3fSDimitry Andric } 965f757f3fSDimitry Andric 975f757f3fSDimitry Andric bool WatchpointResource::ShouldStop(StoppointCallbackContext *context) { 985f757f3fSDimitry Andric // LWP_TODO: Need to poll all Watchpoint constituents and see if 995f757f3fSDimitry Andric // we should stop, like BreakpointSites do. 1005f757f3fSDimitry Andric #if 0 1015f757f3fSDimitry Andric m_hit_counter.Increment(); 1025f757f3fSDimitry Andric // ShouldStop can do a lot of work, and might even come back and hit 1035f757f3fSDimitry Andric // this breakpoint site again. So don't hold the m_constituents_mutex the 1045f757f3fSDimitry Andric // whole while. Instead make a local copy of the collection and call 1055f757f3fSDimitry Andric // ShouldStop on the copy. 1065f757f3fSDimitry Andric WatchpointResourceCollection constituents_copy; 1075f757f3fSDimitry Andric { 1085f757f3fSDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex); 1095f757f3fSDimitry Andric constituents_copy = m_constituents; 1105f757f3fSDimitry Andric } 1115f757f3fSDimitry Andric return constituents_copy.ShouldStop(context); 1125f757f3fSDimitry Andric #endif 1135f757f3fSDimitry Andric return true; 1145f757f3fSDimitry Andric } 1155f757f3fSDimitry Andric 1165f757f3fSDimitry Andric void WatchpointResource::Dump(Stream *s) const { 117*0fca6ea1SDimitry Andric s->Printf("addr = 0x%8.8" PRIx64 " size = %zu", m_addr, m_size); 1185f757f3fSDimitry Andric } 1195f757f3fSDimitry Andric 1205f757f3fSDimitry Andric wp_resource_id_t WatchpointResource::GetNextID() { 1215f757f3fSDimitry Andric static wp_resource_id_t g_next_id = 0; 1225f757f3fSDimitry Andric return ++g_next_id; 1235f757f3fSDimitry Andric } 124