| // Copyright 2020 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_DEBUG_REGISTERS_H_ | |
| #define SRC_DEVELOPER_DEBUG_DEBUG_AGENT_DEBUG_REGISTERS_H_ | |
| #include <zircon/syscalls/debug.h> | |
| #include <optional> | |
| #include "src/developer/debug/debug_agent/watchpoint_info.h" | |
| #include "src/developer/debug/ipc/records.h" | |
| #include "src/developer/debug/shared/address_range.h" | |
| namespace debug_agent { | |
| // Wrapper around the debug thread registers to allow them to be accessed uniformly regardless | |
| // of the platform. | |
| class DebugRegisters { | |
| public: | |
| DebugRegisters() : regs_() {} | |
| explicit DebugRegisters(const zx_thread_state_debug_regs& r) : regs_(r) {} | |
| // Fills the given state the debug registers to what it should be if we added an execution HW | |
| // breakpoint for |address|. Return false if there are no registers left. | |
| bool SetHWBreakpoint(uint64_t address); | |
| // Removes an installed execution HW breakpoint for |address|. If the address is not installed, no | |
| // functional change will happen and false will be returned. | |
| bool RemoveHWBreakpoint(uint64_t address); | |
| // Update the debug registers to install the given watchpoint. The type must be a watchpoint type | |
| // (kWrite or kReadWrite). | |
| // | |
| // The watchpoint count should be the number of hardware watchpoints on the current system. It is | |
| // passed as a parameter here to allow this function to be tested under different conditions. | |
| // | |
| // The address has to be correctly aligned according to its length or an error will be returned. | |
| // The possible values for the size are: | |
| // | |
| // size = 1: 1 byte aligned address. | |
| // size = 2: 2 byte aligned address. | |
| // size = 4: 4 byte aligned address. | |
| // size = 8: 8 byte aligned address. | |
| // | |
| // Any other |size| values will return error. | |
| std::optional<WatchpointInfo> SetWatchpoint(debug_ipc::BreakpointType type, | |
| const debug::AddressRange& range, | |
| uint32_t watchpoint_count); | |
| // Updates the debug registers to remove an installed watchpoint for the given range. Returns | |
| // true on success, false if the range is not installed. | |
| bool RemoveWatchpoint(const debug::AddressRange& range, uint32_t watchpoint_count); | |
| // Decodes the debug registers given the state after a watchpoint exception has been thrown. | |
| std::optional<WatchpointInfo> DecodeHitWatchpoint() const; | |
| // Sets the debug registers to indicate a hit of the watchpoint of the given slot. This is used in | |
| // tests to set up calls for DecodeHitWatchpoint() to succeed. | |
| void SetForHitWatchpoint(int slot); | |
| std::string ToString() const; | |
| zx_thread_state_debug_regs& GetNativeRegisters() { return regs_; } | |
| const zx_thread_state_debug_regs& GetNativeRegisters() const { return regs_; } | |
| private: | |
| zx_thread_state_debug_regs regs_; | |
| }; | |
| } // namespace debug_agent | |
| #endif // SRC_DEVELOPER_DEBUG_DEBUG_AGENT_DEBUG_REGISTERS_H_ |