DNBArchImplI386.h revision 0875a979e39324f0b8e7597b8ba37cca9efa0d27
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 58protected: 59 kern_return_t EnableHardwareSingleStep (bool enable); 60 61 typedef __i386_thread_state_t GPR; 62 typedef __i386_float_state_t FPU; 63 typedef __i386_exception_state_t EXC; 64 typedef __i386_avx_state_t AVX; 65 typedef __i386_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 void InvalidateAllRegisterStates() 138 { 139 SetError (e_regSetALL, Read, -1); 140 } 141 kern_return_t GetError (int flavor, uint32_t err_idx) const 142 { 143 if (err_idx < kNumErrors) 144 { 145 switch (flavor) 146 { 147 // When getting all errors, just OR all values together to see if 148 // we got any kind of error. 149 case e_regSetALL: return gpr_errs[err_idx] | 150 fpu_errs[err_idx] | 151 exc_errs[err_idx]; 152 case e_regSetGPR: return gpr_errs[err_idx]; 153 case e_regSetFPU: return fpu_errs[err_idx]; 154 case e_regSetEXC: return exc_errs[err_idx]; 155 case e_regSetDBG: return dbg_errs[err_idx]; 156 default: break; 157 } 158 } 159 return -1; 160 } 161 bool SetError (int flavor, uint32_t err_idx, kern_return_t err) 162 { 163 if (err_idx < kNumErrors) 164 { 165 switch (flavor) 166 { 167 case e_regSetALL: 168 gpr_errs[err_idx] = 169 fpu_errs[err_idx] = 170 exc_errs[err_idx] = 171 dbg_errs[err_idx] = err; 172 return true; 173 174 case e_regSetGPR: 175 gpr_errs[err_idx] = err; 176 return true; 177 178 case e_regSetFPU: 179 fpu_errs[err_idx] = err; 180 return true; 181 182 case e_regSetEXC: 183 exc_errs[err_idx] = err; 184 return true; 185 186 case e_regSetDBG: 187 dbg_errs[err_idx] = err; 188 return true; 189 190 default: break; 191 } 192 } 193 return false; 194 } 195 bool RegsAreValid (int flavor) const 196 { 197 return GetError(flavor, Read) == KERN_SUCCESS; 198 } 199 }; 200 201 kern_return_t GetGPRState (bool force); 202 kern_return_t GetFPUState (bool force); 203 kern_return_t GetEXCState (bool force); 204 kern_return_t GetDBGState (bool force); 205 206 kern_return_t SetGPRState (); 207 kern_return_t SetFPUState (); 208 kern_return_t SetEXCState (); 209 kern_return_t SetDBGState (); 210 211 static DNBArchProtocol * 212 Create (MachThread *thread); 213 214 static const uint8_t * const 215 SoftwareBreakpointOpcode (nub_size_t byte_size); 216 217 static const DNBRegisterSetInfo * 218 GetRegisterSetInfo(nub_size_t *num_reg_sets); 219 220 static bool 221 CPUHasAVX() 222 { 223 if (s_has_avx == kAVXUnknown) 224 s_has_avx = (::HasAVX() ? kAVXPresent : kAVXNotPresent); 225 226 return (s_has_avx == kAVXPresent); 227 } 228 229 // Helper functions for watchpoint manipulations. 230 static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write); 231 static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); 232 static bool IsVacantWatchpoint(const DBG &debug_state, uint32_t hw_index); 233 static void ClearWatchpointHits(DBG &debug_state); 234 static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); 235 236 MachThread *m_thread; 237 State m_state; 238 239 static enum AVXPresence { 240 kAVXPresent, 241 kAVXNotPresent, 242 kAVXUnknown 243 } s_has_avx; 244}; 245 246#endif // #if defined (__i386__) || defined (__x86_64__) 247#endif // #ifndef __DNBArchImplI386_h__ 248