blob: d4124601f91e02c01fbc17024fc414ad1f02cd74 [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 SRC_DEVELOPER_DEBUG_DEBUG_AGENT_ARCH_H_
#define SRC_DEVELOPER_DEBUG_DEBUG_AGENT_ARCH_H_
#include <lib/zx/process.h>
#include <lib/zx/thread.h>
#include <zircon/syscalls/debug.h>
#include "src/developer/debug/debug_agent/arch_helpers.h"
#include "src/developer/debug/debug_agent/arch_types.h"
#include "src/developer/debug/ipc/protocol.h"
namespace debug_agent {
class DebuggedThread;
namespace arch {
extern const BreakInstructionType kBreakInstruction;
// Class in charge of abstracting the low-level functionalities of the platform.
// This permits a virtual interface for your testing convenience.
class ArchProvider {
public:
ArchProvider() = default;
virtual ~ArchProvider() = default;
::debug_ipc::Arch GetArch();
uint32_t hw_breakpoint_count() const { return hw_breakpoint_count_; }
void set_hw_breakpoint_count(uint32_t count) { hw_breakpoint_count_ = count; }
uint32_t watchpoint_count() const { return watchpoint_count_; }
void set_watchpoint_count(uint32_t count) { watchpoint_count_ = count; }
// Thread Management -----------------------------------------------------------------------------
// Read/write debug registers.
virtual zx_status_t ReadDebugState(const zx::thread& handle,
zx_thread_state_debug_regs* regs) const = 0;
virtual zx_status_t WriteDebugState(const zx::thread& handle,
const zx_thread_state_debug_regs& regs) = 0;
virtual zx_status_t WriteSingleStep(const zx::thread& thread, bool single_step) = 0;
// zx_object_get_info.
virtual zx_status_t GetInfo(const zx::thread&, zx_object_info_topic_t topic, void* buffer,
size_t buffer_size, size_t* actual = nullptr,
size_t* avail = nullptr) const = 0;
// General Exceptions ----------------------------------------------------------------------------
// Converts a system exception info to an IPC exception record.
virtual void FillExceptionRecord(const zx::thread&, debug_ipc::ExceptionRecord* out) const = 0;
// Software Exceptions ---------------------------------------------------------------------------
// Returns the address of the breakpoint instruction given the address of
// a software breakpoint exception.
virtual uint64_t BreakpointInstructionForSoftwareExceptionAddress(uint64_t exception_addr);
// Returns the instruction following the one causing the given software
// exception.
uint64_t NextInstructionForSoftwareExceptionAddress(uint64_t exception_addr);
uint64_t NextInstructionForWatchpointHit(uint64_t exception_addr);
// Address of the instruction that caused the watchpoint exception. Also returns the slot (which
// register triggered it).
//
// Returns {0, -1} on error or not found.
virtual std::pair<debug_ipc::AddressRange, int> InstructionForWatchpointHit(
const DebuggedThread&) const;
// Returns true if there is a breakpoint instruction at the given address.
// This doesn't just check equality of kBreakInstruction which is guaranteed
// to be used for our breakpoints, but also checks other encodings that may
// have been written into the program.
virtual bool IsBreakpointInstruction(zx::process& process, uint64_t address);
// Converts the given register structure to a vector of debug_ipc registers.
static void SaveGeneralRegs(const zx_thread_state_general_regs& input,
std::vector<debug_ipc::Register>* out);
// The registers in the given category are appended to the given output vector.
virtual zx_status_t ReadRegisters(const debug_ipc::RegisterCategory& cat, const zx::thread&,
std::vector<debug_ipc::Register>* out);
// The registers must all be in the same category.
virtual zx_status_t WriteRegisters(const debug_ipc::RegisterCategory&,
const std::vector<debug_ipc::Register>& registers,
zx::thread*);
// Hardware Exceptions ---------------------------------------------------------------------------
// Returns the address of the instruction that hit the exception from the
// address reported by the exception.
uint64_t BreakpointInstructionForHardwareExceptionAddress(uint64_t exception_addr);
// Currently HW notifications can mean both a single step or a hardware debug
// register exception. We need platform-specific queries to figure which one
// is it.
virtual debug_ipc::ExceptionType DecodeExceptionType(const DebuggedThread&,
uint32_t exception_type);
protected:
uint32_t hw_breakpoint_count_ = 0;
uint32_t watchpoint_count_ = 0;
};
} // namespace arch
} // namespace debug_agent
#endif // SRC_DEVELOPER_DEBUG_DEBUG_AGENT_ARCH_H_