//===-- 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() = default;

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