//===-- BreakpointSite.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 <cinttypes>

#include "lldb/Breakpoint/BreakpointSite.h"

#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Stream.h"

using namespace lldb;
using namespace lldb_private;

BreakpointSite::BreakpointSite(const BreakpointLocationSP &constituent,
                               lldb::addr_t addr, bool use_hardware)
    : StoppointSite(GetNextID(), addr, 0, use_hardware),
      m_type(eSoftware), // Process subclasses need to set this correctly using
                         // SetType()
      m_saved_opcode(), m_trap_opcode(),
      m_enabled(false) // Need to create it disabled, so the first enable turns
                       // it on.
{
  m_constituents.Add(constituent);
}

BreakpointSite::~BreakpointSite() {
  BreakpointLocationSP bp_loc_sp;
  const size_t constituent_count = m_constituents.GetSize();
  for (size_t i = 0; i < constituent_count; i++)
    llvm::consumeError(m_constituents.GetByIndex(i)->ClearBreakpointSite());
}

break_id_t BreakpointSite::GetNextID() {
  static break_id_t g_next_id = 0;
  return ++g_next_id;
}

// RETURNS - true if we should stop at this breakpoint, false if we
// should continue.

bool BreakpointSite::ShouldStop(
    StoppointCallbackContext *context,
    BreakpointLocationCollection &stopping_bp_locs) {
  m_hit_counter.Increment();
  // ShouldStop can do a lot of work, and might even come back and hit
  // this breakpoint site again.  So don't hold the m_constituents_mutex the
  // whole while.  Instead make a local copy of the collection and call
  // ShouldStop on the copy.
  BreakpointLocationCollection constituents_copy;
  {
    std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
    constituents_copy = m_constituents;
  }
  return constituents_copy.ShouldStop(context, stopping_bp_locs);
}

bool BreakpointSite::IsBreakpointAtThisSite(lldb::break_id_t bp_id) {
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  const size_t constituent_count = m_constituents.GetSize();
  for (size_t i = 0; i < constituent_count; i++) {
    if (m_constituents.GetByIndex(i)->GetBreakpoint().GetID() == bp_id)
      return true;
  }
  return false;
}

void BreakpointSite::Dump(Stream *s) const {
  if (s == nullptr)
    return;

  s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64
            "  type = %s breakpoint  hit_count = %-4u",
            GetID(), (uint64_t)m_addr, IsHardware() ? "hardware" : "software",
            GetHitCount());
}

void BreakpointSite::GetDescription(Stream *s, lldb::DescriptionLevel level) {
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  if (level != lldb::eDescriptionLevelBrief)
    s->Printf("breakpoint site: %d at 0x%8.8" PRIx64, GetID(),
              GetLoadAddress());
  m_constituents.GetDescription(s, level);
}

std::optional<uint32_t> BreakpointSite::GetSuggestedStackFrameIndex() {

  std::optional<uint32_t> result;
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  for (BreakpointLocationSP loc_sp : m_constituents.BreakpointLocations()) {
    std::optional<uint32_t> loc_frame_index =
        loc_sp->GetSuggestedStackFrameIndex();
    if (loc_frame_index) {
      if (result)
        result = std::max(*loc_frame_index, *result);
      else
        result = loc_frame_index;
    }
  }
  return result;
}

bool BreakpointSite::IsInternal() const { return m_constituents.IsInternal(); }

uint8_t *BreakpointSite::GetTrapOpcodeBytes() { return &m_trap_opcode[0]; }

const uint8_t *BreakpointSite::GetTrapOpcodeBytes() const {
  return &m_trap_opcode[0];
}

size_t BreakpointSite::GetTrapOpcodeMaxByteSize() const {
  return sizeof(m_trap_opcode);
}

bool BreakpointSite::SetTrapOpcode(const uint8_t *trap_opcode,
                                   uint32_t trap_opcode_size) {
  if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode)) {
    m_byte_size = trap_opcode_size;
    ::memcpy(m_trap_opcode, trap_opcode, trap_opcode_size);
    return true;
  }
  m_byte_size = 0;
  return false;
}

uint8_t *BreakpointSite::GetSavedOpcodeBytes() { return &m_saved_opcode[0]; }

const uint8_t *BreakpointSite::GetSavedOpcodeBytes() const {
  return &m_saved_opcode[0];
}

bool BreakpointSite::IsEnabled() const { return m_enabled; }

void BreakpointSite::SetEnabled(bool enabled) { m_enabled = enabled; }

void BreakpointSite::AddConstituent(const BreakpointLocationSP &constituent) {
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  m_constituents.Add(constituent);
}

size_t BreakpointSite::RemoveConstituent(lldb::break_id_t break_id,
                                         lldb::break_id_t break_loc_id) {
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  m_constituents.Remove(break_id, break_loc_id);
  return m_constituents.GetSize();
}

size_t BreakpointSite::GetNumberOfConstituents() {
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  return m_constituents.GetSize();
}

BreakpointLocationSP BreakpointSite::GetConstituentAtIndex(size_t index) {
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  return m_constituents.GetByIndex(index);
}

bool BreakpointSite::ValidForThisThread(Thread &thread) {
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  if (ThreadSP backed_thread = thread.GetBackedThread())
    return m_constituents.ValidForThisThread(*backed_thread);
  return m_constituents.ValidForThisThread(thread);
}

void BreakpointSite::BumpHitCounts() {
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  for (BreakpointLocationSP loc_sp : m_constituents.BreakpointLocations()) {
    loc_sp->BumpHitCount();
  }
}

bool BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size,
                                     lldb::addr_t *intersect_addr,
                                     size_t *intersect_size,
                                     size_t *opcode_offset) const {
  // The function should be called only for software breakpoints.
  lldbassert(GetType() == Type::eSoftware);

  if (m_byte_size == 0)
    return false;

  const lldb::addr_t bp_end_addr = m_addr + m_byte_size;
  const lldb::addr_t end_addr = addr + size;
  // Is the breakpoint end address before the passed in start address?
  if (bp_end_addr <= addr)
    return false;

  // Is the breakpoint start address after passed in end address?
  if (end_addr <= m_addr)
    return false;

  if (intersect_addr || intersect_size || opcode_offset) {
    if (m_addr < addr) {
      if (intersect_addr)
        *intersect_addr = addr;
      if (intersect_size)
        *intersect_size =
            std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr;
      if (opcode_offset)
        *opcode_offset = addr - m_addr;
    } else {
      if (intersect_addr)
        *intersect_addr = m_addr;
      if (intersect_size)
        *intersect_size =
            std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr;
      if (opcode_offset)
        *opcode_offset = 0;
    }
  }
  return true;
}

size_t BreakpointSite::CopyConstituentsList(
    BreakpointLocationCollection &out_collection) {
  std::lock_guard<std::recursive_mutex> guard(m_constituents_mutex);
  for (BreakpointLocationSP loc_sp : m_constituents.BreakpointLocations()) {
    out_collection.Add(loc_sp);
  }
  return out_collection.GetSize();
}
