DNBArchImplI386.h revision f4933ed8d0fa218b5db476ecd881ec67495037f3
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 void HardwareWatchpointStateChanged (); 58 virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); 59 60protected: 61 kern_return_t EnableHardwareSingleStep (bool enable); 62 63 typedef __i386_thread_state_t GPR; 64 typedef __i386_float_state_t FPU; 65 typedef __i386_exception_state_t EXC; 66 typedef __i386_avx_state_t AVX; 67 typedef __i386_debug_state_t DBG; 68 69 static const DNBRegisterInfo g_gpr_registers[]; 70 static const DNBRegisterInfo g_fpu_registers_no_avx[]; 71 static const DNBRegisterInfo g_fpu_registers_avx[]; 72 static const DNBRegisterInfo g_exc_registers[]; 73 static const DNBRegisterSetInfo g_reg_sets_no_avx[]; 74 static const DNBRegisterSetInfo g_reg_sets_avx[]; 75 static const size_t k_num_gpr_registers; 76 static const size_t k_num_fpu_registers_no_avx; 77 static const size_t k_num_fpu_registers_avx; 78 static const size_t k_num_exc_registers; 79 static const size_t k_num_all_registers_no_avx; 80 static const size_t k_num_all_registers_avx; 81 static const size_t k_num_register_sets; 82 83 typedef enum RegisterSetTag 84 { 85 e_regSetALL = REGISTER_SET_ALL, 86 e_regSetGPR, 87 e_regSetFPU, 88 e_regSetEXC, 89 e_regSetDBG, 90 kNumRegisterSets 91 } RegisterSet; 92 93 typedef enum RegisterSetWordSizeTag 94 { 95 e_regSetWordSizeGPR = sizeof(GPR) / sizeof(int), 96 e_regSetWordSizeFPU = sizeof(FPU) / sizeof(int), 97 e_regSetWordSizeEXC = sizeof(EXC) / sizeof(int), 98 e_regSetWordSizeAVX = sizeof(AVX) / sizeof(int), 99 e_regSetWordSizeDBG = sizeof(DBG) / sizeof(int) 100 } RegisterSetWordSize; 101 102 enum 103 { 104 Read = 0, 105 Write = 1, 106 kNumErrors = 2 107 }; 108 109 struct Context 110 { 111 GPR gpr; 112 union { 113 FPU no_avx; 114 AVX avx; 115 } fpu; 116 EXC exc; 117 DBG dbg; 118 }; 119 120 // See also HardwareWatchpointStateChanged() which updates this class-wide variable. 121 static DBG Global_Debug_State; 122 static bool Valid_Global_Debug_State; 123 124 struct State 125 { 126 Context context; 127 kern_return_t gpr_errs[2]; // Read/Write errors 128 kern_return_t fpu_errs[2]; // Read/Write errors 129 kern_return_t exc_errs[2]; // Read/Write errors 130 kern_return_t dbg_errs[2]; // Read/Write errors 131 132 State() 133 { 134 uint32_t i; 135 for (i=0; i<kNumErrors; i++) 136 { 137 gpr_errs[i] = -1; 138 fpu_errs[i] = -1; 139 exc_errs[i] = -1; 140 dbg_errs[i] = -1; 141 } 142 } 143 void InvalidateAllRegisterStates() 144 { 145 SetError (e_regSetALL, Read, -1); 146 } 147 kern_return_t GetError (int flavor, uint32_t err_idx) const 148 { 149 if (err_idx < kNumErrors) 150 { 151 switch (flavor) 152 { 153 // When getting all errors, just OR all values together to see if 154 // we got any kind of error. 155 case e_regSetALL: return gpr_errs[err_idx] | 156 fpu_errs[err_idx] | 157 exc_errs[err_idx]; 158 case e_regSetGPR: return gpr_errs[err_idx]; 159 case e_regSetFPU: return fpu_errs[err_idx]; 160 case e_regSetEXC: return exc_errs[err_idx]; 161 case e_regSetDBG: return dbg_errs[err_idx]; 162 default: break; 163 } 164 } 165 return -1; 166 } 167 bool 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 bool RegsAreValid (int flavor) const 202 { 203 return GetError(flavor, Read) == KERN_SUCCESS; 204 } 205 }; 206 207 kern_return_t GetGPRState (bool force); 208 kern_return_t GetFPUState (bool force); 209 kern_return_t GetEXCState (bool force); 210 kern_return_t GetDBGState (bool force); 211 212 kern_return_t SetGPRState (); 213 kern_return_t SetFPUState (); 214 kern_return_t SetEXCState (); 215 kern_return_t SetDBGState (); 216 217 static DNBArchProtocol * 218 Create (MachThread *thread); 219 220 static const uint8_t * const 221 SoftwareBreakpointOpcode (nub_size_t byte_size); 222 223 static const DNBRegisterSetInfo * 224 GetRegisterSetInfo(nub_size_t *num_reg_sets); 225 226 // Helper functions for watchpoint manipulations. 227 static void SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write); 228 static void ClearWatchpoint(DBG &debug_state, uint32_t hw_index); 229 static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); 230 static void ClearWatchpointHits(DBG &debug_state); 231 static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); 232 static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); 233 234 MachThread *m_thread; 235 State m_state; 236}; 237 238#endif // #if defined (__i386__) || defined (__x86_64__) 239#endif // #ifndef __DNBArchImplI386_h__ 240