130fdc8d8SChris Lattner //===-- BreakpointSiteList.cpp ----------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointSiteList.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1630fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 17ebb81bebSEli Friedman #include <algorithm> 1830fdc8d8SChris Lattner 1930fdc8d8SChris Lattner using namespace lldb; 2030fdc8d8SChris Lattner using namespace lldb_private; 2130fdc8d8SChris Lattner 2230fdc8d8SChris Lattner BreakpointSiteList::BreakpointSiteList() : 2330fdc8d8SChris Lattner m_bp_site_list() 2430fdc8d8SChris Lattner { 2530fdc8d8SChris Lattner } 2630fdc8d8SChris Lattner 2730fdc8d8SChris Lattner BreakpointSiteList::~BreakpointSiteList() 2830fdc8d8SChris Lattner { 2930fdc8d8SChris Lattner } 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner // Add breakpoint site to the list. However, if the element already exists in the 3230fdc8d8SChris Lattner // list, then we don't add it, and return LLDB_INVALID_BREAK_ID. 3330fdc8d8SChris Lattner 34c982c768SGreg Clayton lldb::break_id_t 3530fdc8d8SChris Lattner BreakpointSiteList::Add(const BreakpointSiteSP &bp) 3630fdc8d8SChris Lattner { 3730fdc8d8SChris Lattner lldb::addr_t bp_site_load_addr = bp->GetLoadAddress(); 3830fdc8d8SChris Lattner collection::iterator iter = m_bp_site_list.find (bp_site_load_addr); 3930fdc8d8SChris Lattner 4030fdc8d8SChris Lattner if (iter == m_bp_site_list.end()) 4130fdc8d8SChris Lattner { 4230fdc8d8SChris Lattner m_bp_site_list.insert (iter, collection::value_type (bp_site_load_addr, bp)); 4330fdc8d8SChris Lattner return bp->GetID(); 4430fdc8d8SChris Lattner } 4530fdc8d8SChris Lattner else 4630fdc8d8SChris Lattner { 4730fdc8d8SChris Lattner return LLDB_INVALID_BREAK_ID; 4830fdc8d8SChris Lattner } 4930fdc8d8SChris Lattner } 5030fdc8d8SChris Lattner 5130fdc8d8SChris Lattner bool 52f4b47e15SGreg Clayton BreakpointSiteList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t site_id) 5330fdc8d8SChris Lattner { 54f4b47e15SGreg Clayton BreakpointSiteSP site_sp (FindByID (site_id)); 55f4b47e15SGreg Clayton if (site_sp) 5630fdc8d8SChris Lattner { 5730fdc8d8SChris Lattner // Let the BreakpointSite decide if it should stop here (could not have 5830fdc8d8SChris Lattner // reached it's target hit count yet, or it could have a callback 5930fdc8d8SChris Lattner // that decided it shouldn't stop (shared library loads/unloads). 60f4b47e15SGreg Clayton return site_sp->ShouldStop (context); 6130fdc8d8SChris Lattner } 6230fdc8d8SChris Lattner // We should stop here since this BreakpointSite isn't valid anymore or it 6330fdc8d8SChris Lattner // doesn't exist. 6430fdc8d8SChris Lattner return true; 6530fdc8d8SChris Lattner } 66c982c768SGreg Clayton lldb::break_id_t 6730fdc8d8SChris Lattner BreakpointSiteList::FindIDByAddress (lldb::addr_t addr) 6830fdc8d8SChris Lattner { 6930fdc8d8SChris Lattner BreakpointSiteSP bp = FindByAddress (addr); 7030fdc8d8SChris Lattner if (bp) 7130fdc8d8SChris Lattner { 72d01b2953SDaniel Malea //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" PRIx64 " ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID()); 7330fdc8d8SChris Lattner return bp.get()->GetID(); 7430fdc8d8SChris Lattner } 75d01b2953SDaniel Malea //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" PRIx64 " ) => NONE", __FUNCTION__, (uint64_t)addr); 7630fdc8d8SChris Lattner return LLDB_INVALID_BREAK_ID; 7730fdc8d8SChris Lattner } 7830fdc8d8SChris Lattner 7930fdc8d8SChris Lattner bool 80c982c768SGreg Clayton BreakpointSiteList::Remove (lldb::break_id_t break_id) 8130fdc8d8SChris Lattner { 8230fdc8d8SChris Lattner collection::iterator pos = GetIDIterator(break_id); // Predicate 8330fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 8430fdc8d8SChris Lattner { 8530fdc8d8SChris Lattner m_bp_site_list.erase(pos); 8630fdc8d8SChris Lattner return true; 8730fdc8d8SChris Lattner } 8830fdc8d8SChris Lattner return false; 8930fdc8d8SChris Lattner } 9030fdc8d8SChris Lattner 9130fdc8d8SChris Lattner bool 9230fdc8d8SChris Lattner BreakpointSiteList::RemoveByAddress (lldb::addr_t address) 9330fdc8d8SChris Lattner { 9430fdc8d8SChris Lattner collection::iterator pos = m_bp_site_list.find(address); 9530fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 9630fdc8d8SChris Lattner { 9730fdc8d8SChris Lattner m_bp_site_list.erase(pos); 9830fdc8d8SChris Lattner return true; 9930fdc8d8SChris Lattner } 10030fdc8d8SChris Lattner return false; 10130fdc8d8SChris Lattner } 10230fdc8d8SChris Lattner 10330fdc8d8SChris Lattner class BreakpointSiteIDMatches 10430fdc8d8SChris Lattner { 10530fdc8d8SChris Lattner public: 106c982c768SGreg Clayton BreakpointSiteIDMatches (lldb::break_id_t break_id) : 10730fdc8d8SChris Lattner m_break_id(break_id) 10830fdc8d8SChris Lattner { 10930fdc8d8SChris Lattner } 11030fdc8d8SChris Lattner 11130fdc8d8SChris Lattner bool operator() (std::pair <lldb::addr_t, BreakpointSiteSP> val_pair) const 11230fdc8d8SChris Lattner { 11330fdc8d8SChris Lattner return m_break_id == val_pair.second.get()->GetID(); 11430fdc8d8SChris Lattner } 11530fdc8d8SChris Lattner 11630fdc8d8SChris Lattner private: 117c982c768SGreg Clayton const lldb::break_id_t m_break_id; 11830fdc8d8SChris Lattner }; 11930fdc8d8SChris Lattner 12030fdc8d8SChris Lattner BreakpointSiteList::collection::iterator 121c982c768SGreg Clayton BreakpointSiteList::GetIDIterator (lldb::break_id_t break_id) 12230fdc8d8SChris Lattner { 12330fdc8d8SChris Lattner return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range 12430fdc8d8SChris Lattner BreakpointSiteIDMatches(break_id)); // Predicate 12530fdc8d8SChris Lattner } 12630fdc8d8SChris Lattner 12730fdc8d8SChris Lattner BreakpointSiteList::collection::const_iterator 128c982c768SGreg Clayton BreakpointSiteList::GetIDConstIterator (lldb::break_id_t break_id) const 12930fdc8d8SChris Lattner { 13030fdc8d8SChris Lattner return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range 13130fdc8d8SChris Lattner BreakpointSiteIDMatches(break_id)); // Predicate 13230fdc8d8SChris Lattner } 13330fdc8d8SChris Lattner 13430fdc8d8SChris Lattner BreakpointSiteSP 135c982c768SGreg Clayton BreakpointSiteList::FindByID (lldb::break_id_t break_id) 13630fdc8d8SChris Lattner { 13730fdc8d8SChris Lattner BreakpointSiteSP stop_sp; 13830fdc8d8SChris Lattner collection::iterator pos = GetIDIterator(break_id); 13930fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 14030fdc8d8SChris Lattner stop_sp = pos->second; 14130fdc8d8SChris Lattner 14230fdc8d8SChris Lattner return stop_sp; 14330fdc8d8SChris Lattner } 14430fdc8d8SChris Lattner 14530fdc8d8SChris Lattner const BreakpointSiteSP 146c982c768SGreg Clayton BreakpointSiteList::FindByID (lldb::break_id_t break_id) const 14730fdc8d8SChris Lattner { 14830fdc8d8SChris Lattner BreakpointSiteSP stop_sp; 14930fdc8d8SChris Lattner collection::const_iterator pos = GetIDConstIterator(break_id); 15030fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 15130fdc8d8SChris Lattner stop_sp = pos->second; 15230fdc8d8SChris Lattner 15330fdc8d8SChris Lattner return stop_sp; 15430fdc8d8SChris Lattner } 15530fdc8d8SChris Lattner 15630fdc8d8SChris Lattner BreakpointSiteSP 15730fdc8d8SChris Lattner BreakpointSiteList::FindByAddress (lldb::addr_t addr) 15830fdc8d8SChris Lattner { 15930fdc8d8SChris Lattner BreakpointSiteSP found_sp; 16030fdc8d8SChris Lattner 16130fdc8d8SChris Lattner collection::iterator iter = m_bp_site_list.find(addr); 16230fdc8d8SChris Lattner if (iter != m_bp_site_list.end()) 16330fdc8d8SChris Lattner found_sp = iter->second; 16430fdc8d8SChris Lattner return found_sp; 16530fdc8d8SChris Lattner } 16630fdc8d8SChris Lattner 167564d8bc2SJim Ingham bool 168564d8bc2SJim Ingham BreakpointSiteList::BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id) 169564d8bc2SJim Ingham { 170564d8bc2SJim Ingham collection::const_iterator pos = GetIDConstIterator(bp_site_id); 171564d8bc2SJim Ingham if (pos != m_bp_site_list.end()) 172*367efe7dSJim Ingham return pos->second->IsBreakpointAtThisSite (bp_id); 173564d8bc2SJim Ingham 174564d8bc2SJim Ingham return false; 175564d8bc2SJim Ingham } 176564d8bc2SJim Ingham 17730fdc8d8SChris Lattner void 17830fdc8d8SChris Lattner BreakpointSiteList::Dump (Stream *s) const 17930fdc8d8SChris Lattner { 180fd54b368SJason Molenda s->Printf("%p: ", this); 181ded470d3SGreg Clayton //s->Indent(); 18230fdc8d8SChris Lattner s->Printf("BreakpointSiteList with %u BreakpointSites:\n", (uint32_t)m_bp_site_list.size()); 18330fdc8d8SChris Lattner s->IndentMore(); 18430fdc8d8SChris Lattner collection::const_iterator pos; 18530fdc8d8SChris Lattner collection::const_iterator end = m_bp_site_list.end(); 18630fdc8d8SChris Lattner for (pos = m_bp_site_list.begin(); pos != end; ++pos) 18730fdc8d8SChris Lattner pos->second.get()->Dump(s); 18830fdc8d8SChris Lattner s->IndentLess(); 18930fdc8d8SChris Lattner } 19030fdc8d8SChris Lattner 19130fdc8d8SChris Lattner 19230fdc8d8SChris Lattner BreakpointSiteSP 19330fdc8d8SChris Lattner BreakpointSiteList::GetByIndex (uint32_t i) 19430fdc8d8SChris Lattner { 19530fdc8d8SChris Lattner BreakpointSiteSP stop_sp; 19630fdc8d8SChris Lattner collection::iterator end = m_bp_site_list.end(); 19730fdc8d8SChris Lattner collection::iterator pos; 19830fdc8d8SChris Lattner uint32_t curr_i = 0; 19930fdc8d8SChris Lattner for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) 20030fdc8d8SChris Lattner { 20130fdc8d8SChris Lattner if (curr_i == i) 20230fdc8d8SChris Lattner stop_sp = pos->second; 20330fdc8d8SChris Lattner } 20430fdc8d8SChris Lattner return stop_sp; 20530fdc8d8SChris Lattner } 20630fdc8d8SChris Lattner 20730fdc8d8SChris Lattner const BreakpointSiteSP 20830fdc8d8SChris Lattner BreakpointSiteList::GetByIndex (uint32_t i) const 20930fdc8d8SChris Lattner { 21030fdc8d8SChris Lattner BreakpointSiteSP stop_sp; 21130fdc8d8SChris Lattner collection::const_iterator end = m_bp_site_list.end(); 21230fdc8d8SChris Lattner collection::const_iterator pos; 21330fdc8d8SChris Lattner uint32_t curr_i = 0; 21430fdc8d8SChris Lattner for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) 21530fdc8d8SChris Lattner { 21630fdc8d8SChris Lattner if (curr_i == i) 21730fdc8d8SChris Lattner stop_sp = pos->second; 21830fdc8d8SChris Lattner } 21930fdc8d8SChris Lattner return stop_sp; 22030fdc8d8SChris Lattner } 22130fdc8d8SChris Lattner 22220c77199SJim Ingham bool 22320c77199SJim Ingham BreakpointSiteList::FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const 22420c77199SJim Ingham { 22520c77199SJim Ingham 22620c77199SJim Ingham if (lower_bound > upper_bound) 22720c77199SJim Ingham return false; 22820c77199SJim Ingham 22920c77199SJim Ingham collection::const_iterator lower, upper, pos; 23020c77199SJim Ingham lower = m_bp_site_list.lower_bound(lower_bound); 23120c77199SJim Ingham if (lower == m_bp_site_list.end() 23220c77199SJim Ingham || (*lower).first >= upper_bound) 23320c77199SJim Ingham return false; 23420c77199SJim Ingham 23520c77199SJim Ingham // This is one tricky bit. The breakpoint might overlap the bottom end of the range. So we grab the 23620c77199SJim Ingham // breakpoint prior to the lower bound, and check that that + its byte size isn't in our range. 23720c77199SJim Ingham if (lower != m_bp_site_list.begin()) 23820c77199SJim Ingham { 23920c77199SJim Ingham collection::const_iterator prev_pos = lower; 24020c77199SJim Ingham prev_pos--; 24120c77199SJim Ingham const BreakpointSiteSP &prev_bp = (*prev_pos).second; 24220c77199SJim Ingham if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound) 24320c77199SJim Ingham bp_site_list.Add (prev_bp); 24420c77199SJim Ingham 24520c77199SJim Ingham } 24620c77199SJim Ingham 24720c77199SJim Ingham upper = m_bp_site_list.upper_bound(upper_bound); 24820c77199SJim Ingham 24920c77199SJim Ingham for (pos = lower; pos != upper; pos++) 25020c77199SJim Ingham { 25120c77199SJim Ingham bp_site_list.Add ((*pos).second); 25220c77199SJim Ingham } 25320c77199SJim Ingham return true; 25420c77199SJim Ingham } 25520c77199SJim Ingham 25620c77199SJim Ingham 25730fdc8d8SChris Lattner void 258c982c768SGreg Clayton BreakpointSiteList::SetEnabledForAll (const bool enabled, const lldb::break_id_t except_id) 25930fdc8d8SChris Lattner { 26030fdc8d8SChris Lattner collection::iterator end = m_bp_site_list.end(); 26130fdc8d8SChris Lattner collection::iterator pos; 26230fdc8d8SChris Lattner for (pos = m_bp_site_list.begin(); pos != end; ++pos) 26330fdc8d8SChris Lattner { 26430fdc8d8SChris Lattner if (except_id != LLDB_INVALID_BREAK_ID && except_id != pos->second->GetID()) 26530fdc8d8SChris Lattner pos->second->SetEnabled (enabled); 26630fdc8d8SChris Lattner else 26730fdc8d8SChris Lattner pos->second->SetEnabled (!enabled); 26830fdc8d8SChris Lattner } 26930fdc8d8SChris Lattner } 27030fdc8d8SChris Lattner 27130fdc8d8SChris Lattner const BreakpointSiteList::collection * 27230fdc8d8SChris Lattner BreakpointSiteList::GetMap () 27330fdc8d8SChris Lattner { 27430fdc8d8SChris Lattner return &m_bp_site_list; 27530fdc8d8SChris Lattner } 276