146 lines · c
1//===-- NativeRegisterContextLinux.h ----------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef lldb_NativeRegisterContextLinux_h10#define lldb_NativeRegisterContextLinux_h11 12#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"13#include "lldb/Host/common/NativeThreadProtocol.h"14#include "lldb/Target/MemoryTagManager.h"15#include "llvm/Support/Error.h"16#include <optional>17 18namespace lldb_private {19namespace process_linux {20 21class NativeThreadLinux;22 23class NativeRegisterContextLinux24 : public virtual NativeRegisterContextRegisterInfo {25public:26 // These static methods are implemented individual27 // NativeRegisterContextLinux_* subclasses. The implementations can't collide28 // as only one NativeRegisterContextLinux_* variant should be compiled into29 // the final executable.30 31 // Return a NativeRegisterContextLinux instance suitable for debugging the32 // given thread.33 static std::unique_ptr<NativeRegisterContextLinux>34 CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch,35 NativeThreadLinux &native_thread);36 37 // Determine the architecture of the thread given by its ID.38 static llvm::Expected<ArchSpec> DetermineArchitecture(lldb::tid_t tid);39 40 // Invalidates cached values in register context data structures41 virtual void InvalidateAllRegisters(){}42 43 struct SyscallData {44 /// The syscall instruction. If the architecture uses software45 /// single-stepping, the instruction should also be followed by a trap to46 /// ensure the process is stopped after the syscall.47 llvm::ArrayRef<uint8_t> Insn;48 49 /// Registers used for syscall arguments. The first register is used to50 /// store the syscall number.51 llvm::ArrayRef<uint32_t> Args;52 53 uint32_t Result; ///< Register containing the syscall result.54 };55 /// Return architecture-specific data needed to make inferior syscalls, if56 /// they are supported.57 virtual std::optional<SyscallData> GetSyscallData() { return std::nullopt; }58 59 struct MmapData {60 // Syscall numbers can be found (e.g.) in /usr/include/asm/unistd.h for the61 // relevant architecture.62 unsigned SysMmap; ///< mmap syscall number.63 unsigned SysMunmap; ///< munmap syscall number64 };65 /// Return the architecture-specific data needed to make mmap syscalls, if66 /// they are supported.67 virtual std::optional<MmapData> GetMmapData() { return std::nullopt; }68 69 struct MemoryTaggingDetails {70 /// Object with tag handling utilities. If the function below returns71 /// a valid structure, you can assume that this pointer is valid.72 std::unique_ptr<MemoryTagManager> manager;73 int ptrace_read_req; /// ptrace operation number for memory tag read74 int ptrace_write_req; /// ptrace operation number for memory tag write75 };76 /// Return architecture specific data needed to use memory tags,77 /// if they are supported.78 virtual llvm::Expected<MemoryTaggingDetails>79 GetMemoryTaggingDetails(int32_t type) {80 return llvm::createStringError(81 llvm::inconvertibleErrorCode(),82 "Architecture does not support memory tagging");83 }84 85protected:86 // NB: This constructor is here only because gcc<=6.5 requires a virtual base87 // class initializer on abstract class (even though it is never used). It can88 // be deleted once we move to gcc>=7.0.89 NativeRegisterContextLinux(NativeThreadProtocol &thread)90 : NativeRegisterContextRegisterInfo(thread, nullptr) {}91 92 lldb::ByteOrder GetByteOrder() const;93 94 virtual Status ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value);95 96 virtual Status WriteRegisterRaw(uint32_t reg_index,97 const RegisterValue ®_value);98 99 virtual Status ReadRegisterSet(void *buf, size_t buf_size,100 unsigned int regset);101 102 virtual Status WriteRegisterSet(void *buf, size_t buf_size,103 unsigned int regset);104 105 virtual Status ReadGPR();106 107 virtual Status WriteGPR();108 109 virtual Status ReadFPR();110 111 virtual Status WriteFPR();112 113 virtual void *GetGPRBuffer() = 0;114 115 virtual size_t GetGPRSize() const {116 return GetRegisterInfoInterface().GetGPRSize();117 }118 119 virtual void *GetFPRBuffer() = 0;120 121 virtual size_t GetFPRSize() = 0;122 123 virtual uint32_t GetPtraceOffset(uint32_t reg_index) {124 return GetRegisterInfoAtIndex(reg_index)->byte_offset;125 }126 127 // The Do*** functions are executed on the privileged thread and can perform128 // ptrace129 // operations directly.130 virtual Status DoReadRegisterValue(uint32_t offset, const char *reg_name,131 uint32_t size, RegisterValue &value);132 133 virtual Status DoWriteRegisterValue(uint32_t offset, const char *reg_name,134 const RegisterValue &value);135 136 // Determine the architecture via GPR size, as reported by137 // PTRACE_GETREGSET(NT_PRSTATUS).138 static llvm::Expected<ArchSpec>139 DetermineArchitectureViaGPR(lldb::tid_t tid, size_t gpr64_size);140};141 142} // namespace process_linux143} // namespace lldb_private144 145#endif // #ifndef lldb_NativeRegisterContextLinux_h146