blob: 66ff3ccca1fef8b2dd836adb529b97dd294cbfc7 [file] [log] [blame]
// 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.
#ifndef GARNET_BIN_DEBUG_AGENT_DEBUG_AGENT_H_
#define GARNET_BIN_DEBUG_AGENT_DEBUG_AGENT_H_
#include <zircon/types.h>
#include <map>
#include <memory>
#include "garnet/bin/debug_agent/breakpoint.h"
#include "garnet/bin/debug_agent/debugged_job.h"
#include "garnet/bin/debug_agent/debugged_process.h"
#include "garnet/bin/debug_agent/remote_api.h"
#include "garnet/bin/debug_agent/watchpoint.h"
#include "garnet/lib/debug_ipc/helper/stream_buffer.h"
#include "lib/fxl/macros.h"
#include "lib/svc/cpp/services.h"
namespace debug_agent {
// Main state and control for the debug agent.
class DebugAgent : public RemoteAPI,
public ProcessStartHandler,
public Breakpoint::ProcessDelegate,
public Watchpoint::ProcessDelegate {
public:
// A MessageLoopZircon should already be set up on the current thread.
//
// The stream must outlive this class. It will be used to send data to the
// client. It will not be read (that's the job of the provider of the
// RemoteAPI).
explicit DebugAgent(debug_ipc::StreamBuffer* stream,
std::shared_ptr<component::Services> services);
~DebugAgent();
debug_ipc::StreamBuffer* stream() { return stream_; }
void RemoveDebuggedProcess(zx_koid_t process_koid);
void RemoveDebuggedJob(zx_koid_t job_koid);
void RemoveBreakpoint(uint32_t breakpoint_id);
void OnProcessStart(zx::process process) override;
bool should_quit() const { return should_quit_; }
private:
// RemoteAPI implementation.
void OnHello(const debug_ipc::HelloRequest& request,
debug_ipc::HelloReply* reply) override;
void OnLaunch(const debug_ipc::LaunchRequest& request,
debug_ipc::LaunchReply* reply) override;
void OnKill(const debug_ipc::KillRequest& request,
debug_ipc::KillReply* reply) override;
void OnAttach(std::vector<char> serialized) override;
void OnDetach(const debug_ipc::DetachRequest& request,
debug_ipc::DetachReply* reply) override;
void OnPause(const debug_ipc::PauseRequest& request,
debug_ipc::PauseReply* reply) override;
void OnQuitAgent(const debug_ipc::QuitAgentRequest& request,
debug_ipc::QuitAgentReply* reply) override;
void OnResume(const debug_ipc::ResumeRequest& request,
debug_ipc::ResumeReply* reply) override;
void OnModules(const debug_ipc::ModulesRequest& request,
debug_ipc::ModulesReply* reply) override;
void OnProcessTree(const debug_ipc::ProcessTreeRequest& request,
debug_ipc::ProcessTreeReply* reply) override;
void OnThreads(const debug_ipc::ThreadsRequest& request,
debug_ipc::ThreadsReply* reply) override;
void OnReadMemory(const debug_ipc::ReadMemoryRequest& request,
debug_ipc::ReadMemoryReply* reply) override;
void OnReadRegisters(const debug_ipc::ReadRegistersRequest& request,
debug_ipc::ReadRegistersReply* reply) override;
void OnWriteRegisters(const debug_ipc::WriteRegistersRequest& request,
debug_ipc::WriteRegistersReply* reply) override;
void OnAddOrChangeBreakpoint(
const debug_ipc::AddOrChangeBreakpointRequest& request,
debug_ipc::AddOrChangeBreakpointReply* reply) override;
void OnRemoveBreakpoint(const debug_ipc::RemoveBreakpointRequest& request,
debug_ipc::RemoveBreakpointReply* reply) override;
void OnThreadStatus(const debug_ipc::ThreadStatusRequest& request,
debug_ipc::ThreadStatusReply* reply) override;
void OnAddressSpace(const debug_ipc::AddressSpaceRequest& request,
debug_ipc::AddressSpaceReply* reply) override;
void OnJobFilter(const debug_ipc::JobFilterRequest& request,
debug_ipc::JobFilterReply* reply) override;
void OnWriteMemory(const debug_ipc::WriteMemoryRequest& request,
debug_ipc::WriteMemoryReply* reply) override;
void OnSymbolTables(const debug_ipc::SymbolTablesRequest& request,
debug_ipc::SymbolTablesReply* reply) override;
// Breakpoint::ProcessDelegate implementation --------------------------------
zx_status_t RegisterBreakpoint(Breakpoint* bp, zx_koid_t process_koid,
uint64_t address) override;
void UnregisterBreakpoint(Breakpoint* bp, zx_koid_t process_koid,
uint64_t address) override;
// Watchpoint::ProcessDelegate implementation --------------------------------
zx_status_t RegisterWatchpoint(Watchpoint*, zx_koid_t process_koid,
const debug_ipc::AddressRange&) override;
void UnregisterWatchpoint(Watchpoint*, zx_koid_t process_koid,
const debug_ipc::AddressRange&) override;
// Job/Process/Thread Management ---------------------------------------------
// Returns the debugged process/thread for the given koid(s) or null if not
// found.
DebuggedProcess* GetDebuggedProcess(zx_koid_t koid);
DebuggedJob* GetDebuggedJob(zx_koid_t koid);
DebuggedThread* GetDebuggedThread(zx_koid_t process_koid,
zx_koid_t thread_koid);
// Returns a pointer to the newly created object.
DebuggedProcess* AddDebuggedProcess(zx_koid_t process_koid,
zx::process zx_proc,
bool resume_initial_thread);
DebuggedJob* AddDebuggedJob(zx_koid_t job_koid, zx::job zx_job);
debug_ipc::StreamBuffer* stream_;
std::shared_ptr<component::Services> services_;
std::map<zx_koid_t, std::unique_ptr<DebuggedProcess>> procs_;
std::map<zx_koid_t, std::unique_ptr<DebuggedJob>> jobs_;
std::map<uint32_t, Breakpoint> breakpoints_;
std::map<uint32_t, Watchpoint> watchpoints_;
// Whether the debug agent should exit.
// The main reason for this is receiving a QuitNow message.
bool should_quit_ = false;
FXL_DISALLOW_COPY_AND_ASSIGN(DebugAgent);
};
} // namespace debug_agent
#endif // GARNET_BIN_DEBUG_AGENT_DEBUG_AGENT_H_