1 //===-- DNBArchImpl.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 // Created by Greg Clayton on 6/25/07. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef __DebugNubArchMachARM_h__ 14 #define __DebugNubArchMachARM_h__ 15 16 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__) 17 18 #include "DNBArch.h" 19 20 #include <map> 21 22 class MachThread; 23 24 class DNBArchMachARM : public DNBArchProtocol { 25 public: 26 enum { kMaxNumThumbITBreakpoints = 4 }; 27 DNBArchMachARM(MachThread * thread)28 DNBArchMachARM(MachThread *thread) 29 : m_thread(thread), m_state(), m_disabled_watchpoints(), 30 m_hw_single_chained_step_addr(INVALID_NUB_ADDRESS), 31 m_last_decode_pc(INVALID_NUB_ADDRESS), m_watchpoint_hw_index(-1), 32 m_watchpoint_did_occur(false), 33 m_watchpoint_resume_single_step_enabled(false), 34 m_saved_register_states() { 35 m_disabled_watchpoints.resize(16); 36 memset(&m_dbg_save, 0, sizeof(m_dbg_save)); 37 #if defined(USE_ARM_DISASSEMBLER_FRAMEWORK) 38 ThumbStaticsInit(&m_last_decode_thumb); 39 #endif 40 } 41 ~DNBArchMachARM()42 virtual ~DNBArchMachARM() {} 43 44 static void Initialize(); 45 static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); 46 47 virtual bool GetRegisterValue(uint32_t set, uint32_t reg, 48 DNBRegisterValue *value); 49 virtual bool SetRegisterValue(uint32_t set, uint32_t reg, 50 const DNBRegisterValue *value); 51 virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); 52 virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); 53 virtual uint32_t SaveRegisterState(); 54 virtual bool RestoreRegisterState(uint32_t save_id); 55 56 virtual kern_return_t GetRegisterState(int set, bool force); 57 virtual kern_return_t SetRegisterState(int set); 58 virtual bool RegisterSetStateIsValid(int set) const; 59 60 virtual uint64_t GetPC(uint64_t failValue); // Get program counter 61 virtual kern_return_t SetPC(uint64_t value); 62 virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer 63 virtual void ThreadWillResume(); 64 virtual bool ThreadDidStop(); 65 virtual bool NotifyException(MachException::Data &exc); 66 67 static DNBArchProtocol *Create(MachThread *thread); 68 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); 69 static uint32_t GetCPUType(); 70 71 virtual uint32_t NumSupportedHardwareBreakpoints(); 72 virtual uint32_t NumSupportedHardwareWatchpoints(); 73 virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size); 74 virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index); 75 76 virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, 77 bool read, bool write, 78 bool also_set_on_task); 79 virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, 80 bool also_set_on_task); 81 virtual bool DisableHardwareWatchpoint_helper(uint32_t hw_break_index, 82 bool also_set_on_task); 83 virtual bool ReenableHardwareWatchpoint(uint32_t hw_break_index); 84 virtual bool ReenableHardwareWatchpoint_helper(uint32_t hw_break_index); 85 86 virtual bool StepNotComplete(); 87 virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); 88 89 #if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__)) 90 typedef arm_debug_state32_t DBG; 91 #else 92 typedef arm_debug_state_t DBG; 93 #endif 94 95 protected: 96 kern_return_t EnableHardwareSingleStep(bool enable); 97 kern_return_t SetSingleStepSoftwareBreakpoints(); 98 99 bool ConditionPassed(uint8_t condition, uint32_t cpsr); 100 #if defined(USE_ARM_DISASSEMBLER_FRAMEWORK) 101 bool ComputeNextPC(nub_addr_t currentPC, 102 arm_decoded_instruction_t decodedInstruction, 103 bool currentPCIsThumb, nub_addr_t *targetPC); 104 arm_error_t DecodeInstructionUsingDisassembler( 105 nub_addr_t curr_pc, uint32_t curr_cpsr, 106 arm_decoded_instruction_t *decodedInstruction, 107 thumb_static_data_t *thumbStaticData, nub_addr_t *next_pc); 108 void DecodeITBlockInstructions(nub_addr_t curr_pc); 109 #endif 110 void EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC, 111 uint32_t cpsr, 112 bool currentPCIsThumb, 113 nub_addr_t *nextPC, 114 bool *nextPCIsThumb); 115 116 enum RegisterSet { 117 e_regSetALL = REGISTER_SET_ALL, 118 e_regSetGPR, // ARM_THREAD_STATE 119 e_regSetVFP, // ARM_VFP_STATE (ARM_NEON_STATE if defined __arm64__) 120 e_regSetEXC, // ARM_EXCEPTION_STATE 121 e_regSetDBG, // ARM_DEBUG_STATE (ARM_DEBUG_STATE32 if defined __arm64__) 122 kNumRegisterSets 123 }; 124 125 enum { Read = 0, Write = 1, kNumErrors = 2 }; 126 127 typedef arm_thread_state_t GPR; 128 #if defined(__arm64__) || defined(__aarch64__) 129 typedef arm_neon_state_t FPU; 130 #else 131 typedef arm_vfp_state_t FPU; 132 #endif 133 typedef arm_exception_state_t EXC; 134 135 static const DNBRegisterInfo g_gpr_registers[]; 136 static const DNBRegisterInfo g_vfp_registers[]; 137 static const DNBRegisterInfo g_exc_registers[]; 138 static const DNBRegisterSetInfo g_reg_sets[]; 139 140 static const size_t k_num_gpr_registers; 141 static const size_t k_num_vfp_registers; 142 static const size_t k_num_exc_registers; 143 static const size_t k_num_all_registers; 144 static const size_t k_num_register_sets; 145 146 struct Context { 147 GPR gpr; 148 FPU vfp; 149 EXC exc; 150 }; 151 152 struct State { 153 Context context; 154 DBG dbg; 155 kern_return_t gpr_errs[2]; // Read/Write errors 156 kern_return_t vfp_errs[2]; // Read/Write errors 157 kern_return_t exc_errs[2]; // Read/Write errors 158 kern_return_t dbg_errs[2]; // Read/Write errors StateState159 State() { 160 uint32_t i; 161 for (i = 0; i < kNumErrors; i++) { 162 gpr_errs[i] = -1; 163 vfp_errs[i] = -1; 164 exc_errs[i] = -1; 165 dbg_errs[i] = -1; 166 } 167 } InvalidateRegisterSetStateState168 void InvalidateRegisterSetState(int set) { SetError(set, Read, -1); } GetErrorState169 kern_return_t GetError(int set, uint32_t err_idx) const { 170 if (err_idx < kNumErrors) { 171 switch (set) { 172 // When getting all errors, just OR all values together to see if 173 // we got any kind of error. 174 case e_regSetALL: 175 return gpr_errs[err_idx] | vfp_errs[err_idx] | exc_errs[err_idx] | 176 dbg_errs[err_idx]; 177 case e_regSetGPR: 178 return gpr_errs[err_idx]; 179 case e_regSetVFP: 180 return vfp_errs[err_idx]; 181 case e_regSetEXC: 182 return exc_errs[err_idx]; 183 case e_regSetDBG: 184 return dbg_errs[err_idx]; 185 default: 186 break; 187 } 188 } 189 return -1; 190 } SetErrorState191 bool SetError(int set, uint32_t err_idx, kern_return_t err) { 192 if (err_idx < kNumErrors) { 193 switch (set) { 194 case e_regSetALL: 195 gpr_errs[err_idx] = err; 196 vfp_errs[err_idx] = err; 197 dbg_errs[err_idx] = err; 198 exc_errs[err_idx] = err; 199 return true; 200 201 case e_regSetGPR: 202 gpr_errs[err_idx] = err; 203 return true; 204 205 case e_regSetVFP: 206 vfp_errs[err_idx] = err; 207 return true; 208 209 case e_regSetEXC: 210 exc_errs[err_idx] = err; 211 return true; 212 213 case e_regSetDBG: 214 dbg_errs[err_idx] = err; 215 return true; 216 default: 217 break; 218 } 219 } 220 return false; 221 } RegsAreValidState222 bool RegsAreValid(int set) const { 223 return GetError(set, Read) == KERN_SUCCESS; 224 } 225 }; 226 227 kern_return_t GetGPRState(bool force); 228 kern_return_t GetVFPState(bool force); 229 kern_return_t GetEXCState(bool force); 230 kern_return_t GetDBGState(bool force); 231 232 kern_return_t SetGPRState(); 233 kern_return_t SetVFPState(); 234 kern_return_t SetEXCState(); 235 kern_return_t SetDBGState(bool also_set_on_task); 236 237 bool IsWatchpointEnabled(const DBG &debug_state, uint32_t hw_index); 238 nub_addr_t GetWatchpointAddressByIndex(uint32_t hw_index); 239 nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); 240 241 class disabled_watchpoint { 242 public: disabled_watchpoint()243 disabled_watchpoint() { 244 addr = 0; 245 control = 0; 246 } 247 nub_addr_t addr; 248 uint32_t control; 249 }; 250 251 protected: 252 MachThread *m_thread; 253 State m_state; 254 DBG m_dbg_save; 255 256 // armv8 doesn't keep the disabled watchpoint values in the debug register 257 // context like armv7; 258 // we need to save them aside when we disable them temporarily. 259 std::vector<disabled_watchpoint> m_disabled_watchpoints; 260 261 nub_addr_t m_hw_single_chained_step_addr; 262 nub_addr_t m_last_decode_pc; 263 264 // The following member variables should be updated atomically. 265 int32_t m_watchpoint_hw_index; 266 bool m_watchpoint_did_occur; 267 bool m_watchpoint_resume_single_step_enabled; 268 269 typedef std::map<uint32_t, Context> SaveRegisterStates; 270 SaveRegisterStates m_saved_register_states; 271 }; 272 273 #endif // #if defined (__arm__) 274 #endif // #ifndef __DebugNubArchMachARM_h__ 275