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