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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef lldb_NativeRegisterContextLinux_h 10 #define lldb_NativeRegisterContextLinux_h 11 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 18 namespace lldb_private { 19 namespace process_linux { 20 21 class NativeThreadLinux; 22 23 class NativeRegisterContextLinux 24 : public virtual NativeRegisterContextRegisterInfo { 25 public: 26 // These static methods are implemented individual 27 // NativeRegisterContextLinux_* subclasses. The implementations can't collide 28 // as only one NativeRegisterContextLinux_* variant should be compiled into 29 // the final executable. 30 31 // Return a NativeRegisterContextLinux instance suitable for debugging the 32 // 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 structures InvalidateAllRegisters()41 virtual void InvalidateAllRegisters(){} 42 43 struct SyscallData { 44 /// The syscall instruction. If the architecture uses software 45 /// single-stepping, the instruction should also be followed by a trap to 46 /// 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 to 50 /// 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, if 56 /// they are supported. GetSyscallData()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 the 61 // relevant architecture. 62 unsigned SysMmap; ///< mmap syscall number. 63 unsigned SysMunmap; ///< munmap syscall number 64 }; 65 /// Return the architecture-specific data needed to make mmap syscalls, if 66 /// they are supported. GetMmapData()67 virtual std::optional<MmapData> GetMmapData() { return std::nullopt; } 68 69 struct MemoryTaggingDetails { 70 /// Object with tag handling utilities. If the function below returns 71 /// 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 read 74 int ptrace_write_req; /// ptrace operation number for memory tag write 75 }; 76 /// Return architecture specific data needed to use memory tags, 77 /// if they are supported. 78 virtual llvm::Expected<MemoryTaggingDetails> GetMemoryTaggingDetails(int32_t type)79 GetMemoryTaggingDetails(int32_t type) { 80 return llvm::createStringError( 81 llvm::inconvertibleErrorCode(), 82 "Architecture does not support memory tagging"); 83 } 84 85 protected: 86 // NB: This constructor is here only because gcc<=6.5 requires a virtual base 87 // class initializer on abstract class (even though it is never used). It can 88 // be deleted once we move to gcc>=7.0. NativeRegisterContextLinux(NativeThreadProtocol & thread)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 GetGPRSize()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 GetPtraceOffset(uint32_t reg_index)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 perform 128 // ptrace 129 // 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 by 137 // PTRACE_GETREGSET(NT_PRSTATUS). 138 static llvm::Expected<ArchSpec> 139 DetermineArchitectureViaGPR(lldb::tid_t tid, size_t gpr64_size); 140 }; 141 142 } // namespace process_linux 143 } // namespace lldb_private 144 145 #endif // #ifndef lldb_NativeRegisterContextLinux_h 146