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