// 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 <inttypes.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 "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_thread.h"
#include "src/developer/debug/debug_agent/exception_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/agent_protocol.h"
#include "src/developer/debug/ipc/message_reader.h"
#include "src/developer/debug/ipc/message_writer.h"
#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/shared/platform_message_loop.h"
#include "src/developer/debug/shared/stream_buffer.h"
#include "src/developer/debug/shared/zx_status.h"
#include "src/lib/fxl/strings/concatenate.h"
#include "src/lib/fxl/strings/string_printf.h"

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

}  // namespace

DebugAgent::DebugAgent(std::unique_ptr<SystemInterface> system_interface)
    : system_interface_(std::move(system_interface)), weak_factory_(this) {
  // Set a callback to the LimboProvider to let us know when new processes enter the limbo.
  system_interface_->GetLimboProvider().set_on_enter_limbo(
      [agent = GetWeakPtr()](const LimboProvider::Record& record) {
        if (!agent)
          return;
        agent->OnProcessEnteredLimbo(record);
      });
}

DebugAgent::~DebugAgent() {
  // Clear the callback to prevent dangling pointers.
  system_interface_->GetLimboProvider().set_on_enter_limbo(LimboProvider::OnEnterLimboCallback());
}

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

void DebugAgent::Connect(debug::StreamBuffer* stream) {
  FX_DCHECK(!stream_) << "A debug agent should not be connected twice!";
  stream_ = stream;
}

void DebugAgent::Disconnect() {
  FX_DCHECK(stream_);
  stream_ = nullptr;

  // Remove all DebuggedProcess and DebuggedJob on disconnect. The logic here should be consistent
  // with zxdb::System::DidDisconnect() so that further reconnecting won't create any surprise.
  jobs_.clear();
  // Removes breakpoints before we detach from the processes, although it should also be safe to
  // reverse the order.
  breakpoints_.clear();
  // The destructor of the DebuggedProcess will detach us from the process.
  procs_.clear();
}

debug::StreamBuffer* DebugAgent::stream() {
  FX_DCHECK(stream_);
  return stream_;
}

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

void DebugAgent::RemoveDebuggedJob(zx_koid_t job_koid) {
  auto found = jobs_.find(job_koid);
  if (found == jobs_.end())
    FX_NOTREACHED();
  else
    jobs_.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::OnConfigAgent(const debug_ipc::ConfigAgentRequest& request,
                               debug_ipc::ConfigAgentReply* reply) {
  reply->results = HandleActions(request.actions, &configuration_);
}

void DebugAgent::OnHello(const debug_ipc::HelloRequest& request, debug_ipc::HelloReply* reply) {
  // Version and signature are default-initialized to their current values.
  reply->arch = arch::GetCurrentArch();
}

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();

    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));
    }

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

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

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

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

void DebugAgent::OnLaunch(const debug_ipc::LaunchRequest& request, debug_ipc::LaunchReply* reply) {
  switch (request.inferior_type) {
    case debug_ipc::InferiorType::kBinary:
      LaunchProcess(request, reply);
      return;
    case debug_ipc::InferiorType::kComponent:
      LaunchComponent(request, reply);
      return;
    case debug_ipc::InferiorType::kLast:
      break;
  }

  reply->timestamp = GetNowTimestamp();
  reply->status = debug::Status("Invalid inferior type to launch.");
}

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();
  switch (request.type) {
    case debug_ipc::TaskType::kJob: {
      if (auto debug_job = GetDebuggedJob(request.koid)) {
        RemoveDebuggedJob(request.koid);
        reply->status = debug::Status();
      } else {
        reply->status = debug::Status("Not currently attached to job " +
                                      std::to_string(request.koid) + " to detach from.");
      }
      break;
    }
    case debug_ipc::TaskType::kProcess: {
      // 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();
      } else {
        reply->status = debug::Status("Not currently attached to process " +
                                      std::to_string(request.koid) + " to detach from.");
      }
      break;
    }
    default:
      reply->status = debug::Status("Bad task type to detach from.");
  }
}

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

  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 {
            FX_LOGS(WARNING) << "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::OnQuitAgent(const debug_ipc::QuitAgentRequest& request,
                             debug_ipc::QuitAgentReply* reply) {
  debug::MessageLoop::Current()->QuitNow();
}

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 {
            FX_LOGS(WARNING) << "Could not find thread by koid: " << id.thread;
          }
        } else {
          // All threads in the process.
          proc->OnResume(request);
        }
      } else {
        FX_LOGS(WARNING) << "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 {
    FX_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.");
    FX_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::OnProcessStatus(const debug_ipc::ProcessStatusRequest& request,
                                 debug_ipc::ProcessStatusReply* reply) {
  auto it = procs_.find(request.process_koid);
  if (it == procs_.end()) {
    reply->status =
        debug::Status("Not currently attached to process " + std::to_string(request.process_koid));
    return;
  }

  DebuggedProcess* process = it->second.get();

  debug::MessageLoop::Current()->PostTask(FROM_HERE, [this, process]() mutable {
    debug_ipc::NotifyProcessStarting notify = {};
    notify.koid = process->koid();
    notify.name = process->process_handle().GetName();
    notify.timestamp = GetNowTimestamp();

    debug_ipc::MessageWriter writer;
    debug_ipc::WriteNotifyProcessStarting(notify, &writer);
    stream()->Write(writer.MessageComplete());

    // Send the modules notification.
    process->SuspendAndSendModulesIfKnown();
  });

  reply->status = debug::Status();
}

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::OnJobFilter(const debug_ipc::JobFilterRequest& request,
                             debug_ipc::JobFilterReply* reply) {
  DebuggedJob* job = GetDebuggedJob(request.job_koid);
  if (!job) {
    reply->status = debug::Status("Not attached to job " + std::to_string(request.job_koid) +
                                  " while adding a filter.");
    return;
  }

  for (const auto& match : job->SetFilters(std::move(request.filters)))
    reply->matched_processes.push_back(match->GetKoid());
  reply->status = debug::Status();
}

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

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

DebuggedJob* DebugAgent::GetDebuggedJob(zx_koid_t koid) {
  auto found = jobs_.find(koid);
  if (found == jobs_.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;
}

debug::Status DebugAgent::AddDebuggedJob(std::unique_ptr<JobHandle> job_handle) {
  zx_koid_t koid = job_handle->GetKoid();
  auto job = std::make_unique<DebuggedJob>(this, std::move(job_handle));
  if (auto status = job->Init(); status.has_error()) {
    FX_LOGS(WARNING) << "Failed to attach to job " << koid << ": " << status.message();
    return status;
  }

  jobs_[koid] = std::move(job);
  return debug::Status();
}

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

  auto proc = std::make_unique<DebuggedProcess>(this, std::move(create_info));
  if (auto status = proc->Init(); status.has_error())
    return status;

  auto process_id = proc->koid();
  *new_process = proc.get();
  procs_[process_id] = std::move(proc);
  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 ---------------------------------------------------------------------------------------

namespace {

void SendAttachReply(DebugAgent* debug_agent, uint32_t transaction_id, const debug::Status& status,
                     zx_koid_t process_koid = ZX_HANDLE_INVALID,
                     const std::string& process_name = "") {
  debug_ipc::AttachReply reply;
  reply.status = status;
  reply.koid = process_koid;
  reply.name = process_name;
  reply.timestamp = GetNowTimestamp();

  debug_ipc::MessageWriter writer;
  debug_ipc::WriteReply(reply, transaction_id, &writer);
  debug_agent->stream()->Write(writer.MessageComplete());
}

}  // namespace

void DebugAgent::OnAttach(std::vector<char> serialized) {
  debug_ipc::MessageReader reader(std::move(serialized));
  debug_ipc::AttachRequest request;
  uint32_t transaction_id = 0;
  if (!debug_ipc::ReadRequest(&reader, &request, &transaction_id)) {
    FX_LOGS(WARNING) << "Got bad debugger attach request, ignoring.";
    return;
  }

  OnAttach(transaction_id, request);
}

void DebugAgent::OnAttach(uint32_t transaction_id, const debug_ipc::AttachRequest& request) {
  if (request.type == debug_ipc::TaskType::kProcess) {
    AttachToProcess(request.koid, transaction_id);
    return;
  }

  // All other attach types are variants of job attaches.
  std::unique_ptr<JobHandle> job;
  if (request.type == debug_ipc::TaskType::kJob) {
    job = system_interface_->GetJob(request.koid);
  } else if (request.type == debug_ipc::TaskType::kSystemRoot) {
    job = system_interface_->GetRootJob();
    if (job)
      attached_root_job_koid_ = job->GetKoid();
  } else {
    FX_LOGS(WARNING) << "Got bad debugger attach request type, ignoring.";
    return;
  }

  debug_ipc::AttachReply reply;

  // Don't return early since we always need to send the reply, even on fail.
  if (job) {
    DEBUG_LOG(Agent) << "Attaching to job " << job->GetKoid();

    reply.name = job->GetName();
    reply.koid = job->GetKoid();
    reply.status = AddDebuggedJob(std::move(job));
    reply.timestamp = GetNowTimestamp();
  } else {
    DEBUG_LOG(Agent) << "Failed to get the job.";
    reply.status = debug::Status("Could not get the job.");
  }

  // Send the reply.
  debug_ipc::MessageWriter writer;
  debug_ipc::WriteReply(reply, transaction_id, &writer);
  stream()->Write(writer.MessageComplete());
}

void DebugAgent::AttachToProcess(zx_koid_t process_koid, uint32_t transaction_id) {
  DEBUG_LOG(Agent) << "Attemping to attach to process " << process_koid;

  // See if we're already attached to this process.
  for (auto& [koid, proc] : procs_) {
    if (koid == process_koid) {
      debug::Status error(debug::Status::kAlreadyExists,
                          "Already attached to process " + std::to_string(proc->koid()));
      DEBUG_LOG(Agent) << error.message();
      SendAttachReply(this, transaction_id, error);
      return;
    }
  }

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

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

  // Attempt to attach to an existing process. Sends the appropriate replies/notifications.
  auto status = AttachToExistingProcess(process_koid, transaction_id);
  if (status.ok())
    return;

  DEBUG_LOG(Agent) << "Could not attach to existing process: " << status.message();

  // We didn't find a process.
  SendAttachReply(this, transaction_id, status);
}

debug::Status DebugAgent::AttachToLimboProcess(zx_koid_t process_koid, uint32_t transaction_id) {
  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* debugged_process = nullptr;
  debug::Status status = AddDebuggedProcess(std::move(create_info), &debugged_process);
  if (status.has_error())
    return status;

  // Send the response, then the notifications about the process and threads.
  //
  // DO NOT RETURN FAILURE AFTER THIS POINT or the attach reply will be duplicated (the caller will
  // fall back on non-limbo processes if this function fails and will send another reply).
  SendAttachReply(this, transaction_id, debug::Status(), process_koid,
                  debugged_process->process_handle().GetName());

  debugged_process->PopulateCurrentThreads();
  debugged_process->SuspendAndSendModulesIfKnown();

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

  // Pass in the exception handle to the corresponding thread.
  DebuggedThread* exception_thread = nullptr;
  for (DebuggedThread* thread : debugged_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, uint32_t transaction_id) {
  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;
  if (auto status =
          AddDebuggedProcess(DebuggedProcessCreateInfo(std::move(process_handle)), &process);
      status.has_error())
    return status;

  // Send the response, then the notifications about the process and threads.
  SendAttachReply(this, transaction_id, debug::Status(), process_koid,
                  process->process_handle().GetName());

  process->PopulateCurrentThreads();
  process->SuspendAndSendModulesIfKnown();

  return debug::Status();
}

void DebugAgent::LaunchProcess(const debug_ipc::LaunchRequest& request,
                               debug_ipc::LaunchReply* reply) {
  FX_DCHECK(!request.argv.empty());
  reply->inferior_type = debug_ipc::InferiorType::kBinary;
  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::LaunchComponent(const debug_ipc::LaunchRequest& request,
                                 debug_ipc::LaunchReply* reply) {
  *reply = {};

  // This is a hack. It will fail if the debugger isn't already attached to either the system or
  // component root jobs. Ideally we would get the exact parent job for the component being launched
  // and not depend on what the client may have already attached to.
  DebuggedJob* job = GetDebuggedJob(attached_root_job_koid_);
  if (!job) {
    reply->status = debug::Status(
        "Could not obtain component root job. It could be another debugger is "
        "already running or this is a user OS build.");
    FX_LOGS(WARNING) << reply->status.message();
    return;
  }

  reply->inferior_type = debug_ipc::InferiorType::kComponent;
  reply->status = system_interface_->GetComponentManager().LaunchComponent(job, request.argv,
                                                                           &reply->component_id);
}

void DebugAgent::OnProcessStart(const std::string& filter,
                                std::unique_ptr<ProcessHandle> process_handle) {
  DEBUG_LOG(Process) << "Process starting, koid: " << process_handle->GetKoid();

  auto process_koid = process_handle->GetKoid();
  StdioHandles stdio;  // Will be filled in only for components.
  uint64_t component_id = system_interface_->GetComponentManager().OnProcessStart(filter, stdio);

  // Send notification, then create debug process so that thread notification is sent after this.
  debug_ipc::NotifyProcessStarting notify;
  notify.koid = process_koid;
  notify.name = process_handle->GetName();
  notify.component_id = component_id;
  notify.timestamp = GetNowTimestamp();

  debug_ipc::MessageWriter writer;
  debug_ipc::WriteNotifyProcessStarting(notify, &writer);
  stream()->Write(writer.MessageComplete());

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

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

  if (new_process) {
    // In some edge-cases (see DebuggedProcess::RegisterDebugState() for more) the loader state is
    // known at startup. Send it if so.
    new_process->SuspendAndSendModulesIfKnown();
  }
}

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();

  debug_ipc::MessageWriter writer;
  debug_ipc::WriteNotifyProcessStarting(std::move(process_starting), &writer);
  stream()->Write(writer.MessageComplete());
}

}  // namespace debug_agent
