xref: /freebsd-src/contrib/llvm-project/lldb/source/Breakpoint/WatchpointResource.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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