xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux.h (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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 &reg_value);
95 
96   virtual Status WriteRegisterRaw(uint32_t reg_index,
97                                   const RegisterValue &reg_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