//===-- BreakpointSiteList.cpp --------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Breakpoint/BreakpointSiteList.h"

#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->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->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;
}
