Path: blob/main/contrib/llvm-project/lldb/source/Breakpoint/WatchpointList.cpp
39587 views
//===-- WatchpointList.cpp ------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Breakpoint/WatchpointList.h"9#include "lldb/Breakpoint/Watchpoint.h"1011using namespace lldb;12using namespace lldb_private;1314WatchpointList::WatchpointList() = default;1516WatchpointList::~WatchpointList() = default;1718// Add a watchpoint to the list.19lldb::watch_id_t WatchpointList::Add(const WatchpointSP &wp_sp, bool notify) {20std::lock_guard<std::recursive_mutex> guard(m_mutex);21wp_sp->SetID(++m_next_wp_id);22m_watchpoints.push_back(wp_sp);23if (notify) {24if (wp_sp->GetTarget().EventTypeHasListeners(25Target::eBroadcastBitWatchpointChanged)) {26auto data_sp = std::make_shared<Watchpoint::WatchpointEventData>(27eWatchpointEventTypeAdded, wp_sp);28wp_sp->GetTarget().BroadcastEvent(Target::eBroadcastBitWatchpointChanged,29data_sp);30}31}32return wp_sp->GetID();33}3435void WatchpointList::Dump(Stream *s) const {36DumpWithLevel(s, lldb::eDescriptionLevelBrief);37}3839void WatchpointList::DumpWithLevel(40Stream *s, lldb::DescriptionLevel description_level) const {41std::lock_guard<std::recursive_mutex> guard(m_mutex);42s->Printf("%p: ", static_cast<const void *>(this));43// s->Indent();44s->Printf("WatchpointList with %" PRIu64 " Watchpoints:\n",45(uint64_t)m_watchpoints.size());46s->IndentMore();47wp_collection::const_iterator pos, end = m_watchpoints.end();48for (pos = m_watchpoints.begin(); pos != end; ++pos)49(*pos)->DumpWithLevel(s, description_level);50s->IndentLess();51}5253const WatchpointSP WatchpointList::FindByAddress(lldb::addr_t addr) const {54WatchpointSP wp_sp;55std::lock_guard<std::recursive_mutex> guard(m_mutex);56if (!m_watchpoints.empty()) {57wp_collection::const_iterator pos, end = m_watchpoints.end();58for (pos = m_watchpoints.begin(); pos != end; ++pos) {59lldb::addr_t wp_addr = (*pos)->GetLoadAddress();60uint32_t wp_bytesize = (*pos)->GetByteSize();61if ((wp_addr <= addr) && ((wp_addr + wp_bytesize) > addr)) {62wp_sp = *pos;63break;64}65}66}6768return wp_sp;69}7071const WatchpointSP WatchpointList::FindBySpec(std::string spec) const {72WatchpointSP wp_sp;73std::lock_guard<std::recursive_mutex> guard(m_mutex);74if (!m_watchpoints.empty()) {75wp_collection::const_iterator pos, end = m_watchpoints.end();76for (pos = m_watchpoints.begin(); pos != end; ++pos)77if ((*pos)->GetWatchSpec() == spec) {78wp_sp = *pos;79break;80}81}8283return wp_sp;84}8586class WatchpointIDMatches {87public:88WatchpointIDMatches(lldb::watch_id_t watch_id) : m_watch_id(watch_id) {}8990bool operator()(const WatchpointSP &wp) const {91return m_watch_id == wp->GetID();92}9394private:95const lldb::watch_id_t m_watch_id;96};9798WatchpointList::wp_collection::iterator99WatchpointList::GetIDIterator(lldb::watch_id_t watch_id) {100return std::find_if(m_watchpoints.begin(),101m_watchpoints.end(), // Search full range102WatchpointIDMatches(watch_id)); // Predicate103}104105WatchpointList::wp_collection::const_iterator106WatchpointList::GetIDConstIterator(lldb::watch_id_t watch_id) const {107return std::find_if(m_watchpoints.begin(),108m_watchpoints.end(), // Search full range109WatchpointIDMatches(watch_id)); // Predicate110}111112WatchpointSP WatchpointList::FindByID(lldb::watch_id_t watch_id) const {113WatchpointSP wp_sp;114std::lock_guard<std::recursive_mutex> guard(m_mutex);115wp_collection::const_iterator pos = GetIDConstIterator(watch_id);116if (pos != m_watchpoints.end())117wp_sp = *pos;118119return wp_sp;120}121122lldb::watch_id_t WatchpointList::FindIDByAddress(lldb::addr_t addr) {123WatchpointSP wp_sp = FindByAddress(addr);124if (wp_sp) {125return wp_sp->GetID();126}127return LLDB_INVALID_WATCH_ID;128}129130lldb::watch_id_t WatchpointList::FindIDBySpec(std::string spec) {131WatchpointSP wp_sp = FindBySpec(spec);132if (wp_sp) {133return wp_sp->GetID();134}135return LLDB_INVALID_WATCH_ID;136}137138WatchpointSP WatchpointList::GetByIndex(uint32_t i) {139std::lock_guard<std::recursive_mutex> guard(m_mutex);140WatchpointSP wp_sp;141if (i < m_watchpoints.size()) {142wp_collection::const_iterator pos = m_watchpoints.begin();143std::advance(pos, i);144wp_sp = *pos;145}146return wp_sp;147}148149const WatchpointSP WatchpointList::GetByIndex(uint32_t i) const {150std::lock_guard<std::recursive_mutex> guard(m_mutex);151WatchpointSP wp_sp;152if (i < m_watchpoints.size()) {153wp_collection::const_iterator pos = m_watchpoints.begin();154std::advance(pos, i);155wp_sp = *pos;156}157return wp_sp;158}159160std::vector<lldb::watch_id_t> WatchpointList::GetWatchpointIDs() const {161std::vector<lldb::watch_id_t> IDs;162wp_collection::const_iterator pos, end = m_watchpoints.end();163for (pos = m_watchpoints.begin(); pos != end; ++pos)164IDs.push_back((*pos)->GetID());165return IDs;166}167168bool WatchpointList::Remove(lldb::watch_id_t watch_id, bool notify) {169std::lock_guard<std::recursive_mutex> guard(m_mutex);170wp_collection::iterator pos = GetIDIterator(watch_id);171if (pos != m_watchpoints.end()) {172WatchpointSP wp_sp = *pos;173if (notify) {174if (wp_sp->GetTarget().EventTypeHasListeners(175Target::eBroadcastBitWatchpointChanged)) {176auto data_sp = std::make_shared<Watchpoint::WatchpointEventData>(177eWatchpointEventTypeRemoved, wp_sp);178wp_sp->GetTarget().BroadcastEvent(179Target::eBroadcastBitWatchpointChanged, data_sp);180}181}182m_watchpoints.erase(pos);183return true;184}185return false;186}187188uint32_t WatchpointList::GetHitCount() const {189uint32_t hit_count = 0;190std::lock_guard<std::recursive_mutex> guard(m_mutex);191wp_collection::const_iterator pos, end = m_watchpoints.end();192for (pos = m_watchpoints.begin(); pos != end; ++pos)193hit_count += (*pos)->GetHitCount();194return hit_count;195}196197bool WatchpointList::ShouldStop(StoppointCallbackContext *context,198lldb::watch_id_t watch_id) {199200WatchpointSP wp_sp = FindByID(watch_id);201if (wp_sp) {202// Let the Watchpoint decide if it should stop here (could not have reached203// it's target hit count yet, or it could have a callback that decided it204// shouldn't stop.205return wp_sp->ShouldStop(context);206}207// We should stop here since this Watchpoint isn't valid anymore or it208// doesn't exist.209return true;210}211212void WatchpointList::GetDescription(Stream *s, lldb::DescriptionLevel level) {213std::lock_guard<std::recursive_mutex> guard(m_mutex);214wp_collection::iterator pos, end = m_watchpoints.end();215216for (pos = m_watchpoints.begin(); pos != end; ++pos) {217s->Printf(" ");218(*pos)->Dump(s);219}220}221222void WatchpointList::SetEnabledAll(bool enabled) {223std::lock_guard<std::recursive_mutex> guard(m_mutex);224225wp_collection::iterator pos, end = m_watchpoints.end();226for (pos = m_watchpoints.begin(); pos != end; ++pos)227(*pos)->SetEnabled(enabled);228}229230void WatchpointList::RemoveAll(bool notify) {231std::lock_guard<std::recursive_mutex> guard(m_mutex);232if (notify) {233234{235wp_collection::iterator pos, end = m_watchpoints.end();236for (pos = m_watchpoints.begin(); pos != end; ++pos) {237if ((*pos)->GetTarget().EventTypeHasListeners(238Target::eBroadcastBitBreakpointChanged)) {239auto data_sp = std::make_shared<Watchpoint::WatchpointEventData>(240eWatchpointEventTypeRemoved, *pos);241(*pos)->GetTarget().BroadcastEvent(242Target::eBroadcastBitWatchpointChanged, data_sp);243}244}245}246}247m_watchpoints.clear();248}249250void WatchpointList::GetListMutex(251std::unique_lock<std::recursive_mutex> &lock) {252lock = std::unique_lock<std::recursive_mutex>(m_mutex);253}254255256