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