//===-- BreakpointList.cpp --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Breakpoint/BreakpointList.h" // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; BreakpointList::BreakpointList(bool is_internal) : m_mutex(), m_breakpoints(), m_next_break_id(0), m_is_internal(is_internal) {} BreakpointList::~BreakpointList() {} break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) { std::lock_guard guard(m_mutex); // Internal breakpoint IDs are negative, normal ones are positive bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id); m_breakpoints.push_back(bp_sp); if (notify) { if (bp_sp->GetTarget().EventTypeHasListeners( Target::eBroadcastBitBreakpointChanged)) bp_sp->GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged, new Breakpoint::BreakpointEventData( eBreakpointEventTypeAdded, bp_sp)); } return bp_sp->GetID(); } bool BreakpointList::Remove(break_id_t break_id, bool notify) { std::lock_guard guard(m_mutex); bp_collection::iterator pos = GetBreakpointIDIterator(break_id); // Predicate if (pos != m_breakpoints.end()) { BreakpointSP bp_sp(*pos); m_breakpoints.erase(pos); if (notify) { if (bp_sp->GetTarget().EventTypeHasListeners( Target::eBroadcastBitBreakpointChanged)) bp_sp->GetTarget().BroadcastEvent( Target::eBroadcastBitBreakpointChanged, new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved, bp_sp)); } return true; } return false; } void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) { std::lock_guard guard(m_mutex); for (const auto &bp_sp : m_breakpoints) bp_sp->RemoveInvalidLocations(arch); } void BreakpointList::SetEnabledAll(bool enabled) { std::lock_guard guard(m_mutex); for (const auto &bp_sp : m_breakpoints) bp_sp->SetEnabled(enabled); } void BreakpointList::SetEnabledAllowed(bool enabled) { std::lock_guard guard(m_mutex); for (const auto &bp_sp : m_breakpoints) if (bp_sp->AllowDisable()) bp_sp->SetEnabled(enabled); } void BreakpointList::RemoveAll(bool notify) { std::lock_guard guard(m_mutex); ClearAllBreakpointSites(); if (notify) { bp_collection::iterator pos, end = m_breakpoints.end(); for (pos = m_breakpoints.begin(); pos != end; ++pos) { if ((*pos)->GetTarget().EventTypeHasListeners( Target::eBroadcastBitBreakpointChanged)) { (*pos)->GetTarget().BroadcastEvent( Target::eBroadcastBitBreakpointChanged, new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved, *pos)); } } } m_breakpoints.erase(m_breakpoints.begin(), m_breakpoints.end()); } void BreakpointList::RemoveAllowed(bool notify) { std::lock_guard guard(m_mutex); bp_collection::iterator pos, end = m_breakpoints.end(); if (notify) { for (pos = m_breakpoints.begin(); pos != end; ++pos) { if(!(*pos)->AllowDelete()) continue; if ((*pos)->GetTarget().EventTypeHasListeners( Target::eBroadcastBitBreakpointChanged)) { (*pos)->GetTarget().BroadcastEvent( Target::eBroadcastBitBreakpointChanged, new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved, *pos)); } } } pos = m_breakpoints.begin(); while ( pos != end) { auto bp = *pos; if (bp->AllowDelete()) { bp->ClearAllBreakpointSites(); pos = m_breakpoints.erase(pos); } else pos++; } } class BreakpointIDMatches { public: BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {} bool operator()(const BreakpointSP &bp) const { return m_break_id == bp->GetID(); } private: const break_id_t m_break_id; }; BreakpointList::bp_collection::iterator BreakpointList::GetBreakpointIDIterator(break_id_t break_id) { return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range BreakpointIDMatches(break_id)); // Predicate } BreakpointList::bp_collection::const_iterator BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const { return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range BreakpointIDMatches(break_id)); // Predicate } BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) { std::lock_guard guard(m_mutex); BreakpointSP stop_sp; bp_collection::iterator pos = GetBreakpointIDIterator(break_id); if (pos != m_breakpoints.end()) stop_sp = *pos; return stop_sp; } const BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const { std::lock_guard guard(m_mutex); BreakpointSP stop_sp; bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id); if (pos != m_breakpoints.end()) stop_sp = *pos; return stop_sp; } bool BreakpointList::FindBreakpointsByName(const char *name, BreakpointList &matching_bps) { Status error; if (!name) return false; if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error)) return false; for (BreakpointSP bkpt_sp : Breakpoints()) { if (bkpt_sp->MatchesName(name)) { matching_bps.Add(bkpt_sp, false); } } return true; } void BreakpointList::Dump(Stream *s) const { std::lock_guard guard(m_mutex); s->Printf("%p: ", static_cast(this)); s->Indent(); s->Printf("BreakpointList with %u Breakpoints:\n", (uint32_t)m_breakpoints.size()); s->IndentMore(); for (const auto &bp_sp : m_breakpoints) bp_sp->Dump(s); s->IndentLess(); } BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) { std::lock_guard guard(m_mutex); BreakpointSP stop_sp; bp_collection::iterator end = m_breakpoints.end(); bp_collection::iterator pos; size_t curr_i = 0; for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) { if (curr_i == i) stop_sp = *pos; } return stop_sp; } const BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const { std::lock_guard guard(m_mutex); BreakpointSP stop_sp; bp_collection::const_iterator end = m_breakpoints.end(); bp_collection::const_iterator pos; size_t curr_i = 0; for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) { if (curr_i == i) stop_sp = *pos; } return stop_sp; } void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added, bool delete_locations) { std::lock_guard guard(m_mutex); for (const auto &bp_sp : m_breakpoints) bp_sp->ModulesChanged(module_list, added, delete_locations); } void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced( ModuleSP old_module_sp, ModuleSP new_module_sp) { std::lock_guard guard(m_mutex); for (const auto &bp_sp : m_breakpoints) bp_sp->ModuleReplaced(old_module_sp, new_module_sp); } void BreakpointList::ClearAllBreakpointSites() { std::lock_guard guard(m_mutex); for (const auto &bp_sp : m_breakpoints) bp_sp->ClearAllBreakpointSites(); } void BreakpointList::GetListMutex( std::unique_lock &lock) { lock = std::unique_lock(m_mutex); }