196 lines · cpp
1//===-- BreakpointList.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Breakpoint/BreakpointList.h"10 11#include "lldb/Target/Target.h"12 13#include "llvm/Support/Errc.h"14 15using namespace lldb;16using namespace lldb_private;17 18static void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) {19 bp->GetTarget().NotifyBreakpointChanged(*bp, event);20}21 22BreakpointList::BreakpointList(bool is_internal)23 : m_next_break_id(0), m_is_internal(is_internal) {}24 25BreakpointList::~BreakpointList() = default;26 27break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {28 std::lock_guard<std::recursive_mutex> guard(m_mutex);29 30 // Internal breakpoint IDs are negative, normal ones are positive31 bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);32 33 m_breakpoints.push_back(bp_sp);34 35 if (notify)36 NotifyChange(bp_sp, eBreakpointEventTypeAdded);37 38 return bp_sp->GetID();39}40 41bool BreakpointList::Remove(break_id_t break_id, bool notify) {42 std::lock_guard<std::recursive_mutex> guard(m_mutex);43 44 auto it = llvm::find_if(m_breakpoints, [&](const BreakpointSP &bp) {45 return bp->GetID() == break_id;46 });47 48 if (it == m_breakpoints.end())49 return false;50 51 if (notify)52 NotifyChange(*it, eBreakpointEventTypeRemoved);53 54 m_breakpoints.erase(it);55 56 return true;57}58 59void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {60 std::lock_guard<std::recursive_mutex> guard(m_mutex);61 for (const auto &bp_sp : m_breakpoints)62 bp_sp->RemoveInvalidLocations(arch);63}64 65void BreakpointList::SetEnabledAll(bool enabled) {66 std::lock_guard<std::recursive_mutex> guard(m_mutex);67 for (const auto &bp_sp : m_breakpoints)68 bp_sp->SetEnabled(enabled);69}70 71void BreakpointList::SetEnabledAllowed(bool enabled) {72 std::lock_guard<std::recursive_mutex> guard(m_mutex);73 for (const auto &bp_sp : m_breakpoints)74 if (bp_sp->AllowDisable())75 bp_sp->SetEnabled(enabled);76}77 78void BreakpointList::RemoveAll(bool notify) {79 std::lock_guard<std::recursive_mutex> guard(m_mutex);80 ClearAllBreakpointSites();81 82 if (notify) {83 for (const auto &bp_sp : m_breakpoints)84 NotifyChange(bp_sp, eBreakpointEventTypeRemoved);85 }86 87 m_breakpoints.clear();88}89 90void BreakpointList::RemoveAllowed(bool notify) {91 std::lock_guard<std::recursive_mutex> guard(m_mutex);92 93 for (const auto &bp_sp : m_breakpoints) {94 if (bp_sp->AllowDelete())95 bp_sp->ClearAllBreakpointSites();96 if (notify)97 NotifyChange(bp_sp, eBreakpointEventTypeRemoved);98 }99 100 llvm::erase_if(m_breakpoints,101 [&](const BreakpointSP &bp) { return bp->AllowDelete(); });102}103 104BreakpointList::bp_collection::iterator105BreakpointList::GetBreakpointIDIterator(break_id_t break_id) {106 return llvm::find_if(m_breakpoints, [&](const BreakpointSP &bp) {107 return bp->GetID() == break_id;108 });109}110 111BreakpointList::bp_collection::const_iterator112BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {113 return llvm::find_if(m_breakpoints, [&](const BreakpointSP &bp) {114 return bp->GetID() == break_id;115 });116}117 118BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const {119 std::lock_guard<std::recursive_mutex> guard(m_mutex);120 121 auto it = GetBreakpointIDConstIterator(break_id);122 if (it != m_breakpoints.end())123 return *it;124 return {};125}126 127llvm::Expected<std::vector<lldb::BreakpointSP>>128BreakpointList::FindBreakpointsByName(const char *name) {129 if (!name)130 return llvm::createStringError(llvm::errc::invalid_argument,131 "FindBreakpointsByName requires a name");132 133 Status error;134 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))135 return error.ToError();136 137 std::vector<lldb::BreakpointSP> matching_bps;138 for (BreakpointSP bkpt_sp : Breakpoints()) {139 if (bkpt_sp->MatchesName(name)) {140 matching_bps.push_back(bkpt_sp);141 }142 }143 144 return matching_bps;145}146 147void BreakpointList::Dump(Stream *s) const {148 std::lock_guard<std::recursive_mutex> guard(m_mutex);149 s->Printf("%p: ", static_cast<const void *>(this));150 s->Indent();151 s->Printf("BreakpointList with %u Breakpoints:\n",152 (uint32_t)m_breakpoints.size());153 s->IndentMore();154 for (const auto &bp_sp : m_breakpoints)155 bp_sp->Dump(s);156 s->IndentLess();157}158 159BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {160 std::lock_guard<std::recursive_mutex> guard(m_mutex);161 if (i < m_breakpoints.size())162 return m_breakpoints[i];163 return {};164}165 166void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,167 bool delete_locations) {168 std::lock_guard<std::recursive_mutex> guard(m_mutex);169 for (const auto &bp_sp : m_breakpoints)170 bp_sp->ModulesChanged(module_list, added, delete_locations);171}172 173void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(174 ModuleSP old_module_sp, ModuleSP new_module_sp) {175 std::lock_guard<std::recursive_mutex> guard(m_mutex);176 for (const auto &bp_sp : m_breakpoints)177 bp_sp->ModuleReplaced(old_module_sp, new_module_sp);178}179 180void BreakpointList::ClearAllBreakpointSites() {181 std::lock_guard<std::recursive_mutex> guard(m_mutex);182 for (const auto &bp_sp : m_breakpoints)183 bp_sp->ClearAllBreakpointSites();184}185 186void BreakpointList::ResetHitCounts() {187 std::lock_guard<std::recursive_mutex> guard(m_mutex);188 for (const auto &bp_sp : m_breakpoints)189 bp_sp->ResetHitCount();190}191 192void BreakpointList::GetListMutex(193 std::unique_lock<std::recursive_mutex> &lock) {194 lock = std::unique_lock<std::recursive_mutex>(m_mutex);195}196