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 
17 namespace lldb_private {
18 namespace process_linux {
19 
20 class NativeThreadLinux;
21 
22 class NativeRegisterContextLinux
23     : public virtual NativeRegisterContextRegisterInfo {
24 public:
25   // This function is implemented in the NativeRegisterContextLinux_* subclasses
26   // to create a new instance of the host specific NativeRegisterContextLinux.
27   // The implementations can't collide as only one NativeRegisterContextLinux_*
28   // variant should be compiled into the final executable.
29   static std::unique_ptr<NativeRegisterContextLinux>
30   CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch,
31                                        NativeThreadLinux &native_thread);
32 
33   // Invalidates cached values in register context data structures
34   virtual void InvalidateAllRegisters(){}
35 
36   struct SyscallData {
37     /// The syscall instruction. If the architecture uses software
38     /// single-stepping, the instruction should also be followed by a trap to
39     /// ensure the process is stopped after the syscall.
40     llvm::ArrayRef<uint8_t> Insn;
41 
42     /// Registers used for syscall arguments. The first register is used to
43     /// store the syscall number.
44     llvm::ArrayRef<uint32_t> Args;
45 
46     uint32_t Result; ///< Register containing the syscall result.
47   };
48   /// Return architecture-specific data needed to make inferior syscalls, if
49   /// they are supported.
50   virtual llvm::Optional<SyscallData> GetSyscallData() { return llvm::None; }
51 
52   struct MmapData {
53     // Syscall numbers can be found (e.g.) in /usr/include/asm/unistd.h for the
54     // relevant architecture.
55     unsigned SysMmap;   ///< mmap syscall number.
56     unsigned SysMunmap; ///< munmap syscall number
57   };
58   /// Return the architecture-specific data needed to make mmap syscalls, if
59   /// they are supported.
60   virtual llvm::Optional<MmapData> GetMmapData() { return llvm::None; }
61 
62   struct MemoryTaggingDetails {
63     /// Object with tag handling utilities. If the function below returns
64     /// a valid structure, you can assume that this pointer is valid.
65     std::unique_ptr<MemoryTagManager> manager;
66     int ptrace_read_req;  /// ptrace operation number for memory tag read
67     int ptrace_write_req; /// ptrace operation number for memory tag write
68   };
69   /// Return architecture specific data needed to use memory tags,
70   /// if they are supported.
71   virtual llvm::Expected<MemoryTaggingDetails>
72   GetMemoryTaggingDetails(int32_t type) {
73     return llvm::createStringError(
74         llvm::inconvertibleErrorCode(),
75         "Architecture does not support memory tagging");
76   }
77 
78 protected:
79   // NB: This constructor is here only because gcc<=6.5 requires a virtual base
80   // class initializer on abstract class (even though it is never used). It can
81   // be deleted once we move to gcc>=7.0.
82   NativeRegisterContextLinux(NativeThreadProtocol &thread)
83       : NativeRegisterContextRegisterInfo(thread, nullptr) {}
84 
85   lldb::ByteOrder GetByteOrder() const;
86 
87   virtual Status ReadRegisterRaw(uint32_t reg_index, RegisterValue &reg_value);
88 
89   virtual Status WriteRegisterRaw(uint32_t reg_index,
90                                   const RegisterValue &reg_value);
91 
92   virtual Status ReadRegisterSet(void *buf, size_t buf_size,
93                                  unsigned int regset);
94 
95   virtual Status WriteRegisterSet(void *buf, size_t buf_size,
96                                   unsigned int regset);
97 
98   virtual Status ReadGPR();
99 
100   virtual Status WriteGPR();
101 
102   virtual Status ReadFPR();
103 
104   virtual Status WriteFPR();
105 
106   virtual void *GetGPRBuffer() = 0;
107 
108   virtual size_t GetGPRSize() const {
109     return GetRegisterInfoInterface().GetGPRSize();
110   }
111 
112   virtual void *GetFPRBuffer() = 0;
113 
114   virtual size_t GetFPRSize() = 0;
115 
116   virtual uint32_t GetPtraceOffset(uint32_t reg_index) {
117     return GetRegisterInfoAtIndex(reg_index)->byte_offset;
118   }
119 
120   // The Do*** functions are executed on the privileged thread and can perform
121   // ptrace
122   // operations directly.
123   virtual Status DoReadRegisterValue(uint32_t offset, const char *reg_name,
124                                      uint32_t size, RegisterValue &value);
125 
126   virtual Status DoWriteRegisterValue(uint32_t offset, const char *reg_name,
127                                       const RegisterValue &value);
128 };
129 
130 } // namespace process_linux
131 } // namespace lldb_private
132 
133 #endif // #ifndef lldb_NativeRegisterContextLinux_h
134