//===-- BreakpointLocationList.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/BreakpointLocationList.h"

#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"

using namespace lldb;
using namespace lldb_private;

BreakpointLocationList::BreakpointLocationList(Breakpoint &owner)
    : m_owner(owner), m_next_id(0), m_new_location_recorder(nullptr) {}

BreakpointLocationList::~BreakpointLocationList() = default;

BreakpointLocationSP
BreakpointLocationList::Create(const Address &addr,
                               bool resolve_indirect_symbols) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  // The location ID is just the size of the location list + 1
  lldb::break_id_t bp_loc_id = ++m_next_id;
  BreakpointLocationSP bp_loc_sp(
      new BreakpointLocation(bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID,
                             resolve_indirect_symbols));
  m_locations.push_back(bp_loc_sp);
  m_address_to_location[addr] = bp_loc_sp;
  return bp_loc_sp;
}

bool BreakpointLocationList::ShouldStop(StoppointCallbackContext *context,
                                        lldb::break_id_t break_id,
                                        lldb::BreakpointLocationSP &bp_loc_sp) {
  BreakpointLocationSP bp = FindByID(break_id);
  if (bp) {
    // Let the BreakpointLocation 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 bp->ShouldStop(context, bp_loc_sp);
  }
  // We should stop here since this BreakpointLocation isn't valid anymore or
  // it doesn't exist.
  return true;
}

lldb::break_id_t BreakpointLocationList::FindIDByAddress(const Address &addr) {
  BreakpointLocationSP bp_loc_sp = FindByAddress(addr);
  if (bp_loc_sp) {
    return bp_loc_sp->GetID();
  }
  return LLDB_INVALID_BREAK_ID;
}

static bool Compare(BreakpointLocationSP lhs, lldb::break_id_t val) {
  return lhs->GetID() < val;
}

BreakpointLocationSP
BreakpointLocationList::FindByID(lldb::break_id_t break_id) const {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  collection::const_iterator end = m_locations.end();
  collection::const_iterator pos =
      llvm::lower_bound(m_locations, break_id, Compare);
  if (pos != end && (*pos)->GetID() == break_id)
    return *(pos);
  return BreakpointLocationSP();
}

size_t BreakpointLocationList::FindInModule(
    Module *module, BreakpointLocationCollection &bp_loc_list) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  const size_t orig_size = bp_loc_list.GetSize();
  collection::iterator pos, end = m_locations.end();

  for (pos = m_locations.begin(); pos != end; ++pos) {
    BreakpointLocationSP break_loc = (*pos);
    SectionSP section_sp(break_loc->GetAddress().GetSection());
    if (section_sp && section_sp->GetModule().get() == module) {
      bp_loc_list.Add(break_loc);
    }
  }
  return bp_loc_list.GetSize() - orig_size;
}

const BreakpointLocationSP
BreakpointLocationList::FindByAddress(const Address &addr) const {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  BreakpointLocationSP bp_loc_sp;
  if (!m_locations.empty()) {
    Address so_addr;

    if (addr.IsSectionOffset()) {
      so_addr = addr;
    } else {
      // Try and resolve as a load address if possible.
      m_owner.GetTarget().ResolveLoadAddress(addr.GetOffset(), so_addr);
      if (!so_addr.IsValid()) {
        // The address didn't resolve, so just set to passed in addr.
        so_addr = addr;
      }
    }

    addr_map::const_iterator pos = m_address_to_location.find(so_addr);
    if (pos != m_address_to_location.end())
      bp_loc_sp = pos->second;
  }

  return bp_loc_sp;
}

void BreakpointLocationList::Dump(Stream *s) const {
  s->Printf("%p: ", static_cast<const void *>(this));
  // s->Indent();
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n",
            (uint64_t)m_locations.size());
  s->IndentMore();
  collection::const_iterator pos, end = m_locations.end();
  for (pos = m_locations.begin(); pos != end; ++pos)
    (*pos)->Dump(s);
  s->IndentLess();
}

BreakpointLocationSP BreakpointLocationList::GetByIndex(size_t i) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  BreakpointLocationSP bp_loc_sp;
  if (i < m_locations.size())
    bp_loc_sp = m_locations[i];

  return bp_loc_sp;
}

const BreakpointLocationSP BreakpointLocationList::GetByIndex(size_t i) const {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  BreakpointLocationSP bp_loc_sp;
  if (i < m_locations.size())
    bp_loc_sp = m_locations[i];

  return bp_loc_sp;
}

void BreakpointLocationList::ClearAllBreakpointSites() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  collection::iterator pos, end = m_locations.end();
  Log *log = GetLog(LLDBLog::Breakpoints);

  for (pos = m_locations.begin(); pos != end; ++pos) {
    if (llvm::Error error = (*pos)->ClearBreakpointSite())
      LLDB_LOG_ERROR(log, std::move(error), "{0}");
  }
}

void BreakpointLocationList::ResolveAllBreakpointSites() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  collection::iterator pos, end = m_locations.end();
  Log *log = GetLog(LLDBLog::Breakpoints);

  for (pos = m_locations.begin(); pos != end; ++pos) {
    if ((*pos)->IsEnabled()) {
      if (llvm::Error error = (*pos)->ResolveBreakpointSite())
        LLDB_LOG_ERROR(log, std::move(error), "{0}");
    }
  }
}

uint32_t BreakpointLocationList::GetHitCount() const {
  uint32_t hit_count = 0;
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  collection::const_iterator pos, end = m_locations.end();
  for (pos = m_locations.begin(); pos != end; ++pos)
    hit_count += (*pos)->GetHitCount();
  return hit_count;
}

void BreakpointLocationList::ResetHitCount() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  for (auto &loc : m_locations)
    loc->ResetHitCount();
}

size_t BreakpointLocationList::GetNumResolvedLocations() const {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  size_t resolve_count = 0;
  collection::const_iterator pos, end = m_locations.end();
  for (pos = m_locations.begin(); pos != end; ++pos) {
    if ((*pos)->IsResolved())
      ++resolve_count;
  }
  return resolve_count;
}

void BreakpointLocationList::GetDescription(Stream *s,
                                            lldb::DescriptionLevel level) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  collection::iterator pos, end = m_locations.end();

  for (pos = m_locations.begin(); pos != end; ++pos) {
    s->Printf(" ");
    (*pos)->GetDescription(s, level);
  }
}

BreakpointLocationSP BreakpointLocationList::AddLocation(
    const Address &addr, bool resolve_indirect_symbols, bool *new_location) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);

  if (new_location)
    *new_location = false;
  BreakpointLocationSP bp_loc_sp(FindByAddress(addr));
  if (!bp_loc_sp) {
    bp_loc_sp = Create(addr, resolve_indirect_symbols);
    if (bp_loc_sp) {
      if (llvm::Error error = bp_loc_sp->ResolveBreakpointSite())
        LLDB_LOG_ERROR(GetLog(LLDBLog::Breakpoints), std::move(error), "{0}");

      if (new_location)
        *new_location = true;
      if (m_new_location_recorder) {
        m_new_location_recorder->Add(bp_loc_sp);
      }
    }
  }
  return bp_loc_sp;
}

void BreakpointLocationList::SwapLocation(
    BreakpointLocationSP to_location_sp,
    BreakpointLocationSP from_location_sp) {
  if (!from_location_sp || !to_location_sp)
    return;

  m_address_to_location.erase(to_location_sp->GetAddress());
  to_location_sp->SwapLocation(from_location_sp);
  RemoveLocation(from_location_sp);
  m_address_to_location[to_location_sp->GetAddress()] = to_location_sp;
  llvm::consumeError(to_location_sp->ResolveBreakpointSite());
}

bool BreakpointLocationList::RemoveLocation(
    const lldb::BreakpointLocationSP &bp_loc_sp) {
  if (bp_loc_sp) {
    std::lock_guard<std::recursive_mutex> guard(m_mutex);

    m_address_to_location.erase(bp_loc_sp->GetAddress());

    size_t num_locations = m_locations.size();
    for (size_t idx = 0; idx < num_locations; idx++) {
      if (m_locations[idx].get() == bp_loc_sp.get()) {
        RemoveLocationByIndex(idx);
        return true;
      }
    }
  }
  return false;
}

void BreakpointLocationList::RemoveLocationByIndex(size_t idx) {
  assert (idx < m_locations.size());
  m_address_to_location.erase(m_locations[idx]->GetAddress());
  m_locations.erase(m_locations.begin() + idx);
}

void BreakpointLocationList::RemoveInvalidLocations(const ArchSpec &arch) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  size_t idx = 0;
  // Don't cache m_location.size() as it will change since we might remove
  // locations from our vector...
  while (idx < m_locations.size()) {
    BreakpointLocation *bp_loc = m_locations[idx].get();
    if (bp_loc->GetAddress().SectionWasDeleted()) {
      // Section was deleted which means this breakpoint comes from a module
      // that is no longer valid, so we should remove it.
      RemoveLocationByIndex(idx);
      continue;
    }
    if (arch.IsValid()) {
      ModuleSP module_sp(bp_loc->GetAddress().GetModule());
      if (module_sp) {
        if (!arch.IsCompatibleMatch(module_sp->GetArchitecture())) {
          // The breakpoint was in a module whose architecture is no longer
          // compatible with "arch", so we need to remove it
          RemoveLocationByIndex(idx);
          continue;
        }
      }
    }
    // Only increment the index if we didn't remove the locations at index
    // "idx"
    ++idx;
  }
}

void BreakpointLocationList::StartRecordingNewLocations(
    BreakpointLocationCollection &new_locations) {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  assert(m_new_location_recorder == nullptr);
  m_new_location_recorder = &new_locations;
}

void BreakpointLocationList::StopRecordingNewLocations() {
  std::lock_guard<std::recursive_mutex> guard(m_mutex);
  m_new_location_recorder = nullptr;
}

void BreakpointLocationList::Compact() {
  lldb::break_id_t highest_id = 0;

  for (BreakpointLocationSP loc_sp : m_locations) {
    lldb::break_id_t cur_id = loc_sp->GetID();
    if (cur_id > highest_id)
      highest_id = cur_id;
  }
  m_next_id = highest_id;
}
