1 //===-- DNBArchImplX86_64.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 __DNBArchImplX86_64_h__ 14 #define __DNBArchImplX86_64_h__ 15 16 #if defined(__i386__) || defined(__x86_64__) 17 #include "DNBArch.h" 18 #include "MachRegisterStatesX86_64.h" 19 20 #include <map> 21 22 class MachThread; 23 24 class DNBArchImplX86_64 : public DNBArchProtocol { 25 public: DNBArchImplX86_64(MachThread * thread)26 DNBArchImplX86_64(MachThread *thread) 27 : DNBArchProtocol(), m_thread(thread), m_state(), m_2pc_dbg_checkpoint(), 28 m_2pc_trans_state(Trans_Done), m_saved_register_states() {} ~DNBArchImplX86_64()29 virtual ~DNBArchImplX86_64() {} 30 31 static void Initialize(); 32 33 virtual bool GetRegisterValue(uint32_t set, uint32_t reg, 34 DNBRegisterValue *value); 35 virtual bool SetRegisterValue(uint32_t set, uint32_t reg, 36 const DNBRegisterValue *value); 37 virtual nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); 38 virtual nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); 39 virtual uint32_t SaveRegisterState(); 40 virtual bool RestoreRegisterState(uint32_t save_id); 41 42 virtual kern_return_t GetRegisterState(int set, bool force); 43 virtual kern_return_t SetRegisterState(int set); 44 virtual bool RegisterSetStateIsValid(int set) const; 45 46 virtual uint64_t GetPC(uint64_t failValue); // Get program counter 47 virtual kern_return_t SetPC(uint64_t value); 48 virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer 49 virtual void ThreadWillResume(); 50 virtual bool ThreadDidStop(); 51 virtual bool NotifyException(MachException::Data &exc); 52 53 virtual uint32_t NumSupportedHardwareWatchpoints(); 54 virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size, 55 bool read, bool write, 56 bool also_set_on_task); 57 virtual bool DisableHardwareWatchpoint(uint32_t hw_break_index, 58 bool also_set_on_task); 59 virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); 60 61 protected: 62 kern_return_t EnableHardwareSingleStep(bool enable); 63 64 typedef __x86_64_thread_state_t GPR; 65 typedef __x86_64_float_state_t FPU; 66 typedef __x86_64_exception_state_t EXC; 67 typedef __x86_64_avx_state_t AVX; 68 typedef __x86_64_debug_state_t DBG; 69 70 static const DNBRegisterInfo g_gpr_registers[]; 71 static const DNBRegisterInfo g_fpu_registers_no_avx[]; 72 static const DNBRegisterInfo g_fpu_registers_avx[]; 73 static const DNBRegisterInfo g_exc_registers[]; 74 static const DNBRegisterSetInfo g_reg_sets_no_avx[]; 75 static const DNBRegisterSetInfo g_reg_sets_avx[]; 76 static const size_t k_num_gpr_registers; 77 static const size_t k_num_fpu_registers_no_avx; 78 static const size_t k_num_fpu_registers_avx; 79 static const size_t k_num_exc_registers; 80 static const size_t k_num_all_registers_no_avx; 81 static const size_t k_num_all_registers_avx; 82 static const size_t k_num_register_sets; 83 84 typedef __x86_64_avx512f_state_t AVX512F; 85 static const DNBRegisterInfo g_fpu_registers_avx512f[]; 86 static const DNBRegisterSetInfo g_reg_sets_avx512f[]; 87 static const size_t k_num_fpu_registers_avx512f; 88 static const size_t k_num_all_registers_avx512f; 89 90 enum RegisterSet { 91 e_regSetALL = REGISTER_SET_ALL, 92 e_regSetGPR, 93 e_regSetFPU, 94 e_regSetEXC, 95 e_regSetDBG, 96 kNumRegisterSets 97 }; 98 99 enum RegisterSetWordSize { 100 e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int), 101 e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), 102 e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), 103 e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), 104 e_regSetWordSizeAVX512f = sizeof(AVX512F) / sizeof(int), 105 e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) 106 }; 107 108 enum { Read = 0, Write = 1, kNumErrors = 2 }; 109 110 struct Context { 111 GPR gpr; 112 union { 113 FPU no_avx; 114 AVX avx; 115 AVX512F avx512f; 116 } fpu; 117 EXC exc; 118 DBG dbg; 119 }; 120 121 struct State { 122 Context context; 123 kern_return_t gpr_errs[2]; // Read/Write errors 124 kern_return_t fpu_errs[2]; // Read/Write errors 125 kern_return_t exc_errs[2]; // Read/Write errors 126 kern_return_t dbg_errs[2]; // Read/Write errors 127 StateState128 State() { 129 uint32_t i; 130 for (i = 0; i < kNumErrors; i++) { 131 gpr_errs[i] = -1; 132 fpu_errs[i] = -1; 133 exc_errs[i] = -1; 134 dbg_errs[i] = -1; 135 } 136 } 137 InvalidateAllRegisterStatesState138 void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } 139 GetErrorState140 kern_return_t GetError(int flavor, uint32_t err_idx) const { 141 if (err_idx < kNumErrors) { 142 switch (flavor) { 143 // When getting all errors, just OR all values together to see if 144 // we got any kind of error. 145 case e_regSetALL: 146 return gpr_errs[err_idx] | fpu_errs[err_idx] | exc_errs[err_idx]; 147 case e_regSetGPR: 148 return gpr_errs[err_idx]; 149 case e_regSetFPU: 150 return fpu_errs[err_idx]; 151 case e_regSetEXC: 152 return exc_errs[err_idx]; 153 case e_regSetDBG: 154 return dbg_errs[err_idx]; 155 default: 156 break; 157 } 158 } 159 return -1; 160 } 161 SetErrorState162 bool SetError(int flavor, uint32_t err_idx, kern_return_t err) { 163 if (err_idx < kNumErrors) { 164 switch (flavor) { 165 case e_regSetALL: 166 gpr_errs[err_idx] = fpu_errs[err_idx] = exc_errs[err_idx] = 167 dbg_errs[err_idx] = err; 168 return true; 169 170 case e_regSetGPR: 171 gpr_errs[err_idx] = err; 172 return true; 173 174 case e_regSetFPU: 175 fpu_errs[err_idx] = err; 176 return true; 177 178 case e_regSetEXC: 179 exc_errs[err_idx] = err; 180 return true; 181 182 case e_regSetDBG: 183 dbg_errs[err_idx] = err; 184 return true; 185 186 default: 187 break; 188 } 189 } 190 return false; 191 } 192 RegsAreValidState193 bool RegsAreValid(int flavor) const { 194 return GetError(flavor, Read) == KERN_SUCCESS; 195 } 196 }; 197 198 kern_return_t GetGPRState(bool force); 199 kern_return_t GetFPUState(bool force); 200 kern_return_t GetEXCState(bool force); 201 kern_return_t GetDBGState(bool force); 202 203 kern_return_t SetGPRState(); 204 kern_return_t SetFPUState(); 205 kern_return_t SetEXCState(); 206 kern_return_t SetDBGState(bool also_set_on_task); 207 208 static DNBArchProtocol *Create(MachThread *thread); 209 210 static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); 211 212 static const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets); 213 214 static uint32_t GetRegisterContextSize(); 215 216 // Helper functions for watchpoint manipulations. 217 static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, 218 nub_addr_t addr, nub_size_t size, bool read, 219 bool write); 220 static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); 221 static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); 222 static void ClearWatchpointHits(DBG &debug_state); 223 static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); 224 static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); 225 226 virtual bool StartTransForHWP(); 227 virtual bool RollbackTransForHWP(); 228 virtual bool FinishTransForHWP(); 229 DBG GetDBGCheckpoint(); 230 231 MachThread *m_thread; 232 State m_state; 233 DBG m_2pc_dbg_checkpoint; 234 uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning 235 // (0), Done (1), or Rolled Back (2)? 236 typedef std::map<uint32_t, Context> SaveRegisterStates; 237 SaveRegisterStates m_saved_register_states; 238 }; 239 240 #endif // #if defined (__i386__) || defined (__x86_64__) 241 #endif // #ifndef __DNBArchImplX86_64_h__ 242