1254721Semaste//===-- BreakpointList.cpp --------------------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9254721Semaste#include "lldb/Breakpoint/BreakpointList.h" 10254721Semaste 11254721Semaste#include "lldb/Target/Target.h" 12254721Semaste 13360784Sdim#include "llvm/Support/Errc.h" 14360784Sdim 15254721Semasteusing namespace lldb; 16254721Semasteusing namespace lldb_private; 17254721Semaste 18344779Sdimstatic void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) { 19344779Sdim Target &target = bp->GetTarget(); 20344779Sdim if (target.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged)) 21344779Sdim target.BroadcastEvent(Target::eBroadcastBitBreakpointChanged, 22344779Sdim new Breakpoint::BreakpointEventData(event, bp)); 23344779Sdim} 24344779Sdim 25309124SdimBreakpointList::BreakpointList(bool is_internal) 26314564Sdim : m_mutex(), m_breakpoints(), m_next_break_id(0), 27314564Sdim m_is_internal(is_internal) {} 28254721Semaste 29314564SdimBreakpointList::~BreakpointList() {} 30254721Semaste 31314564Sdimbreak_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) { 32314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 33344779Sdim 34314564Sdim // Internal breakpoint IDs are negative, normal ones are positive 35314564Sdim bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id); 36254721Semaste 37314564Sdim m_breakpoints.push_back(bp_sp); 38344779Sdim 39344779Sdim if (notify) 40344779Sdim NotifyChange(bp_sp, eBreakpointEventTypeAdded); 41344779Sdim 42314564Sdim return bp_sp->GetID(); 43254721Semaste} 44254721Semaste 45314564Sdimbool BreakpointList::Remove(break_id_t break_id, bool notify) { 46314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 47344779Sdim 48344779Sdim auto it = std::find_if( 49344779Sdim m_breakpoints.begin(), m_breakpoints.end(), 50344779Sdim [&](const BreakpointSP &bp) { return bp->GetID() == break_id; }); 51344779Sdim 52344779Sdim if (it == m_breakpoints.end()) 53344779Sdim return false; 54344779Sdim 55344779Sdim if (notify) 56344779Sdim NotifyChange(*it, eBreakpointEventTypeRemoved); 57344779Sdim 58344779Sdim m_breakpoints.erase(it); 59344779Sdim 60344779Sdim return true; 61254721Semaste} 62254721Semaste 63314564Sdimvoid BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) { 64314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 65314564Sdim for (const auto &bp_sp : m_breakpoints) 66314564Sdim bp_sp->RemoveInvalidLocations(arch); 67258884Semaste} 68258884Semaste 69314564Sdimvoid BreakpointList::SetEnabledAll(bool enabled) { 70314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 71314564Sdim for (const auto &bp_sp : m_breakpoints) 72314564Sdim bp_sp->SetEnabled(enabled); 73254721Semaste} 74254721Semaste 75327952Sdimvoid BreakpointList::SetEnabledAllowed(bool enabled) { 76327952Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 77327952Sdim for (const auto &bp_sp : m_breakpoints) 78327952Sdim if (bp_sp->AllowDisable()) 79327952Sdim bp_sp->SetEnabled(enabled); 80327952Sdim} 81327952Sdim 82314564Sdimvoid BreakpointList::RemoveAll(bool notify) { 83314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 84314564Sdim ClearAllBreakpointSites(); 85254721Semaste 86314564Sdim if (notify) { 87344779Sdim for (const auto &bp_sp : m_breakpoints) 88344779Sdim NotifyChange(bp_sp, eBreakpointEventTypeRemoved); 89314564Sdim } 90344779Sdim 91344779Sdim m_breakpoints.clear(); 92254721Semaste} 93254721Semaste 94327952Sdimvoid BreakpointList::RemoveAllowed(bool notify) { 95327952Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 96341825Sdim 97344779Sdim for (const auto &bp_sp : m_breakpoints) { 98344779Sdim if (bp_sp->AllowDelete()) 99344779Sdim bp_sp->ClearAllBreakpointSites(); 100344779Sdim if (notify) 101344779Sdim NotifyChange(bp_sp, eBreakpointEventTypeRemoved); 102327952Sdim } 103344779Sdim 104344779Sdim m_breakpoints.erase( 105344779Sdim std::remove_if(m_breakpoints.begin(), m_breakpoints.end(), 106344779Sdim [&](const BreakpointSP &bp) { return bp->AllowDelete(); }), 107344779Sdim m_breakpoints.end()); 108327952Sdim} 109327952Sdim 110254721SemasteBreakpointList::bp_collection::iterator 111314564SdimBreakpointList::GetBreakpointIDIterator(break_id_t break_id) { 112344779Sdim return std::find_if( 113344779Sdim m_breakpoints.begin(), m_breakpoints.end(), 114344779Sdim [&](const BreakpointSP &bp) { return bp->GetID() == break_id; }); 115254721Semaste} 116254721Semaste 117254721SemasteBreakpointList::bp_collection::const_iterator 118314564SdimBreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const { 119344779Sdim return std::find_if( 120344779Sdim m_breakpoints.begin(), m_breakpoints.end(), 121344779Sdim [&](const BreakpointSP &bp) { return bp->GetID() == break_id; }); 122254721Semaste} 123254721Semaste 124344779SdimBreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const { 125314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 126254721Semaste 127344779Sdim auto it = GetBreakpointIDConstIterator(break_id); 128344779Sdim if (it != m_breakpoints.end()) 129344779Sdim return *it; 130344779Sdim return {}; 131254721Semaste} 132254721Semaste 133360784Sdimllvm::Expected<std::vector<lldb::BreakpointSP>> 134360784SdimBreakpointList::FindBreakpointsByName(const char *name) { 135314564Sdim if (!name) 136360784Sdim return llvm::createStringError(llvm::errc::invalid_argument, 137360784Sdim "FindBreakpointsByName requires a name"); 138254721Semaste 139360784Sdim Status error; 140314564Sdim if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error)) 141360784Sdim return error.ToError(); 142254721Semaste 143360784Sdim std::vector<lldb::BreakpointSP> matching_bps; 144314564Sdim for (BreakpointSP bkpt_sp : Breakpoints()) { 145314564Sdim if (bkpt_sp->MatchesName(name)) { 146360784Sdim matching_bps.push_back(bkpt_sp); 147254721Semaste } 148314564Sdim } 149344779Sdim 150360784Sdim return matching_bps; 151254721Semaste} 152254721Semaste 153314564Sdimvoid BreakpointList::Dump(Stream *s) const { 154314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 155314564Sdim s->Printf("%p: ", static_cast<const void *>(this)); 156314564Sdim s->Indent(); 157314564Sdim s->Printf("BreakpointList with %u Breakpoints:\n", 158314564Sdim (uint32_t)m_breakpoints.size()); 159314564Sdim s->IndentMore(); 160314564Sdim for (const auto &bp_sp : m_breakpoints) 161314564Sdim bp_sp->Dump(s); 162314564Sdim s->IndentLess(); 163254721Semaste} 164254721Semaste 165344779SdimBreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const { 166314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 167344779Sdim if (i < m_breakpoints.size()) 168344779Sdim return m_breakpoints[i]; 169344779Sdim return {}; 170314564Sdim} 171254721Semaste 172314564Sdimvoid BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added, 173314564Sdim bool delete_locations) { 174314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 175314564Sdim for (const auto &bp_sp : m_breakpoints) 176314564Sdim bp_sp->ModulesChanged(module_list, added, delete_locations); 177314564Sdim} 178254721Semaste 179314564Sdimvoid BreakpointList::UpdateBreakpointsWhenModuleIsReplaced( 180314564Sdim ModuleSP old_module_sp, ModuleSP new_module_sp) { 181314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 182314564Sdim for (const auto &bp_sp : m_breakpoints) 183314564Sdim bp_sp->ModuleReplaced(old_module_sp, new_module_sp); 184254721Semaste} 185254721Semaste 186314564Sdimvoid BreakpointList::ClearAllBreakpointSites() { 187314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 188314564Sdim for (const auto &bp_sp : m_breakpoints) 189314564Sdim bp_sp->ClearAllBreakpointSites(); 190254721Semaste} 191254721Semaste 192314564Sdimvoid BreakpointList::GetListMutex( 193314564Sdim std::unique_lock<std::recursive_mutex> &lock) { 194314564Sdim lock = std::unique_lock<std::recursive_mutex>(m_mutex); 195254721Semaste} 196