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 23 class MachThread; 24 25 class DNBArchImplI386 : public DNBArchProtocol 26 { 27 public: DNBArchImplI386(MachThread * thread)28 DNBArchImplI386(MachThread *thread) : 29 m_thread(thread), 30 m_state(), 31 m_2pc_dbg_checkpoint(), 32 m_2pc_trans_state(Trans_Done) 33 { 34 } ~DNBArchImplI386()35 virtual ~DNBArchImplI386() 36 { 37 } 38 39 static void Initialize(); 40 41 virtual bool GetRegisterValue(int set, int reg, DNBRegisterValue *value); 42 virtual bool SetRegisterValue(int set, int reg, const DNBRegisterValue *value); 43 virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); 44 virtual nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); 45 virtual kern_return_t GetRegisterState (int set, bool force); 46 virtual kern_return_t SetRegisterState (int set); 47 virtual bool RegisterSetStateIsValid (int set) const; 48 49 virtual uint64_t GetPC(uint64_t failValue); // Get program counter 50 virtual kern_return_t SetPC(uint64_t value); 51 virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer 52 virtual void ThreadWillResume(); 53 virtual bool ThreadDidStop(); 54 virtual bool NotifyException(MachException::Data& exc); 55 56 virtual uint32_t NumSupportedHardwareWatchpoints(); 57 virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task); 58 virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index, bool also_set_on_task); 59 virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); 60 61 protected: 62 kern_return_t EnableHardwareSingleStep (bool enable); 63 64 typedef __i386_thread_state_t GPR; 65 typedef __i386_float_state_t FPU; 66 typedef __i386_exception_state_t EXC; 67 typedef __i386_avx_state_t AVX; 68 typedef __i386_debug_state_t DBG; 69 70 static const DNBRegisterInfo g_gpr_registers[]; 71 static const DNBRegisterInfo g_fpu_registers_no_avx[]; 72 static const DNBRegisterInfo g_fpu_registers_avx[]; 73 static const DNBRegisterInfo g_exc_registers[]; 74 static const DNBRegisterSetInfo g_reg_sets_no_avx[]; 75 static const DNBRegisterSetInfo g_reg_sets_avx[]; 76 static const size_t k_num_gpr_registers; 77 static const size_t k_num_fpu_registers_no_avx; 78 static const size_t k_num_fpu_registers_avx; 79 static const size_t k_num_exc_registers; 80 static const size_t k_num_all_registers_no_avx; 81 static const size_t k_num_all_registers_avx; 82 static const size_t k_num_register_sets; 83 84 typedef enum RegisterSetTag 85 { 86 e_regSetALL = REGISTER_SET_ALL, 87 e_regSetGPR, 88 e_regSetFPU, 89 e_regSetEXC, 90 e_regSetDBG, 91 kNumRegisterSets 92 } RegisterSet; 93 94 typedef enum RegisterSetWordSizeTag 95 { 96 e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int), 97 e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), 98 e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), 99 e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), 100 e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) 101 } RegisterSetWordSize; 102 103 enum 104 { 105 Read = 0, 106 Write = 1, 107 kNumErrors = 2 108 }; 109 110 struct Context 111 { 112 GPR gpr; 113 union { 114 FPU no_avx; 115 AVX avx; 116 } fpu; 117 EXC exc; 118 DBG dbg; 119 }; 120 121 struct State 122 { 123 Context context; 124 kern_return_t gpr_errs[2]; // Read/Write errors 125 kern_return_t fpu_errs[2]; // Read/Write errors 126 kern_return_t exc_errs[2]; // Read/Write errors 127 kern_return_t dbg_errs[2]; // Read/Write errors 128 StateState129 State() 130 { 131 uint32_t i; 132 for (i=0; i<kNumErrors; i++) 133 { 134 gpr_errs[i] = -1; 135 fpu_errs[i] = -1; 136 exc_errs[i] = -1; 137 dbg_errs[i] = -1; 138 } 139 } InvalidateAllRegisterStatesState140 void InvalidateAllRegisterStates() 141 { 142 SetError (e_regSetALL, Read, -1); 143 } GetErrorState144 kern_return_t 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 } SetErrorState164 bool SetError (int flavor, uint32_t err_idx, kern_return_t err) 165 { 166 if (err_idx < kNumErrors) 167 { 168 switch (flavor) 169 { 170 case e_regSetALL: 171 gpr_errs[err_idx] = 172 fpu_errs[err_idx] = 173 exc_errs[err_idx] = 174 dbg_errs[err_idx] = err; 175 return true; 176 177 case e_regSetGPR: 178 gpr_errs[err_idx] = err; 179 return true; 180 181 case e_regSetFPU: 182 fpu_errs[err_idx] = err; 183 return true; 184 185 case e_regSetEXC: 186 exc_errs[err_idx] = err; 187 return true; 188 189 case e_regSetDBG: 190 dbg_errs[err_idx] = err; 191 return true; 192 193 default: break; 194 } 195 } 196 return false; 197 } RegsAreValidState198 bool RegsAreValid (int flavor) const 199 { 200 return GetError(flavor, Read) == KERN_SUCCESS; 201 } 202 }; 203 204 kern_return_t GetGPRState (bool force); 205 kern_return_t GetFPUState (bool force); 206 kern_return_t GetEXCState (bool force); 207 kern_return_t GetDBGState (bool force); 208 209 kern_return_t SetGPRState (); 210 kern_return_t SetFPUState (); 211 kern_return_t SetEXCState (); 212 kern_return_t SetDBGState (bool also_set_on_task); 213 214 static DNBArchProtocol * 215 Create (MachThread *thread); 216 217 static const uint8_t * const 218 SoftwareBreakpointOpcode (nub_size_t byte_size); 219 220 static const DNBRegisterSetInfo * 221 GetRegisterSetInfo(nub_size_t *num_reg_sets); 222 223 // Helper functions for watchpoint manipulations. 224 static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write); 225 static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); 226 static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); 227 static void ClearWatchpointHits(DBG &debug_state); 228 static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); 229 static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); 230 231 virtual bool StartTransForHWP(); 232 virtual bool RollbackTransForHWP(); 233 virtual bool FinishTransForHWP(); 234 DBG GetDBGCheckpoint(); 235 236 MachThread *m_thread; 237 State m_state; 238 DBG m_2pc_dbg_checkpoint; 239 uint32_t m_2pc_trans_state; // Is transaction of DBG state change: Pedning (0), Done (1), or Rolled Back (2)? 240 }; 241 242 #endif // #if defined (__i386__) || defined (__x86_64__) 243 #endif // #ifndef __DNBArchImplI386_h__ 244