blob: 079c51f681a905297ea5438e537b5608931e909d [file] [log] [blame]
// Copyright 2016 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.
#pragma once
#include <memory>
#include <string>
#include <src/lib/fxl/macros.h>
#include <src/lib/fxl/strings/string_view.h>
#include <zircon/syscalls/debug.h>
#include <zircon/syscalls/exception.h>
#include <zircon/types.h>
namespace inferior_control {
class Thread;
// Registers represents an architecture-dependent general register set.
// This is an abstract, opaque interface that returns a register-value
// representation that complies with the GDB Remote Protocol with
// architecture-specific implementations.
class Registers {
public:
// Factory method for obtaining a Registers instance on the current
// architecture for a particular thread |thread|.
static std::unique_ptr<Registers> Create(Thread* thread);
virtual ~Registers() = default;
// Loads and caches register values for |regset|.
// Returns false if there is an error.
bool RefreshRegset(int regset);
// Write the cached register set |regset| values back.
// Returns false if there is an error.
bool WriteRegset(int regset);
// Wrappers for general regs (regset0).
bool RefreshGeneralRegisters();
bool WriteGeneralRegisters();
// Fetch the general registers.
// The returned pointer is valid until the thread is resumed or killed.
// |RefreshGeneralRegisters()| must have already been called.
zx_thread_state_general_regs_t* GetGeneralRegisters();
// Get the value of register |regno| from the cached set
// and store in |buffer|.
// RefreshRegset() of the appropriate regset must be called first.
// Returns a boolean indicating success.
// TODO(dje): This method is deprecated.
virtual bool GetRegister(int regno, void* buffer, size_t buf_size) = 0;
// Sets the value of the register numbered |regno| to |value| of
// size |value_size| bytes. Returns false if |regno| or
// |value_size| are invalid on the current architecture.
// WriteRegset() of the appropriate regset must be called afterwards.
// TODO(dje): This method is deprecated.
virtual bool SetRegister(int regno, const void* value, size_t value_size) = 0;
// Accessors for frequently accessed registers.
// RefreshGeneralRegisters() must be called first.
virtual zx_vaddr_t GetPC() = 0;
virtual zx_vaddr_t GetSP() = 0;
virtual zx_vaddr_t GetFP() = 0;
// Stepping over s/w breakpoint instructions requires setting PC.
// RefreshGeneralRegisters() must be called first.
virtual void SetPC(zx_vaddr_t pc) = 0;
// Set the h/w singlestepping register.
virtual bool SetSingleStep(bool enable) = 0;
// Return a formatted display of |regset|.
// RefreshRegset() of the appropriate regset must be called first.
virtual std::string GetFormattedRegset(int regset) = 0;
protected:
Registers(Thread* thread);
Thread* thread() const { return thread_; }
// Loads and caches register values for |regset|.
// Returns false if there is an error.
bool RefreshRegsetHelper(int regset, void* buf, size_t buf_size);
// Write the cached register set |regset| values back.
// Returns false if there is an error.
bool WriteRegsetHelper(int regset, const void* buf, size_t buf_size);
// The general registers are generally always required, so allocate space
// for them here.
zx_thread_state_general_regs_t general_regs_ = {};
private:
Thread* thread_; // non-owning
FXL_DISALLOW_COPY_AND_ASSIGN(Registers);
};
} // namespace inferior_control