// 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 "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(); }

zx_status_t 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 ZX_OK;
}

zx_status_t SoftwareBreakpoint::Install() {
  FX_DCHECK(!installed_);

  // Read previous instruction contents.
  size_t actual = 0;
  zx_status_t status = process_->process_handle().ReadMemory(
      address(), &previous_data_, sizeof(arch::BreakInstructionType), &actual);
  if (status != ZX_OK)
    return status;
  if (actual != sizeof(arch::BreakInstructionType))
    return ZX_ERR_UNAVAILABLE;

  // Replace with breakpoint instruction.
  status = process_->process_handle().WriteMemory(address(), &arch::kBreakInstruction,
                                                  sizeof(arch::BreakInstructionType), &actual);
  if (status != ZX_OK)
    return status;
  if (actual != sizeof(arch::BreakInstructionType))
    return ZX_ERR_UNAVAILABLE;

  installed_ = true;
  return ZX_OK;
}

zx_status_t SoftwareBreakpoint::Uninstall() {
  if (!installed_)
    return ZX_OK;  // 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;
  zx_status_t status = process_->process_handle().ReadMemory(
      address(), &current_contents, sizeof(arch::BreakInstructionType), &actual);
  if (status != ZX_OK || actual != sizeof(arch::BreakInstructionType))
    return ZX_OK;  // Probably unmapped, safe to ignore.

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

  status = process_->process_handle().WriteMemory(address(), &previous_data_,
                                                  sizeof(arch::BreakInstructionType), &actual);
  if (status != ZX_OK || actual != sizeof(arch::BreakInstructionType)) {
    FX_LOGS(WARNING) << "Unable to remove breakpoint at 0x" << std::hex << address() << ": "
                     << zx_status_get_string(status);
  }

  installed_ = false;
  return ZX_OK;
}

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 = sizeof(arch::BreakInstructionType);
  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;
}

}  // namespace debug_agent
