DNBArchImplX86_64.h revision fc8909388e6f1cea591c0d56434236f8d16543e6
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 22class MachThread; 23 24class DNBArchImplX86_64 : public DNBArchProtocol 25{ 26public: 27 DNBArchImplX86_64(MachThread *thread) : 28 m_thread(thread), 29 m_state() 30 { 31 } 32 virtual ~DNBArchImplX86_64() 33 { 34 } 35 36 static void Initialize(); 37 virtual bool GetRegisterValue(int set, int reg, DNBRegisterValue *value); 38 virtual bool SetRegisterValue(int set, int reg, const DNBRegisterValue *value); 39 virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); 40 virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); 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, bool read, bool write); 55 virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index); 56 virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); 57 58protected: 59 kern_return_t EnableHardwareSingleStep (bool enable); 60 61 typedef __x86_64_thread_state_t GPR; 62 typedef __x86_64_float_state_t FPU; 63 typedef __x86_64_exception_state_t EXC; 64 typedef __x86_64_avx_state_t AVX; 65 typedef __x86_64_debug_state_t DBG; 66 67 static const DNBRegisterInfo g_gpr_registers[]; 68 static const DNBRegisterInfo g_fpu_registers_no_avx[]; 69 static const DNBRegisterInfo g_fpu_registers_avx[]; 70 static const DNBRegisterInfo g_exc_registers[]; 71 static const DNBRegisterSetInfo g_reg_sets_no_avx[]; 72 static const DNBRegisterSetInfo g_reg_sets_avx[]; 73 static const size_t k_num_gpr_registers; 74 static const size_t k_num_fpu_registers_no_avx; 75 static const size_t k_num_fpu_registers_avx; 76 static const size_t k_num_exc_registers; 77 static const size_t k_num_all_registers_no_avx; 78 static const size_t k_num_all_registers_avx; 79 static const size_t k_num_register_sets; 80 81 typedef enum RegisterSetTag 82 { 83 e_regSetALL = REGISTER_SET_ALL, 84 e_regSetGPR, 85 e_regSetFPU, 86 e_regSetEXC, 87 e_regSetDBG, 88 kNumRegisterSets 89 } RegisterSet; 90 91 typedef enum RegisterSetWordSizeTag 92 { 93 e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int), 94 e_regSetWordSizeFPR = sizeof(FPU) / sizeof(int), 95 e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), 96 e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), 97 e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) 98 } RegisterSetWordSize; 99 100 enum 101 { 102 Read = 0, 103 Write = 1, 104 kNumErrors = 2 105 }; 106 107 struct Context 108 { 109 GPR gpr; 110 union { 111 FPU no_avx; 112 AVX avx; 113 } fpu; 114 EXC exc; 115 DBG dbg; 116 }; 117 118 struct State 119 { 120 Context context; 121 kern_return_t gpr_errs[2]; // Read/Write errors 122 kern_return_t fpu_errs[2]; // Read/Write errors 123 kern_return_t exc_errs[2]; // Read/Write errors 124 kern_return_t dbg_errs[2]; // Read/Write errors 125 126 State() 127 { 128 uint32_t i; 129 for (i=0; i<kNumErrors; i++) 130 { 131 gpr_errs[i] = -1; 132 fpu_errs[i] = -1; 133 exc_errs[i] = -1; 134 dbg_errs[i] = -1; 135 } 136 } 137 138 void 139 InvalidateAllRegisterStates() 140 { 141 SetError (e_regSetALL, Read, -1); 142 } 143 144 kern_return_t 145 GetError (int flavor, uint32_t err_idx) const 146 { 147 if (err_idx < kNumErrors) 148 { 149 switch (flavor) 150 { 151 // When getting all errors, just OR all values together to see if 152 // we got any kind of error. 153 case e_regSetALL: return gpr_errs[err_idx] | 154 fpu_errs[err_idx] | 155 exc_errs[err_idx]; 156 case e_regSetGPR: return gpr_errs[err_idx]; 157 case e_regSetFPU: return fpu_errs[err_idx]; 158 case e_regSetEXC: return exc_errs[err_idx]; 159 case e_regSetDBG: return dbg_errs[err_idx]; 160 default: break; 161 } 162 } 163 return -1; 164 } 165 166 bool 167 SetError (int flavor, uint32_t err_idx, kern_return_t err) 168 { 169 if (err_idx < kNumErrors) 170 { 171 switch (flavor) 172 { 173 case e_regSetALL: 174 gpr_errs[err_idx] = 175 fpu_errs[err_idx] = 176 exc_errs[err_idx] = 177 dbg_errs[err_idx] = err; 178 return true; 179 180 case e_regSetGPR: 181 gpr_errs[err_idx] = err; 182 return true; 183 184 case e_regSetFPU: 185 fpu_errs[err_idx] = err; 186 return true; 187 188 case e_regSetEXC: 189 exc_errs[err_idx] = err; 190 return true; 191 192 case e_regSetDBG: 193 dbg_errs[err_idx] = err; 194 return true; 195 196 default: break; 197 } 198 } 199 return false; 200 } 201 202 bool 203 RegsAreValid (int flavor) const 204 { 205 return GetError(flavor, Read) == KERN_SUCCESS; 206 } 207 }; 208 209 kern_return_t GetGPRState (bool force); 210 kern_return_t GetFPUState (bool force); 211 kern_return_t GetEXCState (bool force); 212 kern_return_t GetDBGState (bool force); 213 214 kern_return_t SetGPRState (); 215 kern_return_t SetFPUState (); 216 kern_return_t SetEXCState (); 217 kern_return_t SetDBGState (); 218 219 static DNBArchProtocol * 220 Create (MachThread *thread); 221 222 static const uint8_t * const 223 SoftwareBreakpointOpcode (nub_size_t byte_size); 224 225 static const DNBRegisterSetInfo * 226 GetRegisterSetInfo(nub_size_t *num_reg_sets); 227 228 static bool 229 CPUHasAVX() 230 { 231 if (s_has_avx == kAVXUnknown) 232 s_has_avx = (::HasAVX() ? kAVXPresent : kAVXNotPresent); 233 234 return (s_has_avx == kAVXPresent); 235 } 236 237 // Helper functions for watchpoint manipulations. 238 static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write); 239 static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); 240 static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); 241 static void ClearWatchpointHits(DBG &debug_state); 242 static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); 243 static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); 244 245 MachThread *m_thread; 246 State m_state; 247 248 static enum AVXPresence { 249 kAVXPresent, 250 kAVXNotPresent, 251 kAVXUnknown 252 } s_has_avx; 253}; 254 255#endif // #if defined (__i386__) || defined (__x86_64__) 256#endif // #ifndef __DNBArchImplX86_64_h__ 257