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 22*b9c1b51eSKate Stone BreakpointSiteList::BreakpointSiteList() : m_mutex(), m_bp_site_list() {} 2330fdc8d8SChris Lattner 24*b9c1b51eSKate Stone BreakpointSiteList::~BreakpointSiteList() {} 2530fdc8d8SChris Lattner 26*b9c1b51eSKate Stone // Add breakpoint site to the list. However, if the element already exists in 27*b9c1b51eSKate Stone // the 2830fdc8d8SChris Lattner // list, then we don't add it, and return LLDB_INVALID_BREAK_ID. 2930fdc8d8SChris Lattner 30*b9c1b51eSKate Stone lldb::break_id_t BreakpointSiteList::Add(const BreakpointSiteSP &bp) { 3130fdc8d8SChris Lattner lldb::addr_t bp_site_load_addr = bp->GetLoadAddress(); 3216ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 3330fdc8d8SChris Lattner collection::iterator iter = m_bp_site_list.find(bp_site_load_addr); 3430fdc8d8SChris Lattner 35*b9c1b51eSKate Stone if (iter == m_bp_site_list.end()) { 3630fdc8d8SChris Lattner m_bp_site_list.insert(iter, collection::value_type(bp_site_load_addr, bp)); 3730fdc8d8SChris Lattner return bp->GetID(); 38*b9c1b51eSKate Stone } else { 3930fdc8d8SChris Lattner return LLDB_INVALID_BREAK_ID; 4030fdc8d8SChris Lattner } 4130fdc8d8SChris Lattner } 4230fdc8d8SChris Lattner 43*b9c1b51eSKate Stone bool BreakpointSiteList::ShouldStop(StoppointCallbackContext *context, 44*b9c1b51eSKate Stone lldb::break_id_t site_id) { 45f4b47e15SGreg Clayton BreakpointSiteSP site_sp(FindByID(site_id)); 46*b9c1b51eSKate Stone if (site_sp) { 4730fdc8d8SChris Lattner // Let the BreakpointSite decide if it should stop here (could not have 4830fdc8d8SChris Lattner // reached it's target hit count yet, or it could have a callback 4930fdc8d8SChris Lattner // that decided it shouldn't stop (shared library loads/unloads). 50f4b47e15SGreg Clayton return site_sp->ShouldStop(context); 5130fdc8d8SChris Lattner } 5230fdc8d8SChris Lattner // We should stop here since this BreakpointSite isn't valid anymore or it 5330fdc8d8SChris Lattner // doesn't exist. 5430fdc8d8SChris Lattner return true; 5530fdc8d8SChris Lattner } 56*b9c1b51eSKate Stone lldb::break_id_t BreakpointSiteList::FindIDByAddress(lldb::addr_t addr) { 5730fdc8d8SChris Lattner BreakpointSiteSP bp = FindByAddress(addr); 58*b9c1b51eSKate Stone if (bp) { 59*b9c1b51eSKate Stone // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" 60*b9c1b51eSKate Stone // PRIx64 " ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID()); 6130fdc8d8SChris Lattner return bp.get()->GetID(); 6230fdc8d8SChris Lattner } 63*b9c1b51eSKate Stone // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" PRIx64 64*b9c1b51eSKate Stone // " ) => NONE", __FUNCTION__, (uint64_t)addr); 6530fdc8d8SChris Lattner return LLDB_INVALID_BREAK_ID; 6630fdc8d8SChris Lattner } 6730fdc8d8SChris Lattner 68*b9c1b51eSKate Stone bool BreakpointSiteList::Remove(lldb::break_id_t break_id) { 6916ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 7030fdc8d8SChris Lattner collection::iterator pos = GetIDIterator(break_id); // Predicate 71*b9c1b51eSKate Stone if (pos != m_bp_site_list.end()) { 7230fdc8d8SChris Lattner m_bp_site_list.erase(pos); 7330fdc8d8SChris Lattner return true; 7430fdc8d8SChris Lattner } 7530fdc8d8SChris Lattner return false; 7630fdc8d8SChris Lattner } 7730fdc8d8SChris Lattner 78*b9c1b51eSKate Stone bool BreakpointSiteList::RemoveByAddress(lldb::addr_t address) { 7916ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 8030fdc8d8SChris Lattner collection::iterator pos = m_bp_site_list.find(address); 81*b9c1b51eSKate Stone if (pos != m_bp_site_list.end()) { 8230fdc8d8SChris Lattner m_bp_site_list.erase(pos); 8330fdc8d8SChris Lattner return true; 8430fdc8d8SChris Lattner } 8530fdc8d8SChris Lattner return false; 8630fdc8d8SChris Lattner } 8730fdc8d8SChris Lattner 88*b9c1b51eSKate Stone class BreakpointSiteIDMatches { 8930fdc8d8SChris Lattner public: 90*b9c1b51eSKate Stone BreakpointSiteIDMatches(lldb::break_id_t break_id) : m_break_id(break_id) {} 9130fdc8d8SChris Lattner 92*b9c1b51eSKate Stone bool operator()(std::pair<lldb::addr_t, BreakpointSiteSP> val_pair) const { 9330fdc8d8SChris Lattner return m_break_id == val_pair.second.get()->GetID(); 9430fdc8d8SChris Lattner } 9530fdc8d8SChris Lattner 9630fdc8d8SChris Lattner private: 97c982c768SGreg Clayton const lldb::break_id_t m_break_id; 9830fdc8d8SChris Lattner }; 9930fdc8d8SChris Lattner 10030fdc8d8SChris Lattner BreakpointSiteList::collection::iterator 101*b9c1b51eSKate Stone BreakpointSiteList::GetIDIterator(lldb::break_id_t break_id) { 10216ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 103*b9c1b51eSKate Stone return std::find_if(m_bp_site_list.begin(), 104*b9c1b51eSKate Stone m_bp_site_list.end(), // Search full range 10530fdc8d8SChris Lattner BreakpointSiteIDMatches(break_id)); // Predicate 10630fdc8d8SChris Lattner } 10730fdc8d8SChris Lattner 10830fdc8d8SChris Lattner BreakpointSiteList::collection::const_iterator 109*b9c1b51eSKate Stone BreakpointSiteList::GetIDConstIterator(lldb::break_id_t break_id) const { 11016ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 111*b9c1b51eSKate Stone return std::find_if(m_bp_site_list.begin(), 112*b9c1b51eSKate Stone m_bp_site_list.end(), // Search full range 11330fdc8d8SChris Lattner BreakpointSiteIDMatches(break_id)); // Predicate 11430fdc8d8SChris Lattner } 11530fdc8d8SChris Lattner 116*b9c1b51eSKate Stone BreakpointSiteSP BreakpointSiteList::FindByID(lldb::break_id_t break_id) { 11716ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 11830fdc8d8SChris Lattner BreakpointSiteSP stop_sp; 11930fdc8d8SChris Lattner collection::iterator pos = GetIDIterator(break_id); 12030fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 12130fdc8d8SChris Lattner stop_sp = pos->second; 12230fdc8d8SChris Lattner 12330fdc8d8SChris Lattner return stop_sp; 12430fdc8d8SChris Lattner } 12530fdc8d8SChris Lattner 12630fdc8d8SChris Lattner const BreakpointSiteSP 127*b9c1b51eSKate Stone BreakpointSiteList::FindByID(lldb::break_id_t break_id) const { 12816ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 12930fdc8d8SChris Lattner BreakpointSiteSP stop_sp; 13030fdc8d8SChris Lattner collection::const_iterator pos = GetIDConstIterator(break_id); 13130fdc8d8SChris Lattner if (pos != m_bp_site_list.end()) 13230fdc8d8SChris Lattner stop_sp = pos->second; 13330fdc8d8SChris Lattner 13430fdc8d8SChris Lattner return stop_sp; 13530fdc8d8SChris Lattner } 13630fdc8d8SChris Lattner 137*b9c1b51eSKate Stone BreakpointSiteSP BreakpointSiteList::FindByAddress(lldb::addr_t addr) { 13830fdc8d8SChris Lattner BreakpointSiteSP found_sp; 13916ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 14030fdc8d8SChris Lattner collection::iterator iter = m_bp_site_list.find(addr); 14130fdc8d8SChris Lattner if (iter != m_bp_site_list.end()) 14230fdc8d8SChris Lattner found_sp = iter->second; 14330fdc8d8SChris Lattner return found_sp; 14430fdc8d8SChris Lattner } 14530fdc8d8SChris Lattner 146*b9c1b51eSKate Stone bool BreakpointSiteList::BreakpointSiteContainsBreakpoint( 147*b9c1b51eSKate Stone lldb::break_id_t bp_site_id, lldb::break_id_t bp_id) { 14816ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 149564d8bc2SJim Ingham collection::const_iterator pos = GetIDConstIterator(bp_site_id); 150564d8bc2SJim Ingham if (pos != m_bp_site_list.end()) 151367efe7dSJim Ingham return pos->second->IsBreakpointAtThisSite(bp_id); 152564d8bc2SJim Ingham 153564d8bc2SJim Ingham return false; 154564d8bc2SJim Ingham } 155564d8bc2SJim Ingham 156*b9c1b51eSKate Stone void BreakpointSiteList::Dump(Stream *s) const { 157324a1036SSaleem Abdulrasool s->Printf("%p: ", static_cast<const void *>(this)); 158ded470d3SGreg Clayton // s->Indent(); 159*b9c1b51eSKate Stone s->Printf("BreakpointSiteList with %u BreakpointSites:\n", 160*b9c1b51eSKate Stone (uint32_t)m_bp_site_list.size()); 16130fdc8d8SChris Lattner s->IndentMore(); 16230fdc8d8SChris Lattner collection::const_iterator pos; 16330fdc8d8SChris Lattner collection::const_iterator end = m_bp_site_list.end(); 16430fdc8d8SChris Lattner for (pos = m_bp_site_list.begin(); pos != end; ++pos) 16530fdc8d8SChris Lattner pos->second.get()->Dump(s); 16630fdc8d8SChris Lattner s->IndentLess(); 16730fdc8d8SChris Lattner } 16830fdc8d8SChris Lattner 169*b9c1b51eSKate Stone void BreakpointSiteList::ForEach( 170*b9c1b51eSKate Stone std::function<void(BreakpointSite *)> const &callback) { 17116ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 172d8cf1a11SGreg Clayton for (auto pair : m_bp_site_list) 173d8cf1a11SGreg Clayton callback(pair.second.get()); 17430fdc8d8SChris Lattner } 17530fdc8d8SChris Lattner 176*b9c1b51eSKate Stone bool BreakpointSiteList::FindInRange(lldb::addr_t lower_bound, 177*b9c1b51eSKate Stone lldb::addr_t upper_bound, 178*b9c1b51eSKate Stone BreakpointSiteList &bp_site_list) const { 17920c77199SJim Ingham if (lower_bound > upper_bound) 18020c77199SJim Ingham return false; 18120c77199SJim Ingham 18216ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_mutex); 18320c77199SJim Ingham collection::const_iterator lower, upper, pos; 18420c77199SJim Ingham lower = m_bp_site_list.lower_bound(lower_bound); 185*b9c1b51eSKate Stone if (lower == m_bp_site_list.end() || (*lower).first >= upper_bound) 18620c77199SJim Ingham return false; 18720c77199SJim Ingham 188*b9c1b51eSKate Stone // This is one tricky bit. The breakpoint might overlap the bottom end of the 189*b9c1b51eSKate Stone // range. So we grab the 190*b9c1b51eSKate Stone // breakpoint prior to the lower bound, and check that that + its byte size 191*b9c1b51eSKate Stone // isn't in our range. 192*b9c1b51eSKate Stone if (lower != m_bp_site_list.begin()) { 19320c77199SJim Ingham collection::const_iterator prev_pos = lower; 19420c77199SJim Ingham prev_pos--; 19520c77199SJim Ingham const BreakpointSiteSP &prev_bp = (*prev_pos).second; 19620c77199SJim Ingham if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound) 19720c77199SJim Ingham bp_site_list.Add(prev_bp); 19820c77199SJim Ingham } 19920c77199SJim Ingham 20020c77199SJim Ingham upper = m_bp_site_list.upper_bound(upper_bound); 20120c77199SJim Ingham 202*b9c1b51eSKate Stone for (pos = lower; pos != upper; pos++) { 20320c77199SJim Ingham bp_site_list.Add((*pos).second); 20420c77199SJim Ingham } 20520c77199SJim Ingham return true; 20620c77199SJim Ingham } 207