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

#include <lib/fit/defer.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/features.h>
#include <zircon/status.h>
#include <zircon/syscalls/debug.h>
#include <zircon/syscalls/exception.h>
#include <zircon/types.h>

#include <algorithm>
#include <memory>
#include <optional>
#include <string>

#include "src/developer/debug/debug_agent/arch.h"
#include "src/developer/debug/debug_agent/binary_launcher.h"
#include "src/developer/debug/debug_agent/component_manager.h"
#include "src/developer/debug/debug_agent/debugged_job.h"
#include "src/developer/debug/debug_agent/debugged_process.h"
#include "src/developer/debug/debug_agent/debugged_thread.h"
#include "src/developer/debug/debug_agent/exception_handle.h"
#include "src/developer/debug/debug_agent/job_handle.h"
#include "src/developer/debug/debug_agent/process_breakpoint.h"
#include "src/developer/debug/debug_agent/system_interface.h"
#include "src/developer/debug/debug_agent/time.h"
#include "src/developer/debug/ipc/filter_utils.h"
#include "src/developer/debug/ipc/protocol.h"
#include "src/developer/debug/ipc/records.h"
#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/shared/status.h"
#include "src/developer/debug/shared/string_util.h"

#if defined(__linux__)
#include <unistd.h>
#endif

namespace debug_agent {

namespace {

constexpr size_t kMegabyte = 1024 * 1024;

std::string LogResumeRequest(const debug_ipc::ResumeRequest& request) {
  std::stringstream ss;
  ss << "Got resume request for ";

  // Print thread koids.
  if (request.ids.empty()) {
    ss << "all processes.";
  } else {
    for (size_t i = 0; i < request.ids.size(); i++) {
      if (i > 0)
        ss << ", ";
      ss << "(" << request.ids[i].process << ", " << request.ids[i].thread << ")";
    }
  }

  // Print step range.
  if (request.range_begin != request.range_end)
    ss << ", Range: [" << std::hex << request.range_begin << ", " << request.range_end << "]";

  return ss.str();
}

bool FilterDoesNotAppearIn(const Filter& needle, const std::vector<Filter>& haystack) {
  return std::ranges::none_of(haystack, [&needle](const auto& filter) {
    return debug::StringStartsWith(needle.filter().pattern, filter.filter().pattern);
  });
}

}  // namespace

DebugAgent::DebugAgent(std::unique_ptr<SystemInterface> system_interface)
    : adapter_(std::make_unique<RemoteAPIAdapter>(this, nullptr)),
      system_interface_(std::move(system_interface)),
      weak_factory_(this) {
  // Register ourselves to receive component events and limbo events.
  //
  // It's safe to pass |this| here because |this| owns |system_interface|, which owns
  // |ComponentManager| and |LimboProvider|.
  system_interface_->GetComponentManager().SetDebugAgent(this);
  system_interface_->GetLimboProvider().set_on_enter_limbo(
      [this](const LimboProvider::Record& record) { OnProcessEnteredLimbo(record); });

#ifdef __Fuchsia__
  // Watch the root job.
  auto status = AttachToRootJob();
  if (status.has_error()) {
    LOGS(Error) << "Failed to watch the root job: " << status.message();
  }
#endif  // __Fuchsia__
}

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

void DebugAgent::TakeAndConnectRemoteAPIStream(std::unique_ptr<debug::BufferedStream> stream) {
  // Now we can create a BufferedZxSocket to pass to the RemoteAPIAdapter. The data path is:
  //
  // BufferedZxSocket -> RemoteAPIAdapter -> DebugAgent
  //
  // DebugAgent owns both the BufferedZxSocket and RemoteAPIAdapter, since the DebugAgent can be
  // started without a socket connection to a host tool, so it is safe to capture |this|. When the
  // socket is closed, we exit.
  adapter_->set_stream(&stream->stream());
  stream->set_data_available_callback([this]() { adapter_->OnStreamReadable(); });
  stream->set_error_callback([this]() {
    // Unconditionally quit when the debug_ipc socket is closed.
    Disconnect();
    ClearState();
    debug::MessageLoop::Current()->QuitNow();
  });

  // Start listening.
  Connect(std::move(stream));
}

void DebugAgent::Connect(std::unique_ptr<debug::BufferedStream> stream) {
  FX_DCHECK(stream) << "Cannot connect to an invalid stream!";

  buffered_stream_ = std::move(stream);

  FX_CHECK(buffered_stream_->Start()) << "Failed to connect to the FIDL socket";
}

void DebugAgent::Disconnect() {
  // Can only disconnect from a connected state.
  FX_DCHECK(buffered_stream_);

  // Release all resources associated with the previous connection.
  buffered_stream_->Reset();
}

void DebugAgent::ClearState() {
  // Reset debugging State
  debug::LogBackend::Unset();

  // Detach from all jobs first so we stop getting process starting notifications.
  jobs_.clear();

  // Removes breakpoints before we detach from the processes, although it should also be safe
  // to reverse the order.
  breakpoints_.clear();
  // Detach us from all processes.
  procs_.clear();
}

void DebugAgent::RemoveDebuggedProcess(zx_koid_t process_koid) {
  auto found = procs_.find(process_koid);
  if (found == procs_.end())
    FX_NOTREACHED();
  else
    procs_.erase(found);
}

Breakpoint* DebugAgent::GetBreakpoint(uint32_t breakpoint_id) {
  if (auto found = breakpoints_.find(breakpoint_id); found != breakpoints_.end())
    return &found->second;
  return nullptr;
}

void DebugAgent::RemoveBreakpoint(uint32_t breakpoint_id) {
  if (auto found = breakpoints_.find(breakpoint_id); found != breakpoints_.end())
    breakpoints_.erase(found);
}

void DebugAgent::OnHello(const debug_ipc::HelloRequest& request, debug_ipc::HelloReply* reply) {
  if (request.version >= debug_ipc::kMinimumProtocolVersion &&
      request.version <= debug_ipc::kCurrentProtocolVersion) {
    // Downgrade only when the requested version is supported by us.
    ipc_version_ = request.version;
  } else {
    LOGS(Error) << "Unsupported IPC version: " << request.version << ", supported range is "
                << debug_ipc::kMinimumProtocolVersion << "-" << debug_ipc::kCurrentProtocolVersion;
    ipc_version_ = debug_ipc::kCurrentProtocolVersion;
  }

  // Signature is default-initialized.
  reply->version = ipc_version_;
  reply->arch = arch::GetCurrentArch();
  reply->platform = debug::CurrentSystemPlatform();

#if defined(__Fuchsia__)
  reply->page_size = zx_system_get_page_size();
#elif defined(__linux__)
  reply->page_size = getpagesize();
#else
#error Need platform page size.
#endif

  // Only enable log backend after the handshake is finished.
  debug::LogBackend::Set(this, true);
}

void DebugAgent::OnStatus(const debug_ipc::StatusRequest& request, debug_ipc::StatusReply* reply) {
  // Get the attached processes.
  reply->processes.reserve(procs_.size());
  for (auto& [process_koid, proc] : procs_) {
    debug_ipc::ProcessRecord process_record = {};
    process_record.process_koid = process_koid;
    process_record.process_name = proc->process_handle().GetName();

    process_record.components =
        system_interface_->GetComponentManager().FindComponentInfo(proc->process_handle());

    auto threads = proc->GetThreads();
    process_record.threads.reserve(threads.size());
    for (auto* thread : threads) {
      process_record.threads.emplace_back(
          thread->GetThreadRecord(debug_ipc::ThreadRecord::StackAmount::kMinimal));
    }

    process_record.shared_address_space = proc->process_handle().GetSharedAddressSpace();

    reply->processes.emplace_back(std::move(process_record));
  }

  reply->breakpoints.reserve(breakpoints_.size());
  for (auto& [_, bp] : breakpoints_) {
    reply->breakpoints.push_back(bp.settings());
  }

  reply->filters.reserve(filters_.size());
  for (auto& filter : filters_) {
    reply->filters.push_back(filter.filter());
  }

  // Get the limbo processes.
  if (system_interface_->GetLimboProvider().Valid()) {
    for (const auto& [process_koid, record] :
         system_interface_->GetLimboProvider().GetLimboRecords()) {
      debug_ipc::ProcessRecord process_record = {};
      process_record.process_koid = process_koid;
      process_record.process_name = record.process->GetName();

      process_record.components =
          system_interface_->GetComponentManager().FindComponentInfo(*record.process);

      // For now, only fill the thread blocked on exception.
      process_record.threads.push_back(record.thread->GetThreadRecord(process_koid));

      process_record.shared_address_space = record.process->GetSharedAddressSpace();

      reply->limbo.push_back(std::move(process_record));
    }
  }
}

void DebugAgent::OnRunBinary(const debug_ipc::RunBinaryRequest& request,
                             debug_ipc::RunBinaryReply* reply) {
  reply->timestamp = GetNowTimestamp();
  if (request.argv.empty()) {
    reply->status = debug::Status("No launch arguments provided");
    return;
  }

  LaunchProcess(request, reply);
}

void DebugAgent::OnRunComponent(const debug_ipc::RunComponentRequest& request,
                                debug_ipc::RunComponentReply* reply) {
  reply->status = system_interface_->GetComponentManager().LaunchComponent(request.url);
}

void DebugAgent::OnRunTest(const debug_ipc::RunTestRequest& request,
                           debug_ipc::RunTestReply* reply) {
  reply->status = system_interface_->GetComponentManager().LaunchTest(request.url, request.realm,
                                                                      request.case_filters);
}

void DebugAgent::OnKill(const debug_ipc::KillRequest& request, debug_ipc::KillReply* reply) {
  reply->timestamp = GetNowTimestamp();
  // See first if the process is in limbo.
  LimboProvider& limbo = system_interface_->GetLimboProvider();
  if (limbo.Valid() && limbo.IsProcessInLimbo(request.process_koid)) {
    // Release if from limbo, which will effectivelly kill it.
    reply->status = limbo.ReleaseProcess(request.process_koid);
    return;
  }

  // Otherwise search locally.
  auto debug_process = GetDebuggedProcess(request.process_koid);
  if (!debug_process) {
    reply->status = debug::Status("Process is not currently being debugged.");
    return;
  }

  debug_process->OnKill(request, reply);

  // Check if this was a limbo "kill". If so, mark this process to be removed from limbo when it
  // re-enters it and tell the client that we successfully killed it.
  if (reply->status.has_error() && debug_process->from_limbo()) {
    killed_limbo_procs_.insert(debug_process->koid());
    reply->status = debug::Status();
  }

  RemoveDebuggedProcess(request.process_koid);
}

void DebugAgent::OnDetach(const debug_ipc::DetachRequest& request, debug_ipc::DetachReply* reply) {
  reply->timestamp = GetNowTimestamp();

  // First check if the process is waiting in limbo. If so, release it.
  LimboProvider& limbo = system_interface_->GetLimboProvider();
  if (limbo.Valid() && limbo.IsProcessInLimbo(request.koid)) {
    reply->status = limbo.ReleaseProcess(request.koid);
    return;
  }

  auto debug_process = GetDebuggedProcess(request.koid);
  if (debug_process) {
    RemoveDebuggedProcess(request.koid);
    reply->status = debug::Status();
    return;
  }

  auto debugged_job = GetDebuggedJob(request.koid);
  if (debugged_job) {
    jobs_.erase(request.koid);
    reply->status = debug::Status();
    return;
  }

  reply->status = debug::Status("Not currently attached to " + std::to_string(request.koid) +
                                " to detach from.");
}

void DebugAgent::OnPause(const debug_ipc::PauseRequest& request, debug_ipc::PauseReply* reply) {
  std::vector<debug_ipc::ProcessThreadId> paused;
  DEBUG_LOG(Agent) << "Got Pause request";

  if (request.ids.empty()) {
    // Pause everything.
    paused = ClientSuspendAll();
  } else {
    // Pause specific threads.
    for (const debug_ipc::ProcessThreadId& id : request.ids) {
      if (DebuggedProcess* proc = GetDebuggedProcess(id.process)) {
        if (id.thread) {
          // Single thread in that process.
          if (DebuggedThread* thread = proc->GetThread(id.thread)) {
            thread->ClientSuspend(true);
            paused.push_back(id);
          } else {
            LOGS(Warn) << "Could not find thread by koid: " << id.thread;
          }
        } else {
          // All threads in the process.
          std::vector<debug_ipc::ProcessThreadId> proc_threads = proc->ClientSuspendAllThreads();
          paused.insert(paused.end(), proc_threads.begin(), proc_threads.end());
        }
      }
    }
  }

  // Save the affected thread info.
  for (const debug_ipc::ProcessThreadId& id : paused) {
    if (DebuggedThread* thread = GetDebuggedThread(id)) {
      reply->threads.push_back(
          thread->GetThreadRecord(debug_ipc::ThreadRecord::StackAmount::kMinimal));
    }
  }
}

void DebugAgent::OnResume(const debug_ipc::ResumeRequest& request, debug_ipc::ResumeReply* reply) {
  DEBUG_LOG(Agent) << LogResumeRequest(request);

  if (request.ids.empty()) {
    // All debugged processes.
    for (const auto& pair : procs_)
      pair.second->OnResume(request);
  } else {
    // Explicit list.
    for (const auto& id : request.ids) {
      if (DebuggedProcess* proc = GetDebuggedProcess(id.process)) {
        if (id.thread) {
          // Single thread in that process.
          if (DebuggedThread* thread = proc->GetThread(id.thread)) {
            thread->ClientResume(request);
          } else {
            LOGS(Warn) << "Could not find thread by koid: " << id.thread;
          }
        } else {
          // All threads in the process.
          proc->OnResume(request);
        }
      } else {
        LOGS(Warn) << "Could not find process by koid: " << id.process;
      }
    }
  }
}

void DebugAgent::OnModules(const debug_ipc::ModulesRequest& request,
                           debug_ipc::ModulesReply* reply) {
  DebuggedProcess* proc = GetDebuggedProcess(request.process_koid);
  if (proc)
    proc->OnModules(reply);
}

void DebugAgent::OnProcessTree(const debug_ipc::ProcessTreeRequest& request,
                               debug_ipc::ProcessTreeReply* reply) {
  reply->root = system_interface_->GetProcessTree();
}

void DebugAgent::OnThreads(const debug_ipc::ThreadsRequest& request,
                           debug_ipc::ThreadsReply* reply) {
  auto found = procs_.find(request.process_koid);
  if (found == procs_.end())
    return;

  reply->threads = found->second->GetThreadRecords();
}

void DebugAgent::OnReadMemory(const debug_ipc::ReadMemoryRequest& request,
                              debug_ipc::ReadMemoryReply* reply) {
  DebuggedProcess* proc = GetDebuggedProcess(request.process_koid);
  if (proc)
    proc->OnReadMemory(request, reply);
}

void DebugAgent::OnReadRegisters(const debug_ipc::ReadRegistersRequest& request,
                                 debug_ipc::ReadRegistersReply* reply) {
  DebuggedThread* thread = GetDebuggedThread(request.id);
  if (thread) {
    reply->registers = thread->ReadRegisters(request.categories);
  } else {
    LOGS(Error) << "Cannot find thread with koid: " << request.id.thread;
  }
}

void DebugAgent::OnWriteRegisters(const debug_ipc::WriteRegistersRequest& request,
                                  debug_ipc::WriteRegistersReply* reply) {
  DebuggedThread* thread = GetDebuggedThread(request.id);
  if (thread) {
    reply->status = debug::Status();
    reply->registers = thread->WriteRegisters(request.registers);
  } else {
    reply->status = debug::Status("Can not find thread " + std::to_string(request.id.thread) +
                                  " to write registers.");
    LOGS(Error) << "Cannot find thread with koid: " << request.id.thread;
  }
}

void DebugAgent::OnAddOrChangeBreakpoint(const debug_ipc::AddOrChangeBreakpointRequest& request,
                                         debug_ipc::AddOrChangeBreakpointReply* reply) {
  switch (request.breakpoint.type) {
    case debug_ipc::BreakpointType::kSoftware:
    case debug_ipc::BreakpointType::kHardware:
    case debug_ipc::BreakpointType::kReadWrite:
    case debug_ipc::BreakpointType::kWrite:
      return SetupBreakpoint(request, reply);
    case debug_ipc::BreakpointType::kLast:
      break;
  }

  FX_NOTREACHED() << "Invalid Breakpoint Type: " << static_cast<int>(request.breakpoint.type);
}

void DebugAgent::OnRemoveBreakpoint(const debug_ipc::RemoveBreakpointRequest& request,
                                    debug_ipc::RemoveBreakpointReply* reply) {
  RemoveBreakpoint(request.breakpoint_id);
}

void DebugAgent::OnSysInfo(const debug_ipc::SysInfoRequest& request,
                           debug_ipc::SysInfoReply* reply) {
  reply->version = system_interface_->GetSystemVersion();
  reply->num_cpus = system_interface_->GetNumCpus();
  reply->memory_mb = system_interface_->GetPhysicalMemory() / kMegabyte;

  reply->hw_breakpoint_count = arch::GetHardwareBreakpointCount();
  reply->hw_watchpoint_count = arch::GetHardwareWatchpointCount();
}

void DebugAgent::OnThreadStatus(const debug_ipc::ThreadStatusRequest& request,
                                debug_ipc::ThreadStatusReply* reply) {
  if (DebuggedThread* thread = GetDebuggedThread(request.id)) {
    reply->record = thread->GetThreadRecord(debug_ipc::ThreadRecord::StackAmount::kFull);
  } else {
    // When the thread is not found the thread record is set to "dead".
    reply->record.id = request.id;
    reply->record.state = debug_ipc::ThreadRecord::State::kDead;
  }
}

debug::Status DebugAgent::RegisterBreakpoint(Breakpoint* bp, zx_koid_t process_koid,
                                             uint64_t address) {
  DebuggedProcess* proc = GetDebuggedProcess(process_koid);
  if (proc)
    return proc->RegisterBreakpoint(bp, address);

  // The process might legitimately be not found if there was a race between
  // the process terminating and a breakpoint add/change.
  return debug::Status("Process not found when adding breakpoint");
}

void DebugAgent::UnregisterBreakpoint(Breakpoint* bp, zx_koid_t process_koid, uint64_t address) {
  // The process might legitimately be not found if it was terminated.
  DebuggedProcess* proc = GetDebuggedProcess(process_koid);
  if (proc)
    proc->UnregisterBreakpoint(bp, address);
}

void DebugAgent::SetupBreakpoint(const debug_ipc::AddOrChangeBreakpointRequest& request,
                                 debug_ipc::AddOrChangeBreakpointReply* reply) {
  uint32_t id = request.breakpoint.id;
  auto found = breakpoints_.find(id);
  if (found == breakpoints_.end()) {
    DEBUG_LOG(Agent) << "Creating new breakpoint " << request.breakpoint.id << " ("
                     << request.breakpoint.name << ").";
    found = breakpoints_
                .emplace(std::piecewise_construct, std::forward_as_tuple(id),
                         std::forward_as_tuple(this))
                .first;
  }

  reply->status = found->second.SetSettings(request.breakpoint);
}

debug::Status DebugAgent::RegisterWatchpoint(Breakpoint* bp, zx_koid_t process_koid,
                                             const debug::AddressRange& range) {
  DebuggedProcess* proc = GetDebuggedProcess(process_koid);
  if (proc)
    return proc->RegisterWatchpoint(bp, range);

  // The process might legitimately be not found if there was a race between the process terminating
  // and a breakpoint add/change.
  return debug::Status("Process not found when adding watchpoint");
}

void DebugAgent::UnregisterWatchpoint(Breakpoint* bp, zx_koid_t process_koid,
                                      const debug::AddressRange& range) {
  // The process might legitimately be not found if it was terminated.
  DebuggedProcess* proc = GetDebuggedProcess(process_koid);
  if (proc)
    proc->UnregisterWatchpoint(bp, range);
}

void DebugAgent::OnAddressSpace(const debug_ipc::AddressSpaceRequest& request,
                                debug_ipc::AddressSpaceReply* reply) {
  DebuggedProcess* proc = GetDebuggedProcess(request.process_koid);
  if (proc)
    proc->OnAddressSpace(request, reply);
}

void DebugAgent::OnUpdateFilter(const debug_ipc::UpdateFilterRequest& request,
                                debug_ipc::UpdateFilterReply* reply) {
  DEBUG_LOG(Agent) << "Received UpdateFilter request size=" << request.filters.size();
  filters_.clear();
  filters_.reserve(request.filters.size());

  for (const auto& debug_ipc_filter : request.filters) {
    auto filter = Filter(debug_ipc_filter);
    // Search all of the known ELF processes in the system for a match.
    auto matched_processes = filter.ApplyToJob(root_job_->job_handle(), *system_interface_);
    for (const auto& match : matched_processes) {
      std::vector<debug_ipc::ComponentInfo> component_info;

      if (auto process = system_interface().GetProcess(match.koid)) {
        component_info = system_interface().GetComponentManager().FindComponentInfo(*process);
      } else if (filter.filter().config.job_only) {
        // If this filter was configured with job_only then the koid values provided here will be
        // the koid of the job itself.
        component_info = system_interface().GetComponentManager().FindComponentInfo(match.koid);
      }

      auto result = CheckForRecursiveFilterMatches(filter, component_info);
      filters_.insert(filters_.end(), result.new_filters.begin(), result.new_filters.end());
      reply->matched_processes_for_filter.insert(reply->matched_processes_for_filter.end(),
                                                 result.new_matches.begin(),
                                                 result.new_matches.end());
    }

    // Also search all of the non-ELF components that we know about for a match to resolve recursive
    // filters.
    for (const auto& [_moniker, component_info] :
         system_interface_->GetComponentManager().GetNonElfComponentInfo()) {
      if (filter.MatchesComponent(component_info.moniker, component_info.url)) {
        auto result = CheckForRecursiveFilterMatches(filter, {component_info});
        filters_.insert(filters_.end(), result.new_filters.begin(), result.new_filters.end());
        reply->matched_processes_for_filter.insert(reply->matched_processes_for_filter.end(),
                                                   result.new_matches.begin(),
                                                   result.new_matches.end());
      }
    }

    if (!matched_processes.empty()) {
      reply->matched_processes_for_filter.emplace_back(filter.filter().id,
                                                       std::move(matched_processes));
    }

    filters_.push_back(filter);
  }
}

void DebugAgent::OnWriteMemory(const debug_ipc::WriteMemoryRequest& request,
                               debug_ipc::WriteMemoryReply* reply) {
  DebuggedProcess* proc = GetDebuggedProcess(request.process_koid);
  if (proc) {
    proc->OnWriteMemory(request, reply);
  } else {
    reply->status = debug::Status("Not attached to process " +
                                  std::to_string(request.process_koid) + " while writing memory.");
  }
}

void DebugAgent::OnLoadInfoHandleTable(const debug_ipc::LoadInfoHandleTableRequest& request,
                                       debug_ipc::LoadInfoHandleTableReply* reply) {
  DebuggedProcess* proc = GetDebuggedProcess(request.process_koid);
  if (proc)
    proc->OnLoadInfoHandleTable(request, reply);
  else
    reply->status =
        debug::Status("Not attached to process " + std::to_string(request.process_koid) +
                      " while getting the handle table.");
}

void DebugAgent::OnUpdateGlobalSettings(const debug_ipc::UpdateGlobalSettingsRequest& request,
                                        debug_ipc::UpdateGlobalSettingsReply* reply) {
  for (const auto& update : request.exception_strategies) {
    exception_strategies_[update.type] = update.value;
  }
}

void DebugAgent::OnSaveMinidump(const debug_ipc::SaveMinidumpRequest& request,
                                debug_ipc::SaveMinidumpReply* reply) {
  reply->status = debug::Status();

  DebuggedProcess* proc = GetDebuggedProcess(request.process_koid);

  if (!proc) {
    reply->status =
        debug::Status("No process found to save core from. Is there an attached process?");
    return;
  }

  proc->OnSaveMinidump(request, reply);
}

DebuggedJob* DebugAgent::GetDebuggedJob(zx_koid_t koid) {
  auto found = jobs_.find(koid);
  if (found == jobs_.end()) {
    return nullptr;
  }

  return found->second.get();
}

DebuggedProcess* DebugAgent::GetDebuggedProcess(zx_koid_t koid) {
  auto found = procs_.find(koid);
  if (found == procs_.end())
    return nullptr;
  return found->second.get();
}

DebuggedThread* DebugAgent::GetDebuggedThread(const debug_ipc::ProcessThreadId& id) {
  DebuggedProcess* process = GetDebuggedProcess(id.process);
  if (!process)
    return nullptr;
  return process->GetThread(id.thread);
}

std::vector<debug_ipc::ProcessThreadId> DebugAgent::ClientSuspendAll(zx_koid_t except_process,
                                                                     zx_koid_t except_thread) {
  // Neither or both koids must be supplied.
  FX_DCHECK((except_process == ZX_KOID_INVALID && except_thread == ZX_KOID_INVALID) ||
            (except_process != ZX_KOID_INVALID && except_thread != ZX_KOID_INVALID));

  std::vector<debug_ipc::ProcessThreadId> affected;

  for (const auto& [process_koid, process] : procs_) {
    std::vector<debug_ipc::ProcessThreadId> proc_threads;
    if (process_koid == except_process) {
      proc_threads = process->ClientSuspendAllThreads(except_thread);
    } else {
      proc_threads = process->ClientSuspendAllThreads();
    }

    affected.insert(affected.end(), proc_threads.begin(), proc_threads.end());
  }

  return affected;
}

bool DebugAgent::IsAttachedToParentOrAncestorOf(zx_koid_t parent) {
  while (parent != ZX_KOID_INVALID && parent != root_job_->koid()) {
    auto debugged_job = GetDebuggedJob(parent);
    if (debugged_job && debugged_job->type() == JobExceptionChannelType::kException) {
      // We are already attached to a parent job between the process and the root job.
      return true;
    }

    // Note if the process was torn down asynchronously by someone else, the ancestry tree could be
    // gone already, resulting in this being ZX_KOID_INVALID.
    //
    // TODO(https://fxbug.dev/377671670): Write better tests for this.
    parent = system_interface().GetParentJobKoid(parent);
  }

  return false;
}

bool DebugAgent::IsAttachedToParentOrAncestorOf(const ProcessHandle* process) {
  return IsAttachedToParentOrAncestorOf(process->GetJobKoid());
}

DebugAgent::RecursiveFilterMatchResult DebugAgent::CheckForRecursiveFilterMatches(
    const Filter& filter, const std::vector<debug_ipc::ComponentInfo>& component_info) {
  // If the filter doesn't have the recursive option set then we don't have to check anything.
  if (!filter.filter().config.recursive) {
    return {};
  }

  RecursiveFilterMatchResult result;

  // If a recursive filter matched on installation, then we also need to proactively install
  // the corresponding prefix filter that would match any descendant components.
  for (const auto& info : component_info) {
    if (auto recursive_filter = filter.MakeRecursiveFilter(info.moniker)) {
      // TODO(https://fxbug.dev/450924906): Handle conflicting filter option resolution.
      if (FilterDoesNotAppearIn(*recursive_filter, filters_) &&
          FilterDoesNotAppearIn(*recursive_filter, result.new_filters)) {
        debug_ipc::NotifyFilterCreated filter_created;
        filter_created.timestamp = GetNowTimestamp();
        filter_created.filter = recursive_filter->filter();
        filter_created.originating_filter_id = filter.filter().id;
        // The clients don't need to send another UpdateFilter request because we're adding the
        // new matches here.
        filter_created.participated_in_matching = true;

        // Tell the client(s) that we created a new filter.
        SendNotification(filter_created);

        auto new_matches =
            recursive_filter->ApplyToJob(root_job_->job_handle(), system_interface());
        if (!new_matches.empty()) {
          result.new_matches.emplace_back(recursive_filter->filter().id, new_matches);
        }

        result.new_filters.push_back(*recursive_filter);
      }
    }
  }

  return result;
}

std::vector<debug_ipc::FilterMatch> DebugAgent::AccumulateFilterMatches(
    const ProcessHandle& handle) {
  std::vector<debug_ipc::FilterMatch> matches;

  std::ranges::for_each(filters_, [&](const Filter& filter) {
    if (filter.MatchesProcess(handle, *system_interface_)) {
      matches.emplace_back(filter.filter().id,
                           std::vector<debug_ipc::MatchedTask>{
                               {.koid = handle.GetKoid(), .type = debug_ipc::TaskType::kProcess}});
    }
  });

  return matches;
}

debug::Status DebugAgent::AddDebuggedJob(DebuggedJobCreateInfo&& create_info, DebuggedJob** added) {
  *added = nullptr;

  // This function should never be called with a null handle. At worst, something in the system has
  // deleted this job out from under us, causing all syscalls using this handle to fail, but the
  // object should still be valid.
  FX_DCHECK(create_info.handle);

  zx_koid_t job_koid = create_info.handle->GetKoid();
  auto unique = std::make_unique<DebuggedJob>(this);
  *added = unique.get();

  jobs_[job_koid] = std::move(unique);

  if (auto status = (*added)->Init(std::move(create_info)); status.has_error()) {
    jobs_.erase(job_koid);
    *added = nullptr;
    return status;
  }

  return debug::Status();
}

debug::Status DebugAgent::AddDebuggedProcess(DebuggedProcessCreateInfo&& create_info,
                                             DebuggedProcess** new_process) {
  *new_process = nullptr;

  auto proc = std::make_unique<DebuggedProcess>(this);

  // Need to register the process before calling DebuggedProcess::Init() because Init() can
  // do things like make breakpoints that call back into this class.
  auto process_id = create_info.handle->GetKoid();
  *new_process = proc.get();
  procs_[process_id] = std::move(proc);

  if (auto status = (*new_process)->Init(std::move(create_info)); status.has_error()) {
    // Undo registration.
    procs_.erase(process_id);
    *new_process = nullptr;
    return status;
  }
  return debug::Status();
}

debug_ipc::ExceptionStrategy DebugAgent::GetExceptionStrategy(debug_ipc::ExceptionType type) {
  auto strategy = exception_strategies_.find(type);
  if (strategy == exception_strategies_.end()) {
    return debug_ipc::ExceptionStrategy::kFirstChance;
  }
  return strategy->second;
}

// Attaching ---------------------------------------------------------------------------------------

void DebugAgent::OnAttach(const debug_ipc::AttachRequest& request, debug_ipc::AttachReply* reply) {
  DEBUG_LOG(Agent) << "Attemping to attach to process " << request.koid;
  reply->timestamp = GetNowTimestamp();

  // See if we already have a DebuggedProcess for this koid. If we do and we're not already attached
  // (we could be attached to the parent job already), try to attach. This might fail if another
  // process eagerly claimed the exception channel before us.
  if (request.config.target == debug_ipc::TaskType::kProcess) {
    if (auto found = procs_.find(request.koid); found != procs_.end()) {
      DebuggedProcess* proc = found->second.get();
      if (proc->IsAttached()) {
        reply->status =
            debug::Status(debug::Status::kAlreadyExists,
                          "Already attached to process " + std::to_string(proc->koid()));
        DEBUG_LOG(Agent) << reply->status.message();
        return;
      }

      // If we get here it means we deferred binding the exception channel of this process, and the
      // client has requested explicitly to attach.
      reply->status = proc->AttachNow();
      if (reply->status.has_error()) {
        DEBUG_LOG(Agent) << std::format("Could not attach to process {}", proc->koid())
                         << reply->status.message();
      }

      DEBUG_LOG(Agent) << std::format("Attached to process {}", proc->koid());
      return;
    }
  }

  // First check if the process is in limbo. Sends the appropiate replies/notifications.
  if (system_interface_->GetLimboProvider().Valid()) {
    reply->status = AttachToLimboProcess(request.koid, reply);
    if (reply->status.ok())
      return;

    DEBUG_LOG(Agent) << "Could not attach to process in limbo: " << reply->status.message();
  }

  if (request.config.target == debug_ipc::TaskType::kJob) {
    if (!IsAttachedToParentOrAncestorOf(request.koid)) {
      reply->status = AttachToExistingJob(request.koid, request.config, reply);
    } else {
      reply->status =
          debug::Status(debug::Status::kAlreadyExists, "Already attached to ancestor job.");
    }

    return;
  }

  // Attempt to attach to an existing process. Sends the appropriate replies/notifications.
  reply->status = AttachToExistingProcess(request.koid, request.config, reply);
  if (reply->status.ok())
    return;

  // We didn't find a process.
  DEBUG_LOG(Agent) << "Could not attach to existing process: " << reply->status.message();
}

debug::Status DebugAgent::AttachToLimboProcess(zx_koid_t process_koid,
                                               debug_ipc::AttachReply* reply) {
  LimboProvider& limbo = system_interface_->GetLimboProvider();
  FX_DCHECK(limbo.Valid());

  // Obtain the process and exception from limbo.
  auto retrieved = limbo.RetrieveException(process_koid);
  if (retrieved.is_error()) {
    debug::Status status = retrieved.error_value();
    DEBUG_LOG(Agent) << "Could not retrieve exception from limbo: " << status.message();
    return status;
  }

  LimboProvider::RetrievedException& exception = retrieved.value();

  DebuggedProcessCreateInfo create_info(std::move(exception.process));
  create_info.from_limbo = true;

  DebuggedProcess* process = nullptr;
  debug::Status status = AddDebuggedProcess(std::move(create_info), &process);
  if (status.has_error())
    return status;

  reply->koid = process->koid();
  reply->name = process->process_handle().GetName();
  reply->components =
      system_interface_->GetComponentManager().FindComponentInfo(process->process_handle());

  // Send the reply first, then the notifications about the process and threads.
  debug::MessageLoop::Current()->PostTask(FROM_HERE, [weak_this = GetWeakPtr(), koid = reply->koid,
                                                      exception = std::move(exception)]() mutable {
    if (!weak_this)
      return;
    if (DebuggedProcess* process = weak_this->GetDebuggedProcess(koid)) {
      process->PopulateCurrentThreads();
      process->SuspendAndSendModules();

      zx_koid_t thread_koid = exception.thread->GetKoid();

      // Pass in the exception handle to the corresponding thread.
      DebuggedThread* exception_thread = nullptr;
      for (DebuggedThread* thread : process->GetThreads()) {
        if (thread->koid() == thread_koid) {
          exception_thread = thread;
          break;
        }
      }

      if (exception_thread)
        exception_thread->set_exception_handle(std::move(exception.exception));
    }
  });

  return debug::Status();
}

debug::Status DebugAgent::AttachToExistingProcess(zx_koid_t process_koid,
                                                  const debug_ipc::AttachConfig& config,
                                                  debug_ipc::AttachReply* reply) {
  std::unique_ptr<ProcessHandle> process_handle = system_interface_->GetProcess(process_koid);
  if (!process_handle)
    return debug::Status("Can't find process " + std::to_string(process_koid) + " to attach to.");

  DebuggedProcess* process = nullptr;
  DebuggedProcessCreateInfo create_info(std::move(process_handle));
  create_info.priority = config.priority;

  if (auto status = AddDebuggedProcess(std::move(create_info), &process); status.has_error())
    return status;

  reply->koid = process->koid();
  reply->name = process->process_handle().GetName();
  reply->components =
      system_interface_->GetComponentManager().FindComponentInfo(process->process_handle());
  reply->shared_address_space = process->process_handle().GetSharedAddressSpace();

  // Send the reply first, then the notifications about the process and threads.
  debug::MessageLoop::Current()->PostTask(
      FROM_HERE, [weak_this = GetWeakPtr(), koid = reply->koid, config]() mutable {
        if (!weak_this)
          return;
        if (DebuggedProcess* process = weak_this->GetDebuggedProcess(koid)) {
          process->PopulateCurrentThreads();
          if (!debug_ipc::AttachConfig::ShouldDeferModules(config))
            process->SuspendAndSendModules();
        }
      });

  return debug::Status();
}

debug::Status DebugAgent::AttachToRootJob() {
  DebuggedJobCreateInfo info(system_interface().GetRootJob());
  // Only ever attach to the root job's debugger channel.
  info.type = JobExceptionChannelType::kDebugger;

  // The root job is otherwise treated just like any other job.
  auto status = AddDebuggedJob(std::move(info), &root_job_);

  // This function should only be called on Fuchsia, and we should always be able to get the
  // root job.
  FX_DCHECK(status.ok());
  FX_DCHECK(root_job_ != nullptr);

  return status;
}

debug::Status DebugAgent::AttachToExistingJob(zx_koid_t job_koid,
                                              const debug_ipc::AttachConfig& config,
                                              debug_ipc::AttachReply* reply) {
  DebuggedJob* debugged_job;
  DebuggedJobCreateInfo info(system_interface().GetJob(job_koid));
  info.type = (config.priority == debug_ipc::AttachConfig::Priority::kWeak)
                  ? JobExceptionChannelType::kDebugger
                  : JobExceptionChannelType::kException;

  // Check the validity of the JobHandle here. We don't pass the job's koid to |AddDebuggedJob|, so
  // it can only get the koid by dereferencing the JobHandle, so we can print a better error message
  // here.
  if (info.handle == nullptr) {
    return debug::Status(std::format("Job with koid {} not found", job_koid));
  }

  auto status = AddDebuggedJob(std::move(info), &debugged_job);

  if (status.has_error()) {
    return status;
  }

  // Won't have a reply object to fill out if this comes from a filter.
  if (reply) {
    reply->components = system_interface().GetComponentManager().FindComponentInfo(job_koid);
    reply->koid = job_koid;
  }

  return status;
}

void DebugAgent::LaunchProcess(const debug_ipc::RunBinaryRequest& request,
                               debug_ipc::RunBinaryReply* reply) {
  FX_DCHECK(!request.argv.empty());
  DEBUG_LOG(Process) << "Launching binary " << request.argv.front();

  std::unique_ptr<BinaryLauncher> launcher = system_interface_->GetLauncher();
  reply->status = launcher->Setup(request.argv);
  if (reply->status.has_error())
    return;

  DebuggedProcessCreateInfo create_info(launcher->GetProcess());
  create_info.stdio = launcher->ReleaseStdioHandles();

  // The DebuggedProcess must be attached to the new process' exception port before actually
  // Starting the process to avoid racing with the program initialization.
  DebuggedProcess* new_process = nullptr;
  reply->status = AddDebuggedProcess(std::move(create_info), &new_process);
  if (reply->status.has_error())
    return;

  reply->status = launcher->Start();
  if (reply->status.has_error()) {
    RemoveDebuggedProcess(new_process->koid());
    return;
  }

  // Success, fill out the reply.
  reply->process_id = new_process->koid();
  reply->process_name = new_process->process_handle().GetName();
}

void DebugAgent::OnProcessChanged(ProcessChangedHow how,
                                  std::unique_ptr<ProcessHandle> process_handle) {
  if (procs_.find(process_handle->GetKoid()) != procs_.end()) {
    return;  // The process might have been attached in |LaunchProcess|.
  }

  debug_ipc::NotifyProcessStarting::Type type = debug_ipc::NotifyProcessStarting::Type::kLast;
  StdioHandles stdio;  // Will be filled in only for components.
  std::string process_name_override;
  std::vector<debug_ipc::FilterMatch> matched_filters;

  // If we have any matching filters for this event, then we'll consolidate their configurations
  // into an attach configuration which will determine what actions we take immediately and what
  // actions we wait for the client to request.
  //
  // In cases we've launched something ourselves, we just use the default attach configuration.
  debug_ipc::AttachConfig attach_config;

  if (how == ProcessChangedHow::kStarting &&
      system_interface_->GetComponentManager().OnProcessStart(*process_handle, &stdio,
                                                              &process_name_override)) {
    type = debug_ipc::NotifyProcessStarting::Type::kLaunch;
  } else if (auto matches = AccumulateFilterMatches(*process_handle); !matches.empty()) {
    matched_filters = std::move(matches);
    type = debug_ipc::NotifyProcessStarting::Type::kAttach;

    FX_DCHECK(!matched_filters.empty());

    const auto& attach_configs =
        debug_ipc::GetAttachConfigsForFilterMatches(matched_filters, GetIpcFilters());

    if (!attach_configs.empty()) {
      // We should only end up with one attach configuration, even if we have many matching filters.
      FX_DCHECK(attach_configs.size() == 1);
      FX_DCHECK(attach_configs.contains(process_handle->GetKoid()));

      // If we have a filter, then derive the attach configuration from that, otherwise use the
      // default values specified in AttachConfig. This is safe to dereference since we assert that
      // it's contained above.
      attach_config = attach_configs.find(process_handle->GetKoid())->second;
    } else if (!matched_filters.empty()) {
      // Returns true if the given |match| is found in our list of installed filters and it is
      // configured to be a job_only filter.
      auto is_job_only = [this](const debug_ipc::FilterMatch match) -> bool {
        const auto filter = debug_ipc::GetFilterForId(GetIpcFilters(), match.id);

        if (filter == nullptr)
          return false;

        return filter->config.job_only;
      };

      if (std::ranges::all_of(matched_filters, is_job_only)) {
        // If all of the matching filters were labeled as job-only, then we still want to make sure
        // that we send a process starting event to the clients, but we explicitly do not want to
        // claim its exception channel.
        //
        // This will be the case for non-recursive job-only filters.
        attach_config.priority = debug_ipc::AttachConfig::Priority::kMinimal;
      }
    }
  } else {
#ifdef __linux__
    // For now, unconditionally attach to all forked processes on Linux.
    // TODO(brettw) This should be revisited when we get better frontend UI for dealing with forks.
    type = debug_ipc::NotifyProcessStarting::Type::kAttach;
#else
    return;
#endif
  }

  bool job_only = attach_config.target == debug_ipc::TaskType::kJob;

  // If we have a job only filter then we only watch for exceptions from the parent job and do not
  // attach to the process (but we do create a DebuggedProcess object for it below).
  if (job_only) {
    // Already attached to this job and have a DebuggedProcess for it, there's nothing to do.
    // This path is quite common when we are attaching to jobs located relatively high in a job tree
    // which can spawn many processes. We will get many notifications of new processes.
    if (GetDebuggedJob(process_handle->GetJobKoid()) &&
        GetDebuggedProcess(process_handle->GetKoid())) {
      return;
    }

    // There's nothing to stop a user from installing a filter that matches a child component with
    // its own unique job_id and then another filter that matches a parent, so this won't completely
    // stop you from attaching to multiple jobs in the job tree. If this happens, releasing an
    // exception reported from the child job job will result in us catching it again at the next job
    // in the tree we're attached to, which could be confusing.
    if (!IsAttachedToParentOrAncestorOf(process_handle.get())) {
      auto status = AttachToExistingJob(process_handle->GetJobKoid(), attach_config, nullptr);
      if (status.has_error()) {
        LOGS(Warn) << "AttachToJob failed for job " << process_handle->GetJobKoid() << ": "
                   << status.message();
      }
    }

    // We can't return yet because we need to tell the front end about this process and its threads
    // because the front end needs to be able to associate all exceptions with a process and thread.
    // Importantly, the DebuggedProcessCreateInfo will defer claiming the process's exception
    // channel.
  }

  DEBUG_LOG(Process) << "Process starting, koid: " << process_handle->GetKoid();

  // Prepare the notification but don't send yet because |process_handle| will be moved and
  // |AddDebuggedProcess| may fail.
  debug_ipc::NotifyProcessStarting notify;
  notify.type = type;
  notify.koid = process_handle->GetKoid();
  notify.name = process_name_override.empty() ? process_handle->GetName() : process_name_override;
  notify.timestamp = GetNowTimestamp();
  notify.components = system_interface_->GetComponentManager().FindComponentInfo(*process_handle);
  notify.filter_ids.reserve(matched_filters.size());
  std::ranges::transform(
      matched_filters, std::back_inserter(notify.filter_ids),
      [](const auto& match) -> debug_ipc::Filter::Identifier { return match.id; });
  notify.attach_config = attach_config;
  notify.shared_address_space = process_handle->GetSharedAddressSpace();

  DebuggedProcessCreateInfo create_info(std::move(process_handle));
  create_info.stdio = std::move(stdio);

  // We have to be careful about choosing which priority applies to us. This logic is for creating
  // (and possibly attaching to) processes, but if the filter that created this attach configuration
  // was labeled as job_only, then we cannot simply inherit it's priority. Instead we should wait
  // for further instructions from the client, e.g. an AttachRequest being sent for this koid with
  // an
  create_info.priority =
      job_only ? debug_ipc::AttachConfig::Priority::kMinimal : attach_config.priority;

  DebuggedProcess* new_process = nullptr;
  debug::Status status = AddDebuggedProcess(std::move(create_info), &new_process);

  if (status.has_error()) {
    LOGS(Warn) << "Failed to attach to process " << notify.koid << ": " << status.message();
    return;
  }

  SendNotification(notify);

  new_process->PopulateCurrentThreads();

  // If this is a strong attach, we need to send modules here. We cannot wait for the client to
  // request all the modules later because we won't be able to load symbols early enough to set
  // breakpoints on things like _dl_start, which will resolve from the first modules being sent
  // now. The rest of the modules will be sent later on when the client requests them or we hit the
  // loader breakpoint.
  if (!debug_ipc::AttachConfig::ShouldDeferModules(attach_config)) {
    new_process->SuspendAndSendModules();
  }
}

void DebugAgent::OnComponentStarted(const std::string& moniker, const std::string& url,
                                    zx_koid_t job_koid) {
  auto matching_filters = GetMatchingFiltersForComponentInfo(moniker, url);
  debug_ipc::NotifyComponentStarting component_started;

  // We have to be very careful to not invalidate the pointers that are being iterated over in
  // |matching_filters|, which are owned by |filters_|, so we instead have to delay putting this
  // into |filters_| until after we're done iterating. We know we'll only install a single filter
  // for |moniker|, if any, so we don't have to worry about handling multiple additions here.
  std::optional<debug_ipc::Filter> maybe_realm_filter = std::nullopt;

  // Install recursive filters.
  for (auto filter : matching_filters) {
    // When any recursive filter matches here, we install a component moniker prefix filter so
    // that any sub-components created as children of this one are attached implicitly. Only one
    // filter match needs to be recursive for us to install the prefix filter for |moniker|, and
    // we only need to install one new filter per invocation of this function. The client is
    // notified of this filter so that it is not removed on subsequent UpdateFilter requests,
    // which the client may do shortly after receiving this notification. Notably, we do not
    // enable the recursive flag on this filter, which would be redundant with the parent filter.
    if (auto realm_filter = filter->MakeRecursiveFilter(moniker)) {
      // TODO(https://fxbug.dev/450924906): Handle conflicting filter option resolution.
      if (maybe_realm_filter) {
        // Ensure that the filter that would have been created by this matching filter matches what
        // we already had in |maybe_realm_filter|. Since this notification is only received for a
        // single component instance, all filters that match should create the same realm filter.
        FX_DCHECK(maybe_realm_filter->pattern == realm_filter->filter().pattern);
        continue;
      }
      if (FilterDoesNotAppearIn(*realm_filter, filters_)) {
        // Support older clients on debug_ipc version < 73.
        component_started.filter = realm_filter->filter();

        debug_ipc::NotifyFilterCreated filter_created;
        filter_created.timestamp = GetNowTimestamp();
        filter_created.filter = realm_filter->filter();
        filter_created.originating_filter_id = filter->filter().id;
        // We aren't doing any explicit matching here, the client will need to send an UpdateFilter
        // request for that to happen, but we will match against new ProcessStarting events with
        // this new filter so it is also acceptable for the client(s) to delay sending an update.
        filter_created.participated_in_matching = false;
        SendNotification(filter_created);

        // We have to be very careful to not invalidate the pointers that are being iterated over
        // in |matching_filters|, which are owned by |filters_|, so we instead have to delay
        // putting this into our filter list until after we're done iterating.
        maybe_realm_filter = realm_filter->filter();
      }
    }

    // All matching filters are reported in the notification. Make sure we don't falsely report that
    // non-job-only filters match this component started event (process starting events come
    // separately via a job's DEBUGGER exception channel).
    if (job_koid != ZX_KOID_INVALID && filter->filter().config.job_only) {
      component_started.matching_filters.emplace_back(
          filter->filter().id, std::vector<debug_ipc::MatchedTask>{
                                   {.koid = job_koid, .type = debug_ipc::TaskType::kJob}});
    }
  }

  // And add the component information, if something matched.
  if (!component_started.matching_filters.empty()) {
    component_started.component.moniker = moniker;
    component_started.component.url = url;
    component_started.timestamp = GetNowTimestamp();

    SendNotification(component_started);
  }

  // Lastly, insert the new filter if we have one. If this causes |filters_| to reallocate, then
  // the pointers in |matching_filters| are now invalid.
  if (maybe_realm_filter) {
    filters_.emplace_back(*maybe_realm_filter);
  }
}

void DebugAgent::OnComponentExited(const std::string& moniker, const std::string& url) {
  if (!GetMatchingFiltersForComponentInfo(moniker, url).empty()) {
    debug_ipc::NotifyComponentExiting notify;
    notify.component.moniker = moniker;
    notify.component.url = url;
    notify.timestamp = GetNowTimestamp();

    SendNotification(notify);
  }
}

void DebugAgent::OnTestComponentExited(const std::string& url) {
  debug_ipc::NotifyTestExited notify;
  notify.url = url;
  notify.timestamp = GetNowTimestamp();

  SendNotification(notify);
}

void DebugAgent::InjectProcessForTest(std::unique_ptr<DebuggedProcess> process) {
  procs_[process->koid()] = std::move(process);
}

void DebugAgent::OnProcessEnteredLimbo(const LimboProvider::Record& record) {
  zx_koid_t process_koid = record.process->GetKoid();

  // First check if we were to "kill" this process.
  if (auto it = killed_limbo_procs_.find(process_koid); it != killed_limbo_procs_.end()) {
    system_interface_->GetLimboProvider().ReleaseProcess(process_koid);
    killed_limbo_procs_.erase(it);
    return;
  }

  std::string process_name = record.process->GetName();
  DEBUG_LOG(Agent) << "Process " << process_name << " (" << process_koid << ") entered limbo.";

  debug_ipc::NotifyProcessStarting process_starting = {};
  process_starting.type = debug_ipc::NotifyProcessStarting::Type::kLimbo;
  process_starting.koid = process_koid;
  process_starting.name = std::move(process_name);
  process_starting.timestamp = GetNowTimestamp();

  SendNotification(process_starting);
}

std::vector<const Filter*> DebugAgent::GetMatchingFiltersForComponentInfo(
    const std::string& moniker, const std::string& url) const {
  std::vector<const Filter*> matches;
  for (const auto& filter : filters_) {
    if (filter.MatchesComponent(moniker, url)) {
      matches.push_back(&filter);
    }
  }

  return matches;
}

std::vector<const debug_ipc::Filter*> DebugAgent::GetIpcFilters() const {
  std::vector<const debug_ipc::Filter*> ipc_filters;
  ipc_filters.reserve(filters_.size());

  std::ranges::transform(
      filters_, std::back_inserter(ipc_filters),
      [](const auto& filter) -> const debug_ipc::Filter* { return &filter.filter(); });

  return ipc_filters;
}

void DebugAgent::RemoveObserver(DebugAgentObserver* observer) {
  observers_.RemoveObserver(observer);

  // If we just removed the last server and there is no debug_ipc client, it's time to exit.
  if (!observers_.might_have_observers() && !is_connected()) {
    ClearState();
    debug::MessageLoop::Current()->QuitNow();
  }
}

void DebugAgent::WriteLog(debug::LogSeverity severity, const debug::FileLineFunction& location,
                          std::string log) {
  debug_ipc::NotifyLog notify;
  switch (severity) {
    case debug::LogSeverity::kInfo:
      return;  // Only forward warnings and errors for now.
    case debug::LogSeverity::kWarn:
      notify.severity = debug_ipc::NotifyLog::Severity::kWarn;
      break;
    case debug::LogSeverity::kError:
      notify.severity = debug_ipc::NotifyLog::Severity::kError;
      break;
  }
  notify.location.file = location.file();
  notify.location.function = location.function();
  notify.location.line = location.line();
  notify.log = log;

  SendNotification(notify);
}

}  // namespace debug_agent
