1 //===-- DNBArchImplARM64.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_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H 10 #define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H 11 12 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) 13 14 #include <mach/thread_status.h> 15 #include <map> 16 17 #if defined(ARM_THREAD_STATE64_COUNT) 18 19 #include "DNBArch.h" 20 21 class MachThread; 22 23 class DNBArchMachARM64 : public DNBArchProtocol { 24 public: 25 enum { kMaxNumThumbITBreakpoints = 4 }; 26 DNBArchMachARM64(MachThread * thread)27 DNBArchMachARM64(MachThread *thread) 28 : m_thread(thread), m_state(), m_disabled_watchpoints(), 29 m_disabled_breakpoints(), m_watchpoint_hw_index(-1), 30 m_watchpoint_did_occur(false), 31 m_watchpoint_resume_single_step_enabled(false), 32 m_saved_register_states() { 33 m_disabled_watchpoints.resize(16); 34 m_disabled_breakpoints.resize(16); 35 memset(&m_dbg_save, 0, sizeof(m_dbg_save)); 36 } 37 ~DNBArchMachARM64()38 virtual ~DNBArchMachARM64() {} 39 40 static void Initialize(); 41 static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); 42 43 virtual bool GetRegisterValue(uint32_t set, uint32_t reg, 44 DNBRegisterValue *value); 45 virtual bool SetRegisterValue(uint32_t set, uint32_t reg, 46 const DNBRegisterValue *value); 47 virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); 48 virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); 49 virtual uint32_t SaveRegisterState(); 50 virtual bool RestoreRegisterState(uint32_t save_id); 51 52 virtual kern_return_t GetRegisterState(int set, bool force); 53 virtual kern_return_t SetRegisterState(int set); 54 virtual bool RegisterSetStateIsValid(int set) const; 55 56 virtual uint64_t GetPC(uint64_t failValue); // Get program counter 57 virtual kern_return_t SetPC(uint64_t value); 58 virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer 59 virtual void ThreadWillResume(); 60 virtual bool ThreadDidStop(); 61 virtual bool NotifyException(MachException::Data &exc); 62 63 static DNBArchProtocol *Create(MachThread *thread); 64 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); 65 static uint32_t GetCPUType(); 66 67 virtual uint32_t NumSupportedHardwareBreakpoints(); 68 virtual uint32_t NumSupportedHardwareWatchpoints(); 69 70 virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size, 71 bool also_set_on_task); 72 virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index, 73 bool also_set_on_task); 74 virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, 75 bool read, bool write, 76 bool also_set_on_task); 77 virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, 78 bool also_set_on_task); 79 virtual bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index, 80 bool also_set_on_task); 81 82 protected: 83 kern_return_t EnableHardwareSingleStep(bool enable); 84 static bool FixGenericRegisterNumber(uint32_t &set, uint32_t ®); 85 86 enum RegisterSet { 87 e_regSetALL = REGISTER_SET_ALL, 88 e_regSetGPR, // ARM_THREAD_STATE64, 89 e_regSetVFP, // ARM_NEON_STATE64, 90 e_regSetEXC, // ARM_EXCEPTION_STATE64, 91 e_regSetDBG, // ARM_DEBUG_STATE64, 92 kNumRegisterSets 93 }; 94 95 enum { 96 e_regSetGPRCount = ARM_THREAD_STATE64_COUNT, 97 e_regSetVFPCount = ARM_NEON_STATE64_COUNT, 98 e_regSetEXCCount = ARM_EXCEPTION_STATE64_COUNT, 99 e_regSetDBGCount = ARM_DEBUG_STATE64_COUNT, 100 }; 101 102 enum { Read = 0, Write = 1, kNumErrors = 2 }; 103 104 typedef arm_thread_state64_t GPR; 105 typedef arm_neon_state64_t FPU; 106 typedef arm_exception_state64_t EXC; 107 108 static const DNBRegisterInfo g_gpr_registers[]; 109 static const DNBRegisterInfo g_vfp_registers[]; 110 static const DNBRegisterInfo g_exc_registers[]; 111 static const DNBRegisterSetInfo g_reg_sets[]; 112 113 static const size_t k_num_gpr_registers; 114 static const size_t k_num_vfp_registers; 115 static const size_t k_num_exc_registers; 116 static const size_t k_num_all_registers; 117 static const size_t k_num_register_sets; 118 119 struct Context { 120 GPR gpr; 121 FPU vfp; 122 EXC exc; 123 }; 124 125 struct State { 126 Context context; 127 arm_debug_state64_t dbg; 128 kern_return_t gpr_errs[2]; // Read/Write errors 129 kern_return_t vfp_errs[2]; // Read/Write errors 130 kern_return_t exc_errs[2]; // Read/Write errors 131 kern_return_t dbg_errs[2]; // Read/Write errors StateState132 State() { 133 uint32_t i; 134 for (i = 0; i < kNumErrors; i++) { 135 gpr_errs[i] = -1; 136 vfp_errs[i] = -1; 137 exc_errs[i] = -1; 138 dbg_errs[i] = -1; 139 } 140 } InvalidateRegisterSetStateState141 void InvalidateRegisterSetState(int set) { SetError(set, Read, -1); } 142 InvalidateAllRegisterStatesState143 void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } 144 GetErrorState145 kern_return_t GetError(int set, uint32_t err_idx) const { 146 if (err_idx < kNumErrors) { 147 switch (set) { 148 // When getting all errors, just OR all values together to see if 149 // we got any kind of error. 150 case e_regSetALL: 151 return gpr_errs[err_idx] | vfp_errs[err_idx] | exc_errs[err_idx] | 152 dbg_errs[err_idx]; 153 case e_regSetGPR: 154 return gpr_errs[err_idx]; 155 case e_regSetVFP: 156 return vfp_errs[err_idx]; 157 case e_regSetEXC: 158 return exc_errs[err_idx]; 159 // case e_regSetDBG: return dbg_errs[err_idx]; 160 default: 161 break; 162 } 163 } 164 return -1; 165 } SetErrorState166 bool SetError(int set, uint32_t err_idx, kern_return_t err) { 167 if (err_idx < kNumErrors) { 168 switch (set) { 169 case e_regSetALL: 170 gpr_errs[err_idx] = err; 171 vfp_errs[err_idx] = err; 172 dbg_errs[err_idx] = err; 173 exc_errs[err_idx] = err; 174 return true; 175 176 case e_regSetGPR: 177 gpr_errs[err_idx] = err; 178 return true; 179 180 case e_regSetVFP: 181 vfp_errs[err_idx] = err; 182 return true; 183 184 case e_regSetEXC: 185 exc_errs[err_idx] = err; 186 return true; 187 188 // case e_regSetDBG: 189 // dbg_errs[err_idx] = err; 190 // return true; 191 default: 192 break; 193 } 194 } 195 return false; 196 } RegsAreValidState197 bool RegsAreValid(int set) const { 198 return GetError(set, Read) == KERN_SUCCESS; 199 } 200 }; 201 202 kern_return_t GetGPRState(bool force); 203 kern_return_t GetVFPState(bool force); 204 kern_return_t GetEXCState(bool force); 205 kern_return_t GetDBGState(bool force); 206 207 kern_return_t SetGPRState(); 208 kern_return_t SetVFPState(); 209 kern_return_t SetEXCState(); 210 kern_return_t SetDBGState(bool also_set_on_task); 211 212 // Helper functions for watchpoint implementaions. 213 214 typedef arm_debug_state64_t DBG; 215 216 void ClearWatchpointOccurred(); 217 bool HasWatchpointOccurred(); 218 bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index); 219 nub_addr_t GetWatchpointAddressByIndex(uint32_t hw_index); 220 nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); 221 virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index); 222 virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index); 223 virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); 224 225 class disabled_watchpoint { 226 public: disabled_watchpoint()227 disabled_watchpoint() { 228 addr = 0; 229 control = 0; 230 } 231 nub_addr_t addr; 232 uint32_t control; 233 }; 234 235 protected: 236 MachThread *m_thread; 237 State m_state; 238 arm_debug_state64_t m_dbg_save; 239 240 // arm64 doesn't keep the disabled watchpoint and breakpoint values in the 241 // debug register context like armv7; 242 // we need to save them aside when we disable them temporarily. 243 std::vector<disabled_watchpoint> m_disabled_watchpoints; 244 std::vector<disabled_watchpoint> m_disabled_breakpoints; 245 246 // The following member variables should be updated atomically. 247 int32_t m_watchpoint_hw_index; 248 bool m_watchpoint_did_occur; 249 bool m_watchpoint_resume_single_step_enabled; 250 251 typedef std::map<uint32_t, Context> SaveRegisterStates; 252 SaveRegisterStates m_saved_register_states; 253 }; 254 255 #endif // #if defined (ARM_THREAD_STATE64_COUNT) 256 #endif // #if defined (__arm__) 257 #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_ARM64_DNBARCHIMPLARM64_H 258