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 ®_value) override; 52 53 bool WriteRegister(const lldb_private::RegisterInfo *reg_info, 54 const lldb_private::RegisterValue ®_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