// 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;

debug::Status ProcessBreakpoint::Init() { return Update(); }

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

debug::Status ProcessBreakpoint::RegisterBreakpoint(Breakpoint* breakpoint) {
  // Shouldn't get duplicates.
  if (std::find(breakpoints_.begin(), breakpoints_.end(), breakpoint) != breakpoints_.end())
    return debug::Status("Breakpoint already registered");

  // Should be the same type.
  if (Type() != breakpoint->settings().type)
    return debug::Status("Breakpoint should be the same type");

  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<debug_ipc::ProcessThreadId> proc_thread_pairs =
          agent->ClientSuspendAll(process_->koid(), hitting_thread->koid());

      for (const debug_ipc::ProcessThreadId& id : proc_thread_pairs) {
        if (DebuggedThread* thread = agent->GetDebuggedThread(id))
          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
