forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			207 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			207 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- BreakpointSiteList.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/BreakpointSiteList.h"
 | 
						|
 | 
						|
// C Includes
 | 
						|
// C++ Includes
 | 
						|
// Other libraries and framework includes
 | 
						|
// Project includes
 | 
						|
#include "lldb/Utility/Stream.h"
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
using namespace lldb;
 | 
						|
using namespace lldb_private;
 | 
						|
 | 
						|
BreakpointSiteList::BreakpointSiteList() : m_mutex(), m_bp_site_list() {}
 | 
						|
 | 
						|
BreakpointSiteList::~BreakpointSiteList() {}
 | 
						|
 | 
						|
// Add breakpoint site to the list.  However, if the element already exists in
 | 
						|
// the
 | 
						|
// list, then we don't add it, and return LLDB_INVALID_BREAK_ID.
 | 
						|
 | 
						|
lldb::break_id_t BreakpointSiteList::Add(const BreakpointSiteSP &bp) {
 | 
						|
  lldb::addr_t bp_site_load_addr = bp->GetLoadAddress();
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  collection::iterator iter = m_bp_site_list.find(bp_site_load_addr);
 | 
						|
 | 
						|
  if (iter == m_bp_site_list.end()) {
 | 
						|
    m_bp_site_list.insert(iter, collection::value_type(bp_site_load_addr, bp));
 | 
						|
    return bp->GetID();
 | 
						|
  } else {
 | 
						|
    return LLDB_INVALID_BREAK_ID;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool BreakpointSiteList::ShouldStop(StoppointCallbackContext *context,
 | 
						|
                                    lldb::break_id_t site_id) {
 | 
						|
  BreakpointSiteSP site_sp(FindByID(site_id));
 | 
						|
  if (site_sp) {
 | 
						|
    // Let the BreakpointSite decide if it should stop here (could not have
 | 
						|
    // reached it's target hit count yet, or it could have a callback
 | 
						|
    // that decided it shouldn't stop (shared library loads/unloads).
 | 
						|
    return site_sp->ShouldStop(context);
 | 
						|
  }
 | 
						|
  // We should stop here since this BreakpointSite isn't valid anymore or it
 | 
						|
  // doesn't exist.
 | 
						|
  return true;
 | 
						|
}
 | 
						|
lldb::break_id_t BreakpointSiteList::FindIDByAddress(lldb::addr_t addr) {
 | 
						|
  BreakpointSiteSP bp = FindByAddress(addr);
 | 
						|
  if (bp) {
 | 
						|
    // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8"
 | 
						|
    // PRIx64 " ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID());
 | 
						|
    return bp.get()->GetID();
 | 
						|
  }
 | 
						|
  // DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8" PRIx64
 | 
						|
  // " ) => NONE", __FUNCTION__, (uint64_t)addr);
 | 
						|
  return LLDB_INVALID_BREAK_ID;
 | 
						|
}
 | 
						|
 | 
						|
bool BreakpointSiteList::Remove(lldb::break_id_t break_id) {
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  collection::iterator pos = GetIDIterator(break_id); // Predicate
 | 
						|
  if (pos != m_bp_site_list.end()) {
 | 
						|
    m_bp_site_list.erase(pos);
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool BreakpointSiteList::RemoveByAddress(lldb::addr_t address) {
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  collection::iterator pos = m_bp_site_list.find(address);
 | 
						|
  if (pos != m_bp_site_list.end()) {
 | 
						|
    m_bp_site_list.erase(pos);
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
class BreakpointSiteIDMatches {
 | 
						|
public:
 | 
						|
  BreakpointSiteIDMatches(lldb::break_id_t break_id) : m_break_id(break_id) {}
 | 
						|
 | 
						|
  bool operator()(std::pair<lldb::addr_t, BreakpointSiteSP> val_pair) const {
 | 
						|
    return m_break_id == val_pair.second.get()->GetID();
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  const lldb::break_id_t m_break_id;
 | 
						|
};
 | 
						|
 | 
						|
BreakpointSiteList::collection::iterator
 | 
						|
BreakpointSiteList::GetIDIterator(lldb::break_id_t break_id) {
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  return std::find_if(m_bp_site_list.begin(),
 | 
						|
                      m_bp_site_list.end(),               // Search full range
 | 
						|
                      BreakpointSiteIDMatches(break_id)); // Predicate
 | 
						|
}
 | 
						|
 | 
						|
BreakpointSiteList::collection::const_iterator
 | 
						|
BreakpointSiteList::GetIDConstIterator(lldb::break_id_t break_id) const {
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  return std::find_if(m_bp_site_list.begin(),
 | 
						|
                      m_bp_site_list.end(),               // Search full range
 | 
						|
                      BreakpointSiteIDMatches(break_id)); // Predicate
 | 
						|
}
 | 
						|
 | 
						|
BreakpointSiteSP BreakpointSiteList::FindByID(lldb::break_id_t break_id) {
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  BreakpointSiteSP stop_sp;
 | 
						|
  collection::iterator pos = GetIDIterator(break_id);
 | 
						|
  if (pos != m_bp_site_list.end())
 | 
						|
    stop_sp = pos->second;
 | 
						|
 | 
						|
  return stop_sp;
 | 
						|
}
 | 
						|
 | 
						|
const BreakpointSiteSP
 | 
						|
BreakpointSiteList::FindByID(lldb::break_id_t break_id) const {
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  BreakpointSiteSP stop_sp;
 | 
						|
  collection::const_iterator pos = GetIDConstIterator(break_id);
 | 
						|
  if (pos != m_bp_site_list.end())
 | 
						|
    stop_sp = pos->second;
 | 
						|
 | 
						|
  return stop_sp;
 | 
						|
}
 | 
						|
 | 
						|
BreakpointSiteSP BreakpointSiteList::FindByAddress(lldb::addr_t addr) {
 | 
						|
  BreakpointSiteSP found_sp;
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  collection::iterator iter = m_bp_site_list.find(addr);
 | 
						|
  if (iter != m_bp_site_list.end())
 | 
						|
    found_sp = iter->second;
 | 
						|
  return found_sp;
 | 
						|
}
 | 
						|
 | 
						|
bool BreakpointSiteList::BreakpointSiteContainsBreakpoint(
 | 
						|
    lldb::break_id_t bp_site_id, lldb::break_id_t bp_id) {
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  collection::const_iterator pos = GetIDConstIterator(bp_site_id);
 | 
						|
  if (pos != m_bp_site_list.end())
 | 
						|
    return pos->second->IsBreakpointAtThisSite(bp_id);
 | 
						|
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
void BreakpointSiteList::Dump(Stream *s) const {
 | 
						|
  s->Printf("%p: ", static_cast<const void *>(this));
 | 
						|
  // s->Indent();
 | 
						|
  s->Printf("BreakpointSiteList with %u BreakpointSites:\n",
 | 
						|
            (uint32_t)m_bp_site_list.size());
 | 
						|
  s->IndentMore();
 | 
						|
  collection::const_iterator pos;
 | 
						|
  collection::const_iterator end = m_bp_site_list.end();
 | 
						|
  for (pos = m_bp_site_list.begin(); pos != end; ++pos)
 | 
						|
    pos->second.get()->Dump(s);
 | 
						|
  s->IndentLess();
 | 
						|
}
 | 
						|
 | 
						|
void BreakpointSiteList::ForEach(
 | 
						|
    std::function<void(BreakpointSite *)> const &callback) {
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  for (auto pair : m_bp_site_list)
 | 
						|
    callback(pair.second.get());
 | 
						|
}
 | 
						|
 | 
						|
bool BreakpointSiteList::FindInRange(lldb::addr_t lower_bound,
 | 
						|
                                     lldb::addr_t upper_bound,
 | 
						|
                                     BreakpointSiteList &bp_site_list) const {
 | 
						|
  if (lower_bound > upper_bound)
 | 
						|
    return false;
 | 
						|
 | 
						|
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
 | 
						|
  collection::const_iterator lower, upper, pos;
 | 
						|
  lower = m_bp_site_list.lower_bound(lower_bound);
 | 
						|
  if (lower == m_bp_site_list.end() || (*lower).first >= upper_bound)
 | 
						|
    return false;
 | 
						|
 | 
						|
  // This is one tricky bit.  The breakpoint might overlap the bottom end of the
 | 
						|
  // range.  So we grab the
 | 
						|
  // breakpoint prior to the lower bound, and check that that + its byte size
 | 
						|
  // isn't in our range.
 | 
						|
  if (lower != m_bp_site_list.begin()) {
 | 
						|
    collection::const_iterator prev_pos = lower;
 | 
						|
    prev_pos--;
 | 
						|
    const BreakpointSiteSP &prev_bp = (*prev_pos).second;
 | 
						|
    if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound)
 | 
						|
      bp_site_list.Add(prev_bp);
 | 
						|
  }
 | 
						|
 | 
						|
  upper = m_bp_site_list.upper_bound(upper_bound);
 | 
						|
 | 
						|
  for (pos = lower; pos != upper; pos++) {
 | 
						|
    bp_site_list.Add((*pos).second);
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 |