| // 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 <zircon/syscalls/exception.h> |
| #include <zircon/types.h> |
| |
| #include "lib/fxl/macros.h" |
| #include "lib/fxl/strings/string_view.h" |
| |
| namespace inferior_control { |
| |
| class Thread; |
| |
| // Returns the register number for the "Program Counter Register" on the current |
| // platform. Returns -1, if this operation is not supported. |
| int GetPCRegisterNumber(); |
| |
| // Returns the register number for the "Frame Pointer Register" on the current |
| // platform. Returns -1, if this operation is not supported. |
| int GetFPRegisterNumber(); |
| |
| // Returns the register number for the "Stack Pointer Register" on the current |
| // platform. Returns -1, if this operation is not supported. |
| int GetSPRegisterNumber(); |
| |
| // 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; |
| |
| // Returns true if reading the general register set on the current |
| // architecture is supported. |
| virtual bool IsSupported() = 0; |
| |
| // Loads and caches register values for |regset|. |
| // Returns false if there is an error. |
| virtual bool RefreshRegset(int regset) = 0; |
| |
| // Write the cached register set |regset| values back. |
| // Returns false if there is an error. |
| virtual bool WriteRegset(int regset) = 0; |
| |
| // Wrappers for general regs (regset0). |
| bool RefreshGeneralRegisters(); |
| bool WriteGeneralRegisters(); |
| std::string GetGeneralRegistersAsString(); |
| bool SetGeneralRegistersFromString(const fxl::StringView& value); |
| |
| // TODO(armansito): The Get/Set AsString/FromString methods work with |
| // strings that conform to the GDB remote serial protocol. We should change |
| // this so that this class is agnostic to the protocol and isolate such |
| // parsing to the CommandHandler/Server. This way we can separate the back |
| // end bits into a stand-alone library that we can use in gdb/lldb ports. |
| |
| // Returns a string containing sequentially encoded hexadecimal values of all |
| // registers in |regset|. For example, on an architecture with 4 registers of |
| // 4 bytes each, this would return the following value: |
| // |
| // WWWWWWWWXXXXXXXXYYYYYYYYZZZZZZZZ |
| // |
| // RefreshRegset() must be called first. |
| // Returns an empty string if there is an error while reading the registers. |
| virtual std::string GetRegsetAsString(int regset) = 0; |
| |
| // Writes |value| to the cached value of |regset|. |
| // |value| should be encoded the same way as the return value of |
| // GetRegsetAsString(), as described above. |
| // WriteRegset() must be called afterwards. |
| // Returns true on success. |
| virtual bool SetRegsetFromString(int regset, |
| const fxl::StringView& value) = 0; |
| |
| // Gets the value of the register numbered |regno|. Returns an empty |
| // string in case of an error or if |regno| is invalid. This avoids |
| // making a syscall to refresh all register values and uses the most recently |
| // cached values instead. Call RefreshRegisterValues() first to get the most |
| // up-to-date values. |
| virtual std::string GetRegisterAsString(int regno) = 0; |
| |
| // 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. |
| 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. |
| virtual bool SetRegister(int regno, const void* value, size_t value_size) = 0; |
| |
| // Get the value of the PC. |
| // RefreshGeneralRegisters() must be called first. |
| zx_vaddr_t GetPC(); |
| |
| // Get the value of the SP. |
| // RefreshGeneralRegisters() must be called first. |
| zx_vaddr_t GetSP(); |
| |
| // Get the value of the FP. |
| // RefreshGeneralRegisters() must be called first. |
| zx_vaddr_t GetFP(); |
| |
| // 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; |
| |
| // Returns a string containing all 0s. This is used in our implementation to |
| // return register values when there is a current inferior but no current |
| // thread. |
| // TODO(armansito): This is because we don't quite have a "stopped state" yet. |
| // With the existing Zircon syscall surface, a process is either "started" or |
| // "not started". |
| static std::string GetUninitializedGeneralRegistersAsString(); |
| |
| // Returns how many bytes each register value can hold. Returns 0 on |
| // unsupported platforms. |
| static size_t GetRegisterSize(); |
| |
| 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); |
| |
| // Fill a regset buffer from its string representation. |
| // This does not write the values to the cpu. |
| // N.B. This helper assumes there is no padding in the regset buffer. |
| bool SetRegsetFromStringHelper(int regset, void* buffer, size_t buf_size, |
| const fxl::StringView& value); |
| |
| private: |
| Thread* thread_; // weak |
| |
| // Helper function for GetPC,GetSP,GetFP. |
| zx_vaddr_t GetIntRegister(int regno); |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(Registers); |
| }; |
| |
| } // namespace inferior_control |