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

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

#include "src/developer/debug/debug_agent/breakpoint.h"
#include "src/developer/debug/debug_agent/debug_agent.h"
#include "src/developer/debug/debug_agent/debugged_thread.h"
#include "src/developer/debug/debug_agent/hardware_breakpoint.h"
#include "src/developer/debug/debug_agent/software_breakpoint.h"
#include "src/developer/debug/shared/logging/logging.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace debug_agent {

ProcessBreakpoint::ProcessBreakpoint(Breakpoint* breakpoint, DebuggedProcess* process,
                                     uint64_t address)
    : process_(process), address_(address), weak_factory_(this) {
  breakpoints_.push_back(breakpoint);
}

ProcessBreakpoint::~ProcessBreakpoint() = default;

zx_status_t ProcessBreakpoint::Init() { return Update(); }

fxl::WeakPtr<ProcessBreakpoint> ProcessBreakpoint::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

zx_status_t ProcessBreakpoint::RegisterBreakpoint(Breakpoint* breakpoint) {
  // Shouldn't get duplicates.
  if (std::find(breakpoints_.begin(), breakpoints_.end(), breakpoint) != breakpoints_.end())
    return ZX_ERR_ALREADY_BOUND;

  // Should be the same type.
  if (Type() != breakpoint->settings().type)
    return ZX_ERR_INVALID_ARGS;

  breakpoints_.push_back(breakpoint);
  // Check if we need to install/uninstall a breakpoint.
  return Update();
}

bool ProcessBreakpoint::UnregisterBreakpoint(Breakpoint* breakpoint) {
  DEBUG_LOG(Breakpoint) << "Unregistering breakpoint " << breakpoint->settings().id << " ("
                        << breakpoint->settings().name << ").";

  auto found = std::find(breakpoints_.begin(), breakpoints_.end(), breakpoint);
  if (found == breakpoints_.end()) {
    FX_NOTREACHED();  // Should always be found.
  } else {
    breakpoints_.erase(found);
  }
  // Check if we need to install/uninstall a breakpoint.
  Update();
  return !breakpoints_.empty();
}

bool ProcessBreakpoint::ShouldHitThread(zx_koid_t thread_koid) const {
  for (const Breakpoint* bp : breakpoints_) {
    if (bp->AppliesToThread(process_->koid(), thread_koid))
      return true;
  }

  return false;
}

void ProcessBreakpoint::OnHit(DebuggedThread* hitting_thread,
                              debug_ipc::BreakpointType exception_type,
                              std::vector<debug_ipc::BreakpointStats>& hit_breakpoints,
                              std::vector<debug_ipc::ThreadRecord>& other_affected_threads) {
  // This will be filled in with the largest scope to stop.
  debug_ipc::Stop max_stop = debug_ipc::Stop::kNone;

  DebugAgent* agent = process_->debug_agent();

  // How much stack to capture for the suspended threads.
  constexpr auto kSuspendedStackAmount = debug_ipc::ThreadRecord::StackAmount::kMinimal;

  hit_breakpoints.clear();
  for (Breakpoint* breakpoint : breakpoints_) {
    // Only care for breakpoints that match the exception type.
    if (!Breakpoint::DoesExceptionApply(breakpoint->settings().type, exception_type))
      continue;

    breakpoint->OnHit();

    // The breakpoint stats are for the client, don't tell it about our internal ones.
    if (!breakpoint->is_debug_agent_internal())
      hit_breakpoints.push_back(breakpoint->stats());

    if (static_cast<uint32_t>(breakpoint->settings().stop) > static_cast<uint32_t>(max_stop))
      max_stop = breakpoint->settings().stop;
  }

  // Apply the maximal stop mode.
  switch (max_stop) {
    case debug_ipc::Stop::kNone: {
      // In this case the client will be in charge of resuming the thread because it may need to do
      // stuff like printing a message.
      break;
    }
    case debug_ipc::Stop::kThread: {
      // The thread is already stopped, nothing to do.
      break;
    }
    case debug_ipc::Stop::kProcess: {
      // Suspend each thread in the process except the one that just hit the exception (leave it
      // suspended in the exception).
      std::vector<zx_koid_t> suspended_koids =
          process_->ClientSuspendAllThreads(hitting_thread->koid());

      // Save the record for each suspended thread.
      for (zx_koid_t affected_thread : suspended_koids) {
        if (DebuggedThread* thread = process_->GetThread(affected_thread))
          other_affected_threads.push_back(thread->GetThreadRecord(kSuspendedStackAmount));
      }
      break;
    }
    case debug_ipc::Stop::kAll: {
      // Suspend each thread in all processes except the one that just hit the exception (leave it
      // suspended in the exception).
      std::vector<std::pair<zx_koid_t, zx_koid_t>> proc_thread_pairs =
          agent->ClientSuspendAll(process_->koid(), hitting_thread->koid());

      for (auto& [process_koid, thread_koid] : proc_thread_pairs) {
        if (DebuggedThread* thread = agent->GetDebuggedThread(process_koid, thread_koid))
          other_affected_threads.push_back(thread->GetThreadRecord(kSuspendedStackAmount));
      }
      break;
    }
  }
}

void ProcessBreakpoint::BeginStepOver(DebuggedThread* thread) {
  // Note that this request may get silently dropped in some edge cases (see EnqueueStepOver
  // comment) so don't keep any state about this request.
  process_->EnqueueStepOver(this, thread);
}

}  // namespace debug_agent
