// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/debug_agent/software_breakpoint.h"

#include <inttypes.h>
#include <lib/syslog/cpp/macros.h>

#include <algorithm>

#include "src/developer/debug/debug_agent/breakpoint.h"
#include "src/developer/debug/debug_agent/process_breakpoint.h"
#include "src/developer/debug/debug_agent/process_handle.h"
#include "src/developer/debug/shared/logging/logging.h"

namespace debug_agent {

namespace {

std::string LogPreamble(ProcessBreakpoint* b) {
  std::stringstream ss;

  ss << "[SW BP 0x" << std::hex << b->address();
  bool first = true;

  // Add the names of all the breakpoints associated with this process breakpoint.
  ss << " (";
  for (Breakpoint* breakpoint : b->breakpoints()) {
    if (!first) {
      first = false;
      ss << ", ";
    }
    ss << breakpoint->settings().name;
  }

  ss << ")] ";
  return ss.str();
}

}  // namespace

SoftwareBreakpoint::SoftwareBreakpoint(Breakpoint* breakpoint, DebuggedProcess* process,
                                       uint64_t address)
    : ProcessBreakpoint(breakpoint, process, address) {}

SoftwareBreakpoint::~SoftwareBreakpoint() { Uninstall(); }

debug::Status SoftwareBreakpoint::Update() {
  // Software breakpoints remain installed as long as even one remains active, regardless of which
  // threads are targeted.
  int sw_bp_count = 0;
  for (Breakpoint* bp : breakpoints()) {
    if (bp->settings().type == debug_ipc::BreakpointType::kSoftware)
      sw_bp_count++;
  }

  if (sw_bp_count == 0 && installed_) {
    Uninstall();
  } else if (sw_bp_count > 0 && !installed_) {
    return Install();
  }

  return debug::Status();
}

debug::Status SoftwareBreakpoint::Install() {
  FX_DCHECK(!installed_);

  // Read previous instruction contents.
  size_t actual = 0;
  if (debug::Status status = process_->process_handle().ReadMemory(
          address(), &previous_data_, arch::kBreakInstructionSize, &actual);
      status.has_error())
    return status;
  if (actual != arch::kBreakInstructionSize)
    return debug::Status("Could not read breakpoint memory.");

  // Replace with breakpoint instruction.
  if (debug::Status status = process_->process_handle().WriteMemory(
          address(), &arch::kBreakInstruction, arch::kBreakInstructionSize, &actual);
      status.has_error())
    return status;
  if (actual != arch::kBreakInstructionSize)
    return debug::Status("Could not write breakpoint memory.");

  installed_ = true;
  return debug::Status();
}

debug::Status SoftwareBreakpoint::Uninstall() {
  auto status = UninstallFromMemorySpace(process_->process_handle());
  installed_ = false;
  return status;
}

// This must use the specified process handle and not mark the breakpoint as uninstalled. This is
// used both by Uninstall() for the normal case, as well as uninstalling breakpoints for forked
// processes (which will be a different process than we're recorded as being installed into).
debug::Status SoftwareBreakpoint::UninstallFromMemorySpace(ProcessHandle& process_handle) {
  if (!installed_)
    return debug::Status();  // Not installed.

  // If the breakpoint was previously installed it means the memory address was valid and writable,
  // so we generally expect to be able to do the same write to uninstall it. But it could have been
  // unmapped during execution or even remapped with something else. So verify that it's still a
  // breakpoint instruction before doing any writes.
  arch::BreakInstructionType current_contents = 0;
  size_t actual = 0;
  debug::Status status =
      process_handle.ReadMemory(address(), &current_contents, arch::kBreakInstructionSize, &actual);
  if (status.has_error() || actual != arch::kBreakInstructionSize)
    return debug::Status();  // Probably unmapped, safe to ignore.

  if (current_contents != arch::kBreakInstruction) {
    LOGS(Warn) << "Debug break instruction unexpectedly replaced at 0x" << std::hex << address();
    return debug::Status();  // Replaced with something else, ignore.
  }

  status =
      process_handle.WriteMemory(address(), &previous_data_, arch::kBreakInstructionSize, &actual);
  if (status.has_error() || actual != arch::kBreakInstructionSize) {
    LOGS(Warn) << "Unable to remove breakpoint at 0x" << std::hex << address();
  }

  return debug::Status();
}

void SoftwareBreakpoint::FixupMemoryBlock(debug_ipc::MemoryBlock* block) {
  if (block->data.empty())
    return;  // Nothing to do.
  FX_DCHECK(static_cast<size_t>(block->size) == block->data.size());

  size_t src_size = arch::kBreakInstructionSize;
  const uint8_t* src = reinterpret_cast<uint8_t*>(&previous_data_);

  // Simple implementation to prevent boundary errors (ARM instructions are 32-bits and could be
  // hanging partially off either end of the requested buffer).
  for (size_t i = 0; i < src_size; i++) {
    uint64_t dest_address = address() + i;
    if (dest_address >= block->address && dest_address < block->address + block->size)
      block->data[dest_address - block->address] = src[i];
  }
}

void SoftwareBreakpoint::ExecuteStepOver(DebuggedThread* thread) {
  DEBUG_LOG(Breakpoint) << LogPreamble(this) << "Thread " << thread->koid() << " is stepping over.";
  currently_stepping_over_thread_ = thread->GetWeakPtr();
  thread->set_stepping_over_breakpoint(true);

  SuspendAllOtherThreads(thread->koid());

  Uninstall(thread);

  // This thread now has to continue running.
  thread->InternalResumeException();
}

void SoftwareBreakpoint::EndStepOver(DebuggedThread* thread) {
  FX_DCHECK(thread->stepping_over_breakpoint());
  FX_DCHECK(currently_stepping_over_thread_);
  FX_DCHECK(currently_stepping_over_thread_->koid() == thread->koid())
      << " Expected " << currently_stepping_over_thread_->koid() << ", Got " << thread->koid();

  DEBUG_LOG(Breakpoint) << LogPreamble(this) << "Thread " << thread->koid() << " ending step over.";
  thread->set_stepping_over_breakpoint(false);
  currently_stepping_over_thread_.reset();

  // Install the breakpoint again.
  // NOTE(donosoc): For multiple threads stepping over (queue), this is inefficient as threads are
  //                suspended and there is no need to reinstall them every time, expect for
  //                implementation simplicity. If performance becomes an issue, we could create a
  //                notification that the process calls when the complete step queue has been done
  //                that tells the breakpoints to reinstall themselves.
  Update();

  // Tell the process we're done stepping over.
  process_->OnBreakpointFinishedSteppingOver();
}

void SoftwareBreakpoint::StepOverCleanup(DebuggedThread* thread) {
  DEBUG_LOG(Breakpoint) << LogPreamble(this) << "Finishing step over for thread " << thread->koid();

  // We are done stepping over this thread, so we can remove the suspend tokens. Normally this means
  // cleaning all the suspend tokens, if there is only one thread in the stepping over queue or the
  // next step over is another breakpoint.
  //
  // But in the case that another thread is stepping over *the same* breakpoint, cleaning all the
  // tokens would resume all the threads that have just been suspended by the next instance of the
  // step over.
  //
  // For this case we need the ability to maintain more than one suspend tokens per thread: one for
  // the first step over and another for the second, as they coincide between the process callind
  // |ExecuteStepOver| on the second instance and callind |StepOverCleanup| on the first one.
  auto it = suspend_tokens_.begin();
  while (it != suspend_tokens_.end()) {
    // Calculate the upper bound (so we skip over repeated keys).
    auto cur_it = it;
    it = suspend_tokens_.upper_bound(it->first);

    // We do not erase a token for the thread we just stepped over, because it will be the only
    // thread that will not have 2 suspend tokens: It will have the one taken by the next step over,
    // as the first one didn't get one.
    if (cur_it->first == thread->koid())
      continue;

    // All other threads would have 2 suspend tokens (one for the first step over and one for the
    // second), meaning that we can safely remove the first one.
    suspend_tokens_.erase(cur_it);
  }

  // Remote the thread from the exception.
  thread->InternalResumeException();
}

void SoftwareBreakpoint::SuspendAllOtherThreads(zx_koid_t stepping_over_koid) {
  std::vector<DebuggedThread*> suspended_threads;
  for (DebuggedThread* thread : process_->GetThreads()) {
    // We do not suspend the stepping over thread.
    if (thread->koid() == stepping_over_koid)
      continue;

    // Only one thread should be stepping over at a time.
    if (thread->stepping_over_breakpoint() && thread->koid() != stepping_over_koid) {
      FX_NOTREACHED() << "Thread " << thread->koid() << " is stepping over. Only thread "
                      << stepping_over_koid << " should be stepping over.";
    }

    // We keep every other thread suspended.
    // If this is a re-entrant breakpoint (two threads in a row are stepping over the same
    // breakpoint), we could have more than one token for each thread.
    suspend_tokens_.insert({thread->koid(), thread->InternalSuspend(false)});
  }

  // We wait on all the suspend signals to trigger.
  for (DebuggedThread* thread : suspended_threads) {
    bool suspended =
        thread->thread_handle().WaitForSuspension(DebuggedThread::DefaultSuspendDeadline());
    FX_DCHECK(suspended) << "Thread " << thread->koid();
  }
}

std::vector<zx_koid_t> SoftwareBreakpoint::CurrentlySuspendedThreads() const {
  std::vector<zx_koid_t> koids;
  koids.reserve(suspend_tokens_.size());
  for (auto& [thread_koid, _] : suspend_tokens_) {
    koids.emplace_back(thread_koid);
  }

  std::sort(koids.begin(), koids.end());
  return koids;
}

bool SoftwareBreakpoint::IsInternalLdSoBreakpoint() const {
  for (const Breakpoint* bp : breakpoints()) {
    if (bp->is_internal_ld_so())
      return true;
  }
  return false;
}

}  // namespace debug_agent
