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() : 23d8cf1a11SGreg Clayton m_mutex (Mutex::eMutexTypeRecursive), 2430fdc8d8SChris Lattner m_bp_site_list() 2530fdc8d8SChris Lattner { 2630fdc8d8SChris Lattner } 2730fdc8d8SChris Lattner 2830fdc8d8SChris Lattner BreakpointSiteList::~BreakpointSiteList() 2930fdc8d8SChris Lattner { 3030fdc8d8SChris Lattner } 3130fdc8d8SChris Lattner 3230fdc8d8SChris Lattner // Add breakpoint site to the list. However, if the element already exists in the 3330fdc8d8SChris Lattner // list, then we don't add it, and return LLDB_INVALID_BREAK_ID. 3430fdc8d8SChris Lattner 35c982c768SGreg Clayton lldb::break_id_t 3630fdc8d8SChris Lattner BreakpointSiteList::Add(const BreakpointSiteSP &bp) 3730fdc8d8SChris Lattner { 3830fdc8d8SChris Lattner lldb::addr_t bp_site_load_addr = bp->GetLoadAddress(); 39d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 4030fdc8d8SChris Lattner collection::iterator iter = m_bp_site_list.find (bp_site_load_addr); 4130fdc8d8SChris Lattner 4230fdc8d8SChris Lattner if (iter == m_bp_site_list.end()) 4330fdc8d8SChris Lattner { 4430fdc8d8SChris Lattner m_bp_site_list.insert (iter, collection::value_type (bp_site_load_addr, bp)); 4530fdc8d8SChris Lattner return bp->GetID(); 4630fdc8d8SChris Lattner } 4730fdc8d8SChris Lattner else 4830fdc8d8SChris Lattner { 4930fdc8d8SChris Lattner return LLDB_INVALID_BREAK_ID; 5030fdc8d8SChris Lattner } 5130fdc8d8SChris Lattner } 5230fdc8d8SChris Lattner 5330fdc8d8SChris Lattner bool 54f4b47e15SGreg Clayton BreakpointSiteList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t site_id) 5530fdc8d8SChris Lattner { 56f4b47e15SGreg Clayton BreakpointSiteSP site_sp (FindByID (site_id)); 57f4b47e15SGreg Clayton if (site_sp) 5830fdc8d8SChris Lattner { 5930fdc8d8SChris Lattner // Let the BreakpointSite decide if it should stop here (could not have 6030fdc8d8SChris Lattner // reached it's target hit count yet, or it could have a callback 6130fdc8d8SChris Lattner // that decided it shouldn't stop (shared library loads/unloads). 62f4b47e15SGreg Clayton return site_sp->ShouldStop (context); 6330fdc8d8SChris Lattner } 6430fdc8d8SChris Lattner // We should stop here since this BreakpointSite isn't valid anymore or it 6530fdc8d8SChris Lattner // doesn't exist. 6630fdc8d8SChris Lattner return true; 6730fdc8d8SChris Lattner } 68c982c768SGreg Clayton lldb::break_id_t 6930fdc8d8SChris Lattner BreakpointSiteList::FindIDByAddress (lldb::addr_t addr) 7030fdc8d8SChris Lattner { 7130fdc8d8SChris Lattner BreakpointSiteSP bp = FindByAddress (addr); 7230fdc8d8SChris Lattner if (bp) 7330fdc8d8SChris Lattner { 74d01b2953SDaniel Malea //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" PRIx64 " ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID()); 7530fdc8d8SChris Lattner return bp.get()->GetID(); 7630fdc8d8SChris Lattner } 77d01b2953SDaniel Malea //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" PRIx64 " ) => NONE", __FUNCTION__, (uint64_t)addr); 7830fdc8d8SChris Lattner return LLDB_INVALID_BREAK_ID; 7930fdc8d8SChris Lattner } 8030fdc8d8SChris Lattner 8130fdc8d8SChris Lattner bool 82c982c768SGreg Clayton BreakpointSiteList::Remove (lldb::break_id_t break_id) 8330fdc8d8SChris Lattner { 84d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 8530fdc8d8SChris Lattner collection::iterator pos = GetIDIterator(break_id); // Predicate 8630fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 8730fdc8d8SChris Lattner { 8830fdc8d8SChris Lattner m_bp_site_list.erase(pos); 8930fdc8d8SChris Lattner return true; 9030fdc8d8SChris Lattner } 9130fdc8d8SChris Lattner return false; 9230fdc8d8SChris Lattner } 9330fdc8d8SChris Lattner 9430fdc8d8SChris Lattner bool 9530fdc8d8SChris Lattner BreakpointSiteList::RemoveByAddress (lldb::addr_t address) 9630fdc8d8SChris Lattner { 97d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 9830fdc8d8SChris Lattner collection::iterator pos = m_bp_site_list.find(address); 9930fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 10030fdc8d8SChris Lattner { 10130fdc8d8SChris Lattner m_bp_site_list.erase(pos); 10230fdc8d8SChris Lattner return true; 10330fdc8d8SChris Lattner } 10430fdc8d8SChris Lattner return false; 10530fdc8d8SChris Lattner } 10630fdc8d8SChris Lattner 10730fdc8d8SChris Lattner class BreakpointSiteIDMatches 10830fdc8d8SChris Lattner { 10930fdc8d8SChris Lattner public: 110c982c768SGreg Clayton BreakpointSiteIDMatches (lldb::break_id_t break_id) : 11130fdc8d8SChris Lattner m_break_id(break_id) 11230fdc8d8SChris Lattner { 11330fdc8d8SChris Lattner } 11430fdc8d8SChris Lattner 11530fdc8d8SChris Lattner bool operator() (std::pair <lldb::addr_t, BreakpointSiteSP> val_pair) const 11630fdc8d8SChris Lattner { 11730fdc8d8SChris Lattner return m_break_id == val_pair.second.get()->GetID(); 11830fdc8d8SChris Lattner } 11930fdc8d8SChris Lattner 12030fdc8d8SChris Lattner private: 121c982c768SGreg Clayton const lldb::break_id_t m_break_id; 12230fdc8d8SChris Lattner }; 12330fdc8d8SChris Lattner 12430fdc8d8SChris Lattner BreakpointSiteList::collection::iterator 125c982c768SGreg Clayton BreakpointSiteList::GetIDIterator (lldb::break_id_t break_id) 12630fdc8d8SChris Lattner { 127d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 12830fdc8d8SChris Lattner return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range 12930fdc8d8SChris Lattner BreakpointSiteIDMatches(break_id)); // Predicate 13030fdc8d8SChris Lattner } 13130fdc8d8SChris Lattner 13230fdc8d8SChris Lattner BreakpointSiteList::collection::const_iterator 133c982c768SGreg Clayton BreakpointSiteList::GetIDConstIterator (lldb::break_id_t break_id) const 13430fdc8d8SChris Lattner { 135d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 13630fdc8d8SChris Lattner return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range 13730fdc8d8SChris Lattner BreakpointSiteIDMatches(break_id)); // Predicate 13830fdc8d8SChris Lattner } 13930fdc8d8SChris Lattner 14030fdc8d8SChris Lattner BreakpointSiteSP 141c982c768SGreg Clayton BreakpointSiteList::FindByID (lldb::break_id_t break_id) 14230fdc8d8SChris Lattner { 143d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 14430fdc8d8SChris Lattner BreakpointSiteSP stop_sp; 14530fdc8d8SChris Lattner collection::iterator pos = GetIDIterator(break_id); 14630fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 14730fdc8d8SChris Lattner stop_sp = pos->second; 14830fdc8d8SChris Lattner 14930fdc8d8SChris Lattner return stop_sp; 15030fdc8d8SChris Lattner } 15130fdc8d8SChris Lattner 15230fdc8d8SChris Lattner const BreakpointSiteSP 153c982c768SGreg Clayton BreakpointSiteList::FindByID (lldb::break_id_t break_id) const 15430fdc8d8SChris Lattner { 155d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 15630fdc8d8SChris Lattner BreakpointSiteSP stop_sp; 15730fdc8d8SChris Lattner collection::const_iterator pos = GetIDConstIterator(break_id); 15830fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 15930fdc8d8SChris Lattner stop_sp = pos->second; 16030fdc8d8SChris Lattner 16130fdc8d8SChris Lattner return stop_sp; 16230fdc8d8SChris Lattner } 16330fdc8d8SChris Lattner 16430fdc8d8SChris Lattner BreakpointSiteSP 16530fdc8d8SChris Lattner BreakpointSiteList::FindByAddress (lldb::addr_t addr) 16630fdc8d8SChris Lattner { 16730fdc8d8SChris Lattner BreakpointSiteSP found_sp; 168d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 16930fdc8d8SChris Lattner collection::iterator iter = m_bp_site_list.find(addr); 17030fdc8d8SChris Lattner if (iter != m_bp_site_list.end()) 17130fdc8d8SChris Lattner found_sp = iter->second; 17230fdc8d8SChris Lattner return found_sp; 17330fdc8d8SChris Lattner } 17430fdc8d8SChris Lattner 175564d8bc2SJim Ingham bool 176564d8bc2SJim Ingham BreakpointSiteList::BreakpointSiteContainsBreakpoint (lldb::break_id_t bp_site_id, lldb::break_id_t bp_id) 177564d8bc2SJim Ingham { 178d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 179564d8bc2SJim Ingham collection::const_iterator pos = GetIDConstIterator(bp_site_id); 180564d8bc2SJim Ingham if (pos != m_bp_site_list.end()) 181367efe7dSJim Ingham return pos->second->IsBreakpointAtThisSite (bp_id); 182564d8bc2SJim Ingham 183564d8bc2SJim Ingham return false; 184564d8bc2SJim Ingham } 185564d8bc2SJim Ingham 18630fdc8d8SChris Lattner void 18730fdc8d8SChris Lattner BreakpointSiteList::Dump (Stream *s) const 18830fdc8d8SChris Lattner { 189*324a1036SSaleem Abdulrasool s->Printf("%p: ", static_cast<const void*>(this)); 190ded470d3SGreg Clayton //s->Indent(); 19130fdc8d8SChris Lattner s->Printf("BreakpointSiteList with %u BreakpointSites:\n", (uint32_t)m_bp_site_list.size()); 19230fdc8d8SChris Lattner s->IndentMore(); 19330fdc8d8SChris Lattner collection::const_iterator pos; 19430fdc8d8SChris Lattner collection::const_iterator end = m_bp_site_list.end(); 19530fdc8d8SChris Lattner for (pos = m_bp_site_list.begin(); pos != end; ++pos) 19630fdc8d8SChris Lattner pos->second.get()->Dump(s); 19730fdc8d8SChris Lattner s->IndentLess(); 19830fdc8d8SChris Lattner } 19930fdc8d8SChris Lattner 200d8cf1a11SGreg Clayton void 201d8cf1a11SGreg Clayton BreakpointSiteList::ForEach (std::function <void(BreakpointSite *)> const &callback) 20230fdc8d8SChris Lattner { 203d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 204d8cf1a11SGreg Clayton for (auto pair : m_bp_site_list) 205d8cf1a11SGreg Clayton callback (pair.second.get()); 20630fdc8d8SChris Lattner } 20730fdc8d8SChris Lattner 20820c77199SJim Ingham bool 20920c77199SJim Ingham BreakpointSiteList::FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const 21020c77199SJim Ingham { 21120c77199SJim Ingham if (lower_bound > upper_bound) 21220c77199SJim Ingham return false; 21320c77199SJim Ingham 214d8cf1a11SGreg Clayton Mutex::Locker locker(m_mutex); 21520c77199SJim Ingham collection::const_iterator lower, upper, pos; 21620c77199SJim Ingham lower = m_bp_site_list.lower_bound(lower_bound); 21720c77199SJim Ingham if (lower == m_bp_site_list.end() 21820c77199SJim Ingham || (*lower).first >= upper_bound) 21920c77199SJim Ingham return false; 22020c77199SJim Ingham 22120c77199SJim Ingham // This is one tricky bit. The breakpoint might overlap the bottom end of the range. So we grab the 22220c77199SJim Ingham // breakpoint prior to the lower bound, and check that that + its byte size isn't in our range. 22320c77199SJim Ingham if (lower != m_bp_site_list.begin()) 22420c77199SJim Ingham { 22520c77199SJim Ingham collection::const_iterator prev_pos = lower; 22620c77199SJim Ingham prev_pos--; 22720c77199SJim Ingham const BreakpointSiteSP &prev_bp = (*prev_pos).second; 22820c77199SJim Ingham if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound) 22920c77199SJim Ingham bp_site_list.Add (prev_bp); 23020c77199SJim Ingham 23120c77199SJim Ingham } 23220c77199SJim Ingham 23320c77199SJim Ingham upper = m_bp_site_list.upper_bound(upper_bound); 23420c77199SJim Ingham 23520c77199SJim Ingham for (pos = lower; pos != upper; pos++) 23620c77199SJim Ingham { 23720c77199SJim Ingham bp_site_list.Add ((*pos).second); 23820c77199SJim Ingham } 23920c77199SJim Ingham return true; 24020c77199SJim Ingham } 241