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