//===-- BreakpointSite.cpp --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
// C++ Includes
#include <inttypes.h>

// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointSite.h"

#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSiteList.h"
#include "lldb/Utility/Stream.h"

using namespace lldb;
using namespace lldb_private;

BreakpointSite::BreakpointSite(BreakpointSiteList *list,
                               const BreakpointLocationSP &owner,
                               lldb::addr_t addr, bool use_hardware)
    : StoppointLocation(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_owners(), m_owners_mutex() {
  m_owners.Add(owner);
}

BreakpointSite::~BreakpointSite() {
  BreakpointLocationSP bp_loc_sp;
  const size_t owner_count = m_owners.GetSize();
  for (size_t i = 0; i < owner_count; i++) {
    m_owners.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) {
  std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
  IncrementHitCount();
  return m_owners.ShouldStop(context);
}

bool BreakpointSite::IsBreakpointAtThisSite(lldb::break_id_t bp_id) {
  std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
  const size_t owner_count = m_owners.GetSize();
  for (size_t i = 0; i < owner_count; i++) {
    if (m_owners.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  hw_index = %i  hit_count = %-4u",
            GetID(), (uint64_t)m_addr, IsHardware() ? "hardware" : "software",
            GetHardwareIndex(), GetHitCount());
}

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

bool BreakpointSite::IsInternal() const { return m_owners.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::AddOwner(const BreakpointLocationSP &owner) {
  std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
  m_owners.Add(owner);
}

size_t BreakpointSite::RemoveOwner(lldb::break_id_t break_id,
                                   lldb::break_id_t break_loc_id) {
  std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
  m_owners.Remove(break_id, break_loc_id);
  return m_owners.GetSize();
}

size_t BreakpointSite::GetNumberOfOwners() {
  std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
  return m_owners.GetSize();
}

BreakpointLocationSP BreakpointSite::GetOwnerAtIndex(size_t index) {
  std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
  return m_owners.GetByIndex(index);
}

bool BreakpointSite::ValidForThisThread(Thread *thread) {
  std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
  return m_owners.ValidForThisThread(thread);
}

void BreakpointSite::BumpHitCounts() {
  std::lock_guard<std::recursive_mutex> guard(m_owners_mutex);
  for (BreakpointLocationSP loc_sp : m_owners.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 {
  // We only use software traps for software breakpoints
  if (!IsHardware()) {
    if (m_byte_size > 0) {
      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;
    }
  }
  return false;
}

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