1 //===-- RegisterContextDarwin_arm64.h -----------------------------*- C++
2 //-*-===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 
11 #ifndef liblldb_RegisterContextDarwin_arm64_h_
12 #define liblldb_RegisterContextDarwin_arm64_h_
13 
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Target/RegisterContext.h"
19 #include "lldb/lldb-private.h"
20 
21 // Break only in privileged or user mode
22 #define S_RSVD ((uint32_t)(0u << 1))
23 #define S_PRIV ((uint32_t)(1u << 1))
24 #define S_USER ((uint32_t)(2u << 1))
25 #define S_PRIV_USER ((S_PRIV) | (S_USER))
26 
27 #define WCR_ENABLE ((uint32_t)(1u))
28 
29 // Watchpoint load/store
30 #define WCR_LOAD ((uint32_t)(1u << 3))
31 #define WCR_STORE ((uint32_t)(1u << 4))
32 
33 class RegisterContextDarwin_arm64 : public lldb_private::RegisterContext {
34 public:
35   RegisterContextDarwin_arm64(lldb_private::Thread &thread,
36                               uint32_t concrete_frame_idx);
37 
38   ~RegisterContextDarwin_arm64() override;
39 
40   void InvalidateAllRegisters() override;
41 
42   size_t GetRegisterCount() override;
43 
44   const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
45 
46   size_t GetRegisterSetCount() override;
47 
48   const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;
49 
50   bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
51                     lldb_private::RegisterValue &reg_value) override;
52 
53   bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
54                      const lldb_private::RegisterValue &reg_value) override;
55 
56   bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
57 
58   bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
59 
60   uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
61                                                uint32_t num) override;
62 
63   uint32_t NumSupportedHardwareWatchpoints() override;
64 
65   uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
66                                  bool write) override;
67 
68   bool ClearHardwareWatchpoint(uint32_t hw_index) override;
69 
70   // mirrors <mach/arm/thread_status.h> arm_thread_state64_t
71   struct GPR {
72     uint64_t x[29]; // x0-x28
73     uint64_t fp;    // x29
74     uint64_t lr;    // x30
75     uint64_t sp;    // x31
76     uint64_t pc;    // pc
77     uint32_t cpsr;  // cpsr
78   };
79 
80   struct VReg {
81     uint8_t bytes[16];
82   };
83 
84   // mirrors <mach/arm/thread_status.h> arm_neon_state64_t
85   struct FPU {
86     VReg v[32];
87     uint32_t fpsr;
88     uint32_t fpcr;
89   };
90 
91   // mirrors <mach/arm/thread_status.h> arm_exception_state64_t
92   struct EXC {
93     uint64_t far;       // Virtual Fault Address
94     uint32_t esr;       // Exception syndrome
95     uint32_t exception; // number of arm exception token
96   };
97 
98   // mirrors <mach/arm/thread_status.h> arm_debug_state64_t
99   struct DBG {
100     uint64_t bvr[16];
101     uint64_t bcr[16];
102     uint64_t wvr[16];
103     uint64_t wcr[16];
104     uint64_t mdscr_el1;
105   };
106 
107   static void LogDBGRegisters(lldb_private::Log *log, const DBG &dbg);
108 
109 protected:
110   enum {
111     GPRRegSet = 6,  // ARM_THREAD_STATE64
112     FPURegSet = 17, // ARM_NEON_STATE64
113     EXCRegSet = 7,  // ARM_EXCEPTION_STATE64
114     DBGRegSet = 15  // ARM_DEBUG_STATE64
115   };
116 
117   enum {
118     GPRWordCount = sizeof(GPR) / sizeof(uint32_t), // ARM_THREAD_STATE64_COUNT
119     FPUWordCount = sizeof(FPU) / sizeof(uint32_t), // ARM_NEON_STATE64_COUNT
120     EXCWordCount =
121         sizeof(EXC) / sizeof(uint32_t),           // ARM_EXCEPTION_STATE64_COUNT
122     DBGWordCount = sizeof(DBG) / sizeof(uint32_t) // ARM_DEBUG_STATE64_COUNT
123   };
124 
125   enum { Read = 0, Write = 1, kNumErrors = 2 };
126 
127   GPR gpr;
128   FPU fpu;
129   EXC exc;
130   DBG dbg;
131   int gpr_errs[2]; // Read/Write errors
132   int fpu_errs[2]; // Read/Write errors
133   int exc_errs[2]; // Read/Write errors
134   int dbg_errs[2]; // Read/Write errors
135 
136   void InvalidateAllRegisterStates() {
137     SetError(GPRRegSet, Read, -1);
138     SetError(FPURegSet, Read, -1);
139     SetError(EXCRegSet, Read, -1);
140   }
141 
142   int GetError(int flavor, uint32_t err_idx) const {
143     if (err_idx < kNumErrors) {
144       switch (flavor) {
145       // When getting all errors, just OR all values together to see if
146       // we got any kind of error.
147       case GPRRegSet:
148         return gpr_errs[err_idx];
149       case FPURegSet:
150         return fpu_errs[err_idx];
151       case EXCRegSet:
152         return exc_errs[err_idx];
153       case DBGRegSet:
154         return dbg_errs[err_idx];
155       default:
156         break;
157       }
158     }
159     return -1;
160   }
161 
162   bool SetError(int flavor, uint32_t err_idx, int err) {
163     if (err_idx < kNumErrors) {
164       switch (flavor) {
165       case GPRRegSet:
166         gpr_errs[err_idx] = err;
167         return true;
168 
169       case FPURegSet:
170         fpu_errs[err_idx] = err;
171         return true;
172 
173       case EXCRegSet:
174         exc_errs[err_idx] = err;
175         return true;
176 
177       case DBGRegSet:
178         exc_errs[err_idx] = err;
179         return true;
180 
181       default:
182         break;
183       }
184     }
185     return false;
186   }
187 
188   bool RegisterSetIsCached(int set) const { return GetError(set, Read) == 0; }
189 
190   int ReadGPR(bool force);
191 
192   int ReadFPU(bool force);
193 
194   int ReadEXC(bool force);
195 
196   int ReadDBG(bool force);
197 
198   int WriteGPR();
199 
200   int WriteFPU();
201 
202   int WriteEXC();
203 
204   int WriteDBG();
205 
206   // Subclasses override these to do the actual reading.
207   virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) { return -1; }
208 
209   virtual int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) = 0;
210 
211   virtual int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) = 0;
212 
213   virtual int DoReadDBG(lldb::tid_t tid, int flavor, DBG &dbg) = 0;
214 
215   virtual int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
216 
217   virtual int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
218 
219   virtual int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) = 0;
220 
221   virtual int DoWriteDBG(lldb::tid_t tid, int flavor, const DBG &dbg) = 0;
222 
223   int ReadRegisterSet(uint32_t set, bool force);
224 
225   int WriteRegisterSet(uint32_t set);
226 
227   static uint32_t GetRegisterNumber(uint32_t reg_kind, uint32_t reg_num);
228 
229   static int GetSetForNativeRegNum(int reg_num);
230 
231   static size_t GetRegisterInfosCount();
232 
233   static const lldb_private::RegisterInfo *GetRegisterInfos();
234 };
235 
236 #endif // liblldb_RegisterContextDarwin_arm64_h_
237