1 //===-- DNBArchImplX86_64.cpp -----------------------------------*- 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 #if defined(__i386__) || defined(__x86_64__) 15 16 #include <sys/cdefs.h> 17 #include <sys/sysctl.h> 18 #include <sys/types.h> 19 20 #include "DNBLog.h" 21 #include "MacOSX/x86_64/DNBArchImplX86_64.h" 22 #include "MachProcess.h" 23 #include "MachThread.h" 24 #include <mach/mach.h> 25 #include <stdlib.h> 26 27 #if defined(LLDB_DEBUGSERVER_RELEASE) || defined(LLDB_DEBUGSERVER_DEBUG) 28 enum debugState { debugStateUnknown, debugStateOff, debugStateOn }; 29 30 static debugState sFPUDebugState = debugStateUnknown; 31 static debugState sAVXForceState = debugStateUnknown; 32 33 static bool DebugFPURegs() { 34 if (sFPUDebugState == debugStateUnknown) { 35 if (getenv("DNB_DEBUG_FPU_REGS")) 36 sFPUDebugState = debugStateOn; 37 else 38 sFPUDebugState = debugStateOff; 39 } 40 41 return (sFPUDebugState == debugStateOn); 42 } 43 44 static bool ForceAVXRegs() { 45 if (sFPUDebugState == debugStateUnknown) { 46 if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS")) 47 sAVXForceState = debugStateOn; 48 else 49 sAVXForceState = debugStateOff; 50 } 51 52 return (sAVXForceState == debugStateOn); 53 } 54 55 #define DEBUG_FPU_REGS (DebugFPURegs()) 56 #define FORCE_AVX_REGS (ForceAVXRegs()) 57 #else 58 #define DEBUG_FPU_REGS (0) 59 #define FORCE_AVX_REGS (0) 60 #endif 61 62 bool DetectHardwareFeature(const char *feature) { 63 int answer = 0; 64 size_t answer_size = sizeof(answer); 65 int error = ::sysctlbyname(feature, &answer, &answer_size, NULL, 0); 66 return error == 0 && answer != 0; 67 } 68 69 enum AVXPresence { eAVXUnknown = -1, eAVXNotPresent = 0, eAVXPresent = 1 }; 70 71 bool LogAVXAndReturn(AVXPresence has_avx, int err, const char * os_ver) { 72 DNBLogThreadedIf(LOG_THREAD, 73 "CPUHasAVX(): g_has_avx = %i (err = %i, os_ver = %s)", 74 has_avx, err, os_ver); 75 return (has_avx == eAVXPresent); 76 } 77 78 extern "C" bool CPUHasAVX() { 79 static AVXPresence g_has_avx = eAVXUnknown; 80 if (g_has_avx != eAVXUnknown) 81 return LogAVXAndReturn(g_has_avx, 0, ""); 82 83 g_has_avx = eAVXNotPresent; 84 85 // OS X 10.7.3 and earlier have a bug in thread_get_state that truncated the 86 // size of the return. To work around this we have to disable AVX debugging 87 // on hosts prior to 10.7.3 (<rdar://problem/10122874>). 88 int mib[2]; 89 char buffer[1024]; 90 size_t length = sizeof(buffer); 91 mib[0] = CTL_KERN; 92 mib[1] = KERN_OSVERSION; 93 94 // KERN_OSVERSION returns the build number which is a number signifying the 95 // major version, a capitol letter signifying the minor version, and numbers 96 // signifying the build (ex: on 10.12.3, the returned value is 16D32). 97 int err = ::sysctl(mib, 2, &buffer, &length, NULL, 0); 98 if (err != 0) 99 return LogAVXAndReturn(g_has_avx, err, ""); 100 101 size_t first_letter = 0; 102 for (; first_letter < length; ++first_letter) { 103 // This is looking for the first uppercase letter 104 if (isupper(buffer[first_letter])) 105 break; 106 } 107 char letter = buffer[first_letter]; 108 buffer[first_letter] = '\0'; 109 auto major_ver = strtoull(buffer, NULL, 0); 110 buffer[first_letter] = letter; 111 112 // In this check we're looking to see that our major and minor version numer 113 // was >= 11E, which is the 10.7.4 release. 114 if (major_ver < 11 || (major_ver == 11 && letter < 'E')) 115 return LogAVXAndReturn(g_has_avx, err, buffer); 116 if (DetectHardwareFeature("hw.optional.avx1_0")) 117 g_has_avx = eAVXPresent; 118 119 return LogAVXAndReturn(g_has_avx, err, buffer); 120 } 121 122 uint64_t DNBArchImplX86_64::GetPC(uint64_t failValue) { 123 // Get program counter 124 if (GetGPRState(false) == KERN_SUCCESS) 125 return m_state.context.gpr.__rip; 126 return failValue; 127 } 128 129 kern_return_t DNBArchImplX86_64::SetPC(uint64_t value) { 130 // Get program counter 131 kern_return_t err = GetGPRState(false); 132 if (err == KERN_SUCCESS) { 133 m_state.context.gpr.__rip = value; 134 err = SetGPRState(); 135 } 136 return err == KERN_SUCCESS; 137 } 138 139 uint64_t DNBArchImplX86_64::GetSP(uint64_t failValue) { 140 // Get stack pointer 141 if (GetGPRState(false) == KERN_SUCCESS) 142 return m_state.context.gpr.__rsp; 143 return failValue; 144 } 145 146 // Uncomment the value below to verify the values in the debugger. 147 //#define DEBUG_GPR_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED 148 149 kern_return_t DNBArchImplX86_64::GetGPRState(bool force) { 150 if (force || m_state.GetError(e_regSetGPR, Read)) { 151 #if DEBUG_GPR_VALUES 152 m_state.context.gpr.__rax = ('a' << 8) + 'x'; 153 m_state.context.gpr.__rbx = ('b' << 8) + 'x'; 154 m_state.context.gpr.__rcx = ('c' << 8) + 'x'; 155 m_state.context.gpr.__rdx = ('d' << 8) + 'x'; 156 m_state.context.gpr.__rdi = ('d' << 8) + 'i'; 157 m_state.context.gpr.__rsi = ('s' << 8) + 'i'; 158 m_state.context.gpr.__rbp = ('b' << 8) + 'p'; 159 m_state.context.gpr.__rsp = ('s' << 8) + 'p'; 160 m_state.context.gpr.__r8 = ('r' << 8) + '8'; 161 m_state.context.gpr.__r9 = ('r' << 8) + '9'; 162 m_state.context.gpr.__r10 = ('r' << 8) + 'a'; 163 m_state.context.gpr.__r11 = ('r' << 8) + 'b'; 164 m_state.context.gpr.__r12 = ('r' << 8) + 'c'; 165 m_state.context.gpr.__r13 = ('r' << 8) + 'd'; 166 m_state.context.gpr.__r14 = ('r' << 8) + 'e'; 167 m_state.context.gpr.__r15 = ('r' << 8) + 'f'; 168 m_state.context.gpr.__rip = ('i' << 8) + 'p'; 169 m_state.context.gpr.__rflags = ('f' << 8) + 'l'; 170 m_state.context.gpr.__cs = ('c' << 8) + 's'; 171 m_state.context.gpr.__fs = ('f' << 8) + 's'; 172 m_state.context.gpr.__gs = ('g' << 8) + 's'; 173 m_state.SetError(e_regSetGPR, Read, 0); 174 #else 175 mach_msg_type_number_t count = e_regSetWordSizeGPR; 176 m_state.SetError( 177 e_regSetGPR, Read, 178 ::thread_get_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, 179 (thread_state_t)&m_state.context.gpr, &count)); 180 DNBLogThreadedIf( 181 LOG_THREAD, 182 "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" 183 "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" 184 "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" 185 "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" 186 "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" 187 "\n\trip = %16.16llx" 188 "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", 189 m_thread->MachPortNumber(), x86_THREAD_STATE64, 190 x86_THREAD_STATE64_COUNT, m_state.GetError(e_regSetGPR, Read), 191 m_state.context.gpr.__rax, m_state.context.gpr.__rbx, 192 m_state.context.gpr.__rcx, m_state.context.gpr.__rdx, 193 m_state.context.gpr.__rdi, m_state.context.gpr.__rsi, 194 m_state.context.gpr.__rbp, m_state.context.gpr.__rsp, 195 m_state.context.gpr.__r8, m_state.context.gpr.__r9, 196 m_state.context.gpr.__r10, m_state.context.gpr.__r11, 197 m_state.context.gpr.__r12, m_state.context.gpr.__r13, 198 m_state.context.gpr.__r14, m_state.context.gpr.__r15, 199 m_state.context.gpr.__rip, m_state.context.gpr.__rflags, 200 m_state.context.gpr.__cs, m_state.context.gpr.__fs, 201 m_state.context.gpr.__gs); 202 203 // DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) 204 // => 0x%8.8x" 205 // "\n\trax = %16.16llx" 206 // "\n\trbx = %16.16llx" 207 // "\n\trcx = %16.16llx" 208 // "\n\trdx = %16.16llx" 209 // "\n\trdi = %16.16llx" 210 // "\n\trsi = %16.16llx" 211 // "\n\trbp = %16.16llx" 212 // "\n\trsp = %16.16llx" 213 // "\n\t r8 = %16.16llx" 214 // "\n\t r9 = %16.16llx" 215 // "\n\tr10 = %16.16llx" 216 // "\n\tr11 = %16.16llx" 217 // "\n\tr12 = %16.16llx" 218 // "\n\tr13 = %16.16llx" 219 // "\n\tr14 = %16.16llx" 220 // "\n\tr15 = %16.16llx" 221 // "\n\trip = %16.16llx" 222 // "\n\tflg = %16.16llx" 223 // "\n\t cs = %16.16llx" 224 // "\n\t fs = %16.16llx" 225 // "\n\t gs = %16.16llx", 226 // m_thread->MachPortNumber(), 227 // x86_THREAD_STATE64, 228 // x86_THREAD_STATE64_COUNT, 229 // m_state.GetError(e_regSetGPR, Read), 230 // m_state.context.gpr.__rax, 231 // m_state.context.gpr.__rbx, 232 // m_state.context.gpr.__rcx, 233 // m_state.context.gpr.__rdx, 234 // m_state.context.gpr.__rdi, 235 // m_state.context.gpr.__rsi, 236 // m_state.context.gpr.__rbp, 237 // m_state.context.gpr.__rsp, 238 // m_state.context.gpr.__r8, 239 // m_state.context.gpr.__r9, 240 // m_state.context.gpr.__r10, 241 // m_state.context.gpr.__r11, 242 // m_state.context.gpr.__r12, 243 // m_state.context.gpr.__r13, 244 // m_state.context.gpr.__r14, 245 // m_state.context.gpr.__r15, 246 // m_state.context.gpr.__rip, 247 // m_state.context.gpr.__rflags, 248 // m_state.context.gpr.__cs, 249 // m_state.context.gpr.__fs, 250 // m_state.context.gpr.__gs); 251 #endif 252 } 253 return m_state.GetError(e_regSetGPR, Read); 254 } 255 256 // Uncomment the value below to verify the values in the debugger. 257 //#define DEBUG_FPU_REGS 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED 258 259 kern_return_t DNBArchImplX86_64::GetFPUState(bool force) { 260 if (force || m_state.GetError(e_regSetFPU, Read)) { 261 if (DEBUG_FPU_REGS) { 262 m_state.context.fpu.no_avx.__fpu_reserved[0] = -1; 263 m_state.context.fpu.no_avx.__fpu_reserved[1] = -1; 264 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234; 265 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678; 266 m_state.context.fpu.no_avx.__fpu_ftw = 1; 267 m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX; 268 m_state.context.fpu.no_avx.__fpu_fop = 2; 269 m_state.context.fpu.no_avx.__fpu_ip = 3; 270 m_state.context.fpu.no_avx.__fpu_cs = 4; 271 m_state.context.fpu.no_avx.__fpu_rsrv2 = 5; 272 m_state.context.fpu.no_avx.__fpu_dp = 6; 273 m_state.context.fpu.no_avx.__fpu_ds = 7; 274 m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX; 275 m_state.context.fpu.no_avx.__fpu_mxcsr = 8; 276 m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9; 277 for (int i = 0; i < 16; ++i) { 278 if (i < 10) { 279 m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a'; 280 m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b'; 281 m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c'; 282 m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd'; 283 m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e'; 284 m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f'; 285 m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g'; 286 m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h'; 287 } else { 288 m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; 289 m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; 290 m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; 291 m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; 292 m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; 293 m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; 294 m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; 295 m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; 296 } 297 298 m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0'; 299 m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1'; 300 m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2'; 301 m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3'; 302 m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4'; 303 m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5'; 304 m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6'; 305 m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7'; 306 m_state.context.fpu.no_avx.__fpu_xmm8.__xmm_reg[i] = '8'; 307 m_state.context.fpu.no_avx.__fpu_xmm9.__xmm_reg[i] = '9'; 308 m_state.context.fpu.no_avx.__fpu_xmm10.__xmm_reg[i] = 'A'; 309 m_state.context.fpu.no_avx.__fpu_xmm11.__xmm_reg[i] = 'B'; 310 m_state.context.fpu.no_avx.__fpu_xmm12.__xmm_reg[i] = 'C'; 311 m_state.context.fpu.no_avx.__fpu_xmm13.__xmm_reg[i] = 'D'; 312 m_state.context.fpu.no_avx.__fpu_xmm14.__xmm_reg[i] = 'E'; 313 m_state.context.fpu.no_avx.__fpu_xmm15.__xmm_reg[i] = 'F'; 314 } 315 for (int i = 0; i < sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i) 316 m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN; 317 m_state.context.fpu.no_avx.__fpu_reserved1 = -1; 318 319 if (CPUHasAVX() || FORCE_AVX_REGS) { 320 for (int i = 0; i < 16; ++i) { 321 m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0' + i; 322 m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1' + i; 323 m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2' + i; 324 m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3' + i; 325 m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4' + i; 326 m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5' + i; 327 m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6' + i; 328 m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7' + i; 329 m_state.context.fpu.avx.__fpu_ymmh8.__xmm_reg[i] = '8' + i; 330 m_state.context.fpu.avx.__fpu_ymmh9.__xmm_reg[i] = '9' + i; 331 m_state.context.fpu.avx.__fpu_ymmh10.__xmm_reg[i] = 'A' + i; 332 m_state.context.fpu.avx.__fpu_ymmh11.__xmm_reg[i] = 'B' + i; 333 m_state.context.fpu.avx.__fpu_ymmh12.__xmm_reg[i] = 'C' + i; 334 m_state.context.fpu.avx.__fpu_ymmh13.__xmm_reg[i] = 'D' + i; 335 m_state.context.fpu.avx.__fpu_ymmh14.__xmm_reg[i] = 'E' + i; 336 m_state.context.fpu.avx.__fpu_ymmh15.__xmm_reg[i] = 'F' + i; 337 } 338 for (int i = 0; i < sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i) 339 m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN; 340 } 341 m_state.SetError(e_regSetFPU, Read, 0); 342 } else { 343 mach_msg_type_number_t count = e_regSetWordSizeFPU; 344 int flavor = __x86_64_FLOAT_STATE; 345 if (CPUHasAVX() || FORCE_AVX_REGS) { 346 count = e_regSetWordSizeAVX; 347 flavor = __x86_64_AVX_STATE; 348 } 349 m_state.SetError(e_regSetFPU, Read, 350 ::thread_get_state(m_thread->MachPortNumber(), flavor, 351 (thread_state_t)&m_state.context.fpu, 352 &count)); 353 DNBLogThreadedIf(LOG_THREAD, 354 "::thread_get_state (0x%4.4x, %u, &fpu, %u => 0x%8.8x", 355 m_thread->MachPortNumber(), flavor, (uint32_t)count, 356 m_state.GetError(e_regSetFPU, Read)); 357 } 358 } 359 return m_state.GetError(e_regSetFPU, Read); 360 } 361 362 kern_return_t DNBArchImplX86_64::GetEXCState(bool force) { 363 if (force || m_state.GetError(e_regSetEXC, Read)) { 364 mach_msg_type_number_t count = e_regSetWordSizeEXC; 365 m_state.SetError( 366 e_regSetEXC, Read, 367 ::thread_get_state(m_thread->MachPortNumber(), __x86_64_EXCEPTION_STATE, 368 (thread_state_t)&m_state.context.exc, &count)); 369 } 370 return m_state.GetError(e_regSetEXC, Read); 371 } 372 373 kern_return_t DNBArchImplX86_64::SetGPRState() { 374 kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); 375 DNBLogThreadedIf( 376 LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " 377 "(SetGPRState() for stop_count = %u)", 378 m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); 379 380 m_state.SetError(e_regSetGPR, Write, 381 ::thread_set_state(m_thread->MachPortNumber(), 382 __x86_64_THREAD_STATE, 383 (thread_state_t)&m_state.context.gpr, 384 e_regSetWordSizeGPR)); 385 DNBLogThreadedIf( 386 LOG_THREAD, 387 "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" 388 "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" 389 "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" 390 "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" 391 "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" 392 "\n\trip = %16.16llx" 393 "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", 394 m_thread->MachPortNumber(), __x86_64_THREAD_STATE, e_regSetWordSizeGPR, 395 m_state.GetError(e_regSetGPR, Write), m_state.context.gpr.__rax, 396 m_state.context.gpr.__rbx, m_state.context.gpr.__rcx, 397 m_state.context.gpr.__rdx, m_state.context.gpr.__rdi, 398 m_state.context.gpr.__rsi, m_state.context.gpr.__rbp, 399 m_state.context.gpr.__rsp, m_state.context.gpr.__r8, 400 m_state.context.gpr.__r9, m_state.context.gpr.__r10, 401 m_state.context.gpr.__r11, m_state.context.gpr.__r12, 402 m_state.context.gpr.__r13, m_state.context.gpr.__r14, 403 m_state.context.gpr.__r15, m_state.context.gpr.__rip, 404 m_state.context.gpr.__rflags, m_state.context.gpr.__cs, 405 m_state.context.gpr.__fs, m_state.context.gpr.__gs); 406 return m_state.GetError(e_regSetGPR, Write); 407 } 408 409 kern_return_t DNBArchImplX86_64::SetFPUState() { 410 if (DEBUG_FPU_REGS) { 411 m_state.SetError(e_regSetFPU, Write, 0); 412 return m_state.GetError(e_regSetFPU, Write); 413 } else { 414 int flavor = __x86_64_FLOAT_STATE; 415 mach_msg_type_number_t count = e_regSetWordSizeFPU; 416 if (CPUHasAVX() || FORCE_AVX_REGS) { 417 flavor = __x86_64_AVX_STATE; 418 count = e_regSetWordSizeAVX; 419 } 420 m_state.SetError( 421 e_regSetFPU, Write, 422 ::thread_set_state(m_thread->MachPortNumber(), flavor, 423 (thread_state_t)&m_state.context.fpu, count)); 424 return m_state.GetError(e_regSetFPU, Write); 425 } 426 } 427 428 kern_return_t DNBArchImplX86_64::SetEXCState() { 429 m_state.SetError(e_regSetEXC, Write, 430 ::thread_set_state(m_thread->MachPortNumber(), 431 __x86_64_EXCEPTION_STATE, 432 (thread_state_t)&m_state.context.exc, 433 e_regSetWordSizeEXC)); 434 return m_state.GetError(e_regSetEXC, Write); 435 } 436 437 kern_return_t DNBArchImplX86_64::GetDBGState(bool force) { 438 if (force || m_state.GetError(e_regSetDBG, Read)) { 439 mach_msg_type_number_t count = e_regSetWordSizeDBG; 440 m_state.SetError( 441 e_regSetDBG, Read, 442 ::thread_get_state(m_thread->MachPortNumber(), __x86_64_DEBUG_STATE, 443 (thread_state_t)&m_state.context.dbg, &count)); 444 } 445 return m_state.GetError(e_regSetDBG, Read); 446 } 447 448 kern_return_t DNBArchImplX86_64::SetDBGState(bool also_set_on_task) { 449 m_state.SetError(e_regSetDBG, Write, 450 ::thread_set_state(m_thread->MachPortNumber(), 451 __x86_64_DEBUG_STATE, 452 (thread_state_t)&m_state.context.dbg, 453 e_regSetWordSizeDBG)); 454 if (also_set_on_task) { 455 kern_return_t kret = ::task_set_state( 456 m_thread->Process()->Task().TaskPort(), __x86_64_DEBUG_STATE, 457 (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG); 458 if (kret != KERN_SUCCESS) 459 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::SetDBGState failed " 460 "to set debug control register state: " 461 "0x%8.8x.", 462 kret); 463 } 464 return m_state.GetError(e_regSetDBG, Write); 465 } 466 467 void DNBArchImplX86_64::ThreadWillResume() { 468 // Do we need to step this thread? If so, let the mach thread tell us so. 469 if (m_thread->IsStepping()) { 470 // This is the primary thread, let the arch do anything it needs 471 EnableHardwareSingleStep(true); 472 } 473 474 // Reset the debug status register, if necessary, before we resume. 475 kern_return_t kret = GetDBGState(false); 476 DNBLogThreadedIf( 477 LOG_WATCHPOINTS, 478 "DNBArchImplX86_64::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret); 479 if (kret != KERN_SUCCESS) 480 return; 481 482 DBG &debug_state = m_state.context.dbg; 483 bool need_reset = false; 484 uint32_t i, num = NumSupportedHardwareWatchpoints(); 485 for (i = 0; i < num; ++i) 486 if (IsWatchpointHit(debug_state, i)) 487 need_reset = true; 488 489 if (need_reset) { 490 ClearWatchpointHits(debug_state); 491 kret = SetDBGState(false); 492 DNBLogThreadedIf( 493 LOG_WATCHPOINTS, 494 "DNBArchImplX86_64::ThreadWillResume() SetDBGState() => 0x%8.8x.", 495 kret); 496 } 497 } 498 499 bool DNBArchImplX86_64::ThreadDidStop() { 500 bool success = true; 501 502 m_state.InvalidateAllRegisterStates(); 503 504 // Are we stepping a single instruction? 505 if (GetGPRState(true) == KERN_SUCCESS) { 506 // We are single stepping, was this the primary thread? 507 if (m_thread->IsStepping()) { 508 // This was the primary thread, we need to clear the trace 509 // bit if so. 510 success = EnableHardwareSingleStep(false) == KERN_SUCCESS; 511 } else { 512 // The MachThread will automatically restore the suspend count 513 // in ThreadDidStop(), so we don't need to do anything here if 514 // we weren't the primary thread the last time 515 } 516 } 517 return success; 518 } 519 520 bool DNBArchImplX86_64::NotifyException(MachException::Data &exc) { 521 switch (exc.exc_type) { 522 case EXC_BAD_ACCESS: 523 break; 524 case EXC_BAD_INSTRUCTION: 525 break; 526 case EXC_ARITHMETIC: 527 break; 528 case EXC_EMULATION: 529 break; 530 case EXC_SOFTWARE: 531 break; 532 case EXC_BREAKPOINT: 533 if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) { 534 // exc_code = EXC_I386_BPT 535 // 536 nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS); 537 if (pc != INVALID_NUB_ADDRESS && pc > 0) { 538 pc -= 1; 539 // Check for a breakpoint at one byte prior to the current PC value 540 // since the PC will be just past the trap. 541 542 DNBBreakpoint *bp = 543 m_thread->Process()->Breakpoints().FindByAddress(pc); 544 if (bp) { 545 // Backup the PC for i386 since the trap was taken and the PC 546 // is at the address following the single byte trap instruction. 547 if (m_state.context.gpr.__rip > 0) { 548 m_state.context.gpr.__rip = pc; 549 // Write the new PC back out 550 SetGPRState(); 551 } 552 } 553 return true; 554 } 555 } else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) { 556 // exc_code = EXC_I386_SGL 557 // 558 // Check whether this corresponds to a watchpoint hit event. 559 // If yes, set the exc_sub_code to the data break address. 560 nub_addr_t addr = 0; 561 uint32_t hw_index = GetHardwareWatchpointHit(addr); 562 if (hw_index != INVALID_NUB_HW_INDEX) { 563 exc.exc_data[1] = addr; 564 // Piggyback the hw_index in the exc.data. 565 exc.exc_data.push_back(hw_index); 566 } 567 568 return true; 569 } 570 break; 571 case EXC_SYSCALL: 572 break; 573 case EXC_MACH_SYSCALL: 574 break; 575 case EXC_RPC_ALERT: 576 break; 577 } 578 return false; 579 } 580 581 uint32_t DNBArchImplX86_64::NumSupportedHardwareWatchpoints() { 582 // Available debug address registers: dr0, dr1, dr2, dr3. 583 return 4; 584 } 585 586 static uint32_t size_and_rw_bits(nub_size_t size, bool read, bool write) { 587 uint32_t rw; 588 if (read) { 589 rw = 0x3; // READ or READ/WRITE 590 } else if (write) { 591 rw = 0x1; // WRITE 592 } else { 593 assert(0 && "read and write cannot both be false"); 594 } 595 596 switch (size) { 597 case 1: 598 return rw; 599 case 2: 600 return (0x1 << 2) | rw; 601 case 4: 602 return (0x3 << 2) | rw; 603 case 8: 604 return (0x2 << 2) | rw; 605 } 606 assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); 607 return 0; 608 } 609 void DNBArchImplX86_64::SetWatchpoint(DBG &debug_state, uint32_t hw_index, 610 nub_addr_t addr, nub_size_t size, 611 bool read, bool write) { 612 // Set both dr7 (debug control register) and dri (debug address register). 613 614 // dr7{7-0} encodes the local/gloabl enable bits: 615 // global enable --. .-- local enable 616 // | | 617 // v v 618 // dr0 -> bits{1-0} 619 // dr1 -> bits{3-2} 620 // dr2 -> bits{5-4} 621 // dr3 -> bits{7-6} 622 // 623 // dr7{31-16} encodes the rw/len bits: 624 // b_x+3, b_x+2, b_x+1, b_x 625 // where bits{x+1, x} => rw 626 // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io 627 // read-or-write (unused) 628 // and bits{x+3, x+2} => len 629 // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte 630 // 631 // dr0 -> bits{19-16} 632 // dr1 -> bits{23-20} 633 // dr2 -> bits{27-24} 634 // dr3 -> bits{31-28} 635 debug_state.__dr7 |= 636 (1 << (2 * hw_index) | 637 size_and_rw_bits(size, read, write) << (16 + 4 * hw_index)); 638 switch (hw_index) { 639 case 0: 640 debug_state.__dr0 = addr; 641 break; 642 case 1: 643 debug_state.__dr1 = addr; 644 break; 645 case 2: 646 debug_state.__dr2 = addr; 647 break; 648 case 3: 649 debug_state.__dr3 = addr; 650 break; 651 default: 652 assert(0 && 653 "invalid hardware register index, must be one of 0, 1, 2, or 3"); 654 } 655 return; 656 } 657 658 void DNBArchImplX86_64::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) { 659 debug_state.__dr7 &= ~(3 << (2 * hw_index)); 660 switch (hw_index) { 661 case 0: 662 debug_state.__dr0 = 0; 663 break; 664 case 1: 665 debug_state.__dr1 = 0; 666 break; 667 case 2: 668 debug_state.__dr2 = 0; 669 break; 670 case 3: 671 debug_state.__dr3 = 0; 672 break; 673 default: 674 assert(0 && 675 "invalid hardware register index, must be one of 0, 1, 2, or 3"); 676 } 677 return; 678 } 679 680 bool DNBArchImplX86_64::IsWatchpointVacant(const DBG &debug_state, 681 uint32_t hw_index) { 682 // Check dr7 (debug control register) for local/global enable bits: 683 // global enable --. .-- local enable 684 // | | 685 // v v 686 // dr0 -> bits{1-0} 687 // dr1 -> bits{3-2} 688 // dr2 -> bits{5-4} 689 // dr3 -> bits{7-6} 690 return (debug_state.__dr7 & (3 << (2 * hw_index))) == 0; 691 } 692 693 // Resets local copy of debug status register to wait for the next debug 694 // exception. 695 void DNBArchImplX86_64::ClearWatchpointHits(DBG &debug_state) { 696 // See also IsWatchpointHit(). 697 debug_state.__dr6 = 0; 698 return; 699 } 700 701 bool DNBArchImplX86_64::IsWatchpointHit(const DBG &debug_state, 702 uint32_t hw_index) { 703 // Check dr6 (debug status register) whether a watchpoint hits: 704 // is watchpoint hit? 705 // | 706 // v 707 // dr0 -> bits{0} 708 // dr1 -> bits{1} 709 // dr2 -> bits{2} 710 // dr3 -> bits{3} 711 return (debug_state.__dr6 & (1 << hw_index)); 712 } 713 714 nub_addr_t DNBArchImplX86_64::GetWatchAddress(const DBG &debug_state, 715 uint32_t hw_index) { 716 switch (hw_index) { 717 case 0: 718 return debug_state.__dr0; 719 case 1: 720 return debug_state.__dr1; 721 case 2: 722 return debug_state.__dr2; 723 case 3: 724 return debug_state.__dr3; 725 } 726 assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); 727 return 0; 728 } 729 730 bool DNBArchImplX86_64::StartTransForHWP() { 731 if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back) 732 DNBLogError("%s inconsistent state detected, expected %d or %d, got: %d", 733 __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state); 734 m_2pc_dbg_checkpoint = m_state.context.dbg; 735 m_2pc_trans_state = Trans_Pending; 736 return true; 737 } 738 bool DNBArchImplX86_64::RollbackTransForHWP() { 739 m_state.context.dbg = m_2pc_dbg_checkpoint; 740 if (m_2pc_trans_state != Trans_Pending) 741 DNBLogError("%s inconsistent state detected, expected %d, got: %d", 742 __FUNCTION__, Trans_Pending, m_2pc_trans_state); 743 m_2pc_trans_state = Trans_Rolled_Back; 744 kern_return_t kret = SetDBGState(false); 745 DNBLogThreadedIf( 746 LOG_WATCHPOINTS, 747 "DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", 748 kret); 749 750 if (kret == KERN_SUCCESS) 751 return true; 752 else 753 return false; 754 } 755 bool DNBArchImplX86_64::FinishTransForHWP() { 756 m_2pc_trans_state = Trans_Done; 757 return true; 758 } 759 DNBArchImplX86_64::DBG DNBArchImplX86_64::GetDBGCheckpoint() { 760 return m_2pc_dbg_checkpoint; 761 } 762 763 uint32_t DNBArchImplX86_64::EnableHardwareWatchpoint(nub_addr_t addr, 764 nub_size_t size, bool read, 765 bool write, 766 bool also_set_on_task) { 767 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::" 768 "EnableHardwareWatchpoint(addr = 0x%llx, " 769 "size = %llu, read = %u, write = %u)", 770 (uint64_t)addr, (uint64_t)size, read, write); 771 772 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); 773 774 // Can only watch 1, 2, 4, or 8 bytes. 775 if (!(size == 1 || size == 2 || size == 4 || size == 8)) 776 return INVALID_NUB_HW_INDEX; 777 778 // We must watch for either read or write 779 if (read == false && write == false) 780 return INVALID_NUB_HW_INDEX; 781 782 // Read the debug state 783 kern_return_t kret = GetDBGState(false); 784 785 if (kret == KERN_SUCCESS) { 786 // Check to make sure we have the needed hardware support 787 uint32_t i = 0; 788 789 DBG &debug_state = m_state.context.dbg; 790 for (i = 0; i < num_hw_watchpoints; ++i) { 791 if (IsWatchpointVacant(debug_state, i)) 792 break; 793 } 794 795 // See if we found an available hw breakpoint slot above 796 if (i < num_hw_watchpoints) { 797 StartTransForHWP(); 798 799 // Modify our local copy of the debug state, first. 800 SetWatchpoint(debug_state, i, addr, size, read, write); 801 // Now set the watch point in the inferior. 802 kret = SetDBGState(also_set_on_task); 803 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::" 804 "EnableHardwareWatchpoint() " 805 "SetDBGState() => 0x%8.8x.", 806 kret); 807 808 if (kret == KERN_SUCCESS) 809 return i; 810 else // Revert to the previous debug state voluntarily. The transaction 811 // coordinator knows that we have failed. 812 m_state.context.dbg = GetDBGCheckpoint(); 813 } else { 814 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::" 815 "EnableHardwareWatchpoint(): All " 816 "hardware resources (%u) are in use.", 817 num_hw_watchpoints); 818 } 819 } 820 return INVALID_NUB_HW_INDEX; 821 } 822 823 bool DNBArchImplX86_64::DisableHardwareWatchpoint(uint32_t hw_index, 824 bool also_set_on_task) { 825 kern_return_t kret = GetDBGState(false); 826 827 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); 828 if (kret == KERN_SUCCESS) { 829 DBG &debug_state = m_state.context.dbg; 830 if (hw_index < num_hw_points && 831 !IsWatchpointVacant(debug_state, hw_index)) { 832 StartTransForHWP(); 833 834 // Modify our local copy of the debug state, first. 835 ClearWatchpoint(debug_state, hw_index); 836 // Now disable the watch point in the inferior. 837 kret = SetDBGState(also_set_on_task); 838 DNBLogThreadedIf(LOG_WATCHPOINTS, 839 "DNBArchImplX86_64::DisableHardwareWatchpoint( %u )", 840 hw_index); 841 842 if (kret == KERN_SUCCESS) 843 return true; 844 else // Revert to the previous debug state voluntarily. The transaction 845 // coordinator knows that we have failed. 846 m_state.context.dbg = GetDBGCheckpoint(); 847 } 848 } 849 return false; 850 } 851 852 // Iterate through the debug status register; return the index of the first hit. 853 uint32_t DNBArchImplX86_64::GetHardwareWatchpointHit(nub_addr_t &addr) { 854 // Read the debug state 855 kern_return_t kret = GetDBGState(true); 856 DNBLogThreadedIf( 857 LOG_WATCHPOINTS, 858 "DNBArchImplX86_64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", 859 kret); 860 if (kret == KERN_SUCCESS) { 861 DBG &debug_state = m_state.context.dbg; 862 uint32_t i, num = NumSupportedHardwareWatchpoints(); 863 for (i = 0; i < num; ++i) { 864 if (IsWatchpointHit(debug_state, i)) { 865 addr = GetWatchAddress(debug_state, i); 866 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::" 867 "GetHardwareWatchpointHit() found => " 868 "%u (addr = 0x%llx).", 869 i, (uint64_t)addr); 870 return i; 871 } 872 } 873 } 874 return INVALID_NUB_HW_INDEX; 875 } 876 877 // Set the single step bit in the processor status register. 878 kern_return_t DNBArchImplX86_64::EnableHardwareSingleStep(bool enable) { 879 if (GetGPRState(false) == KERN_SUCCESS) { 880 const uint32_t trace_bit = 0x100u; 881 if (enable) 882 m_state.context.gpr.__rflags |= trace_bit; 883 else 884 m_state.context.gpr.__rflags &= ~trace_bit; 885 return SetGPRState(); 886 } 887 return m_state.GetError(e_regSetGPR, Read); 888 } 889 890 //---------------------------------------------------------------------- 891 // Register information definitions 892 //---------------------------------------------------------------------- 893 894 enum { 895 gpr_rax = 0, 896 gpr_rbx, 897 gpr_rcx, 898 gpr_rdx, 899 gpr_rdi, 900 gpr_rsi, 901 gpr_rbp, 902 gpr_rsp, 903 gpr_r8, 904 gpr_r9, 905 gpr_r10, 906 gpr_r11, 907 gpr_r12, 908 gpr_r13, 909 gpr_r14, 910 gpr_r15, 911 gpr_rip, 912 gpr_rflags, 913 gpr_cs, 914 gpr_fs, 915 gpr_gs, 916 gpr_eax, 917 gpr_ebx, 918 gpr_ecx, 919 gpr_edx, 920 gpr_edi, 921 gpr_esi, 922 gpr_ebp, 923 gpr_esp, 924 gpr_r8d, // Low 32 bits or r8 925 gpr_r9d, // Low 32 bits or r9 926 gpr_r10d, // Low 32 bits or r10 927 gpr_r11d, // Low 32 bits or r11 928 gpr_r12d, // Low 32 bits or r12 929 gpr_r13d, // Low 32 bits or r13 930 gpr_r14d, // Low 32 bits or r14 931 gpr_r15d, // Low 32 bits or r15 932 gpr_ax, 933 gpr_bx, 934 gpr_cx, 935 gpr_dx, 936 gpr_di, 937 gpr_si, 938 gpr_bp, 939 gpr_sp, 940 gpr_r8w, // Low 16 bits or r8 941 gpr_r9w, // Low 16 bits or r9 942 gpr_r10w, // Low 16 bits or r10 943 gpr_r11w, // Low 16 bits or r11 944 gpr_r12w, // Low 16 bits or r12 945 gpr_r13w, // Low 16 bits or r13 946 gpr_r14w, // Low 16 bits or r14 947 gpr_r15w, // Low 16 bits or r15 948 gpr_ah, 949 gpr_bh, 950 gpr_ch, 951 gpr_dh, 952 gpr_al, 953 gpr_bl, 954 gpr_cl, 955 gpr_dl, 956 gpr_dil, 957 gpr_sil, 958 gpr_bpl, 959 gpr_spl, 960 gpr_r8l, // Low 8 bits or r8 961 gpr_r9l, // Low 8 bits or r9 962 gpr_r10l, // Low 8 bits or r10 963 gpr_r11l, // Low 8 bits or r11 964 gpr_r12l, // Low 8 bits or r12 965 gpr_r13l, // Low 8 bits or r13 966 gpr_r14l, // Low 8 bits or r14 967 gpr_r15l, // Low 8 bits or r15 968 k_num_gpr_regs 969 }; 970 971 enum { 972 fpu_fcw, 973 fpu_fsw, 974 fpu_ftw, 975 fpu_fop, 976 fpu_ip, 977 fpu_cs, 978 fpu_dp, 979 fpu_ds, 980 fpu_mxcsr, 981 fpu_mxcsrmask, 982 fpu_stmm0, 983 fpu_stmm1, 984 fpu_stmm2, 985 fpu_stmm3, 986 fpu_stmm4, 987 fpu_stmm5, 988 fpu_stmm6, 989 fpu_stmm7, 990 fpu_xmm0, 991 fpu_xmm1, 992 fpu_xmm2, 993 fpu_xmm3, 994 fpu_xmm4, 995 fpu_xmm5, 996 fpu_xmm6, 997 fpu_xmm7, 998 fpu_xmm8, 999 fpu_xmm9, 1000 fpu_xmm10, 1001 fpu_xmm11, 1002 fpu_xmm12, 1003 fpu_xmm13, 1004 fpu_xmm14, 1005 fpu_xmm15, 1006 fpu_ymm0, 1007 fpu_ymm1, 1008 fpu_ymm2, 1009 fpu_ymm3, 1010 fpu_ymm4, 1011 fpu_ymm5, 1012 fpu_ymm6, 1013 fpu_ymm7, 1014 fpu_ymm8, 1015 fpu_ymm9, 1016 fpu_ymm10, 1017 fpu_ymm11, 1018 fpu_ymm12, 1019 fpu_ymm13, 1020 fpu_ymm14, 1021 fpu_ymm15, 1022 k_num_fpu_regs, 1023 1024 // Aliases 1025 fpu_fctrl = fpu_fcw, 1026 fpu_fstat = fpu_fsw, 1027 fpu_ftag = fpu_ftw, 1028 fpu_fiseg = fpu_cs, 1029 fpu_fioff = fpu_ip, 1030 fpu_foseg = fpu_ds, 1031 fpu_fooff = fpu_dp 1032 }; 1033 1034 enum { 1035 exc_trapno, 1036 exc_err, 1037 exc_faultvaddr, 1038 k_num_exc_regs, 1039 }; 1040 1041 enum ehframe_dwarf_regnums { 1042 ehframe_dwarf_rax = 0, 1043 ehframe_dwarf_rdx = 1, 1044 ehframe_dwarf_rcx = 2, 1045 ehframe_dwarf_rbx = 3, 1046 ehframe_dwarf_rsi = 4, 1047 ehframe_dwarf_rdi = 5, 1048 ehframe_dwarf_rbp = 6, 1049 ehframe_dwarf_rsp = 7, 1050 ehframe_dwarf_r8, 1051 ehframe_dwarf_r9, 1052 ehframe_dwarf_r10, 1053 ehframe_dwarf_r11, 1054 ehframe_dwarf_r12, 1055 ehframe_dwarf_r13, 1056 ehframe_dwarf_r14, 1057 ehframe_dwarf_r15, 1058 ehframe_dwarf_rip, 1059 ehframe_dwarf_xmm0, 1060 ehframe_dwarf_xmm1, 1061 ehframe_dwarf_xmm2, 1062 ehframe_dwarf_xmm3, 1063 ehframe_dwarf_xmm4, 1064 ehframe_dwarf_xmm5, 1065 ehframe_dwarf_xmm6, 1066 ehframe_dwarf_xmm7, 1067 ehframe_dwarf_xmm8, 1068 ehframe_dwarf_xmm9, 1069 ehframe_dwarf_xmm10, 1070 ehframe_dwarf_xmm11, 1071 ehframe_dwarf_xmm12, 1072 ehframe_dwarf_xmm13, 1073 ehframe_dwarf_xmm14, 1074 ehframe_dwarf_xmm15, 1075 ehframe_dwarf_stmm0, 1076 ehframe_dwarf_stmm1, 1077 ehframe_dwarf_stmm2, 1078 ehframe_dwarf_stmm3, 1079 ehframe_dwarf_stmm4, 1080 ehframe_dwarf_stmm5, 1081 ehframe_dwarf_stmm6, 1082 ehframe_dwarf_stmm7, 1083 ehframe_dwarf_ymm0 = ehframe_dwarf_xmm0, 1084 ehframe_dwarf_ymm1 = ehframe_dwarf_xmm1, 1085 ehframe_dwarf_ymm2 = ehframe_dwarf_xmm2, 1086 ehframe_dwarf_ymm3 = ehframe_dwarf_xmm3, 1087 ehframe_dwarf_ymm4 = ehframe_dwarf_xmm4, 1088 ehframe_dwarf_ymm5 = ehframe_dwarf_xmm5, 1089 ehframe_dwarf_ymm6 = ehframe_dwarf_xmm6, 1090 ehframe_dwarf_ymm7 = ehframe_dwarf_xmm7, 1091 ehframe_dwarf_ymm8 = ehframe_dwarf_xmm8, 1092 ehframe_dwarf_ymm9 = ehframe_dwarf_xmm9, 1093 ehframe_dwarf_ymm10 = ehframe_dwarf_xmm10, 1094 ehframe_dwarf_ymm11 = ehframe_dwarf_xmm11, 1095 ehframe_dwarf_ymm12 = ehframe_dwarf_xmm12, 1096 ehframe_dwarf_ymm13 = ehframe_dwarf_xmm13, 1097 ehframe_dwarf_ymm14 = ehframe_dwarf_xmm14, 1098 ehframe_dwarf_ymm15 = ehframe_dwarf_xmm15 1099 }; 1100 1101 enum debugserver_regnums { 1102 debugserver_rax = 0, 1103 debugserver_rbx = 1, 1104 debugserver_rcx = 2, 1105 debugserver_rdx = 3, 1106 debugserver_rsi = 4, 1107 debugserver_rdi = 5, 1108 debugserver_rbp = 6, 1109 debugserver_rsp = 7, 1110 debugserver_r8 = 8, 1111 debugserver_r9 = 9, 1112 debugserver_r10 = 10, 1113 debugserver_r11 = 11, 1114 debugserver_r12 = 12, 1115 debugserver_r13 = 13, 1116 debugserver_r14 = 14, 1117 debugserver_r15 = 15, 1118 debugserver_rip = 16, 1119 debugserver_rflags = 17, 1120 debugserver_cs = 18, 1121 debugserver_ss = 19, 1122 debugserver_ds = 20, 1123 debugserver_es = 21, 1124 debugserver_fs = 22, 1125 debugserver_gs = 23, 1126 debugserver_stmm0 = 24, 1127 debugserver_stmm1 = 25, 1128 debugserver_stmm2 = 26, 1129 debugserver_stmm3 = 27, 1130 debugserver_stmm4 = 28, 1131 debugserver_stmm5 = 29, 1132 debugserver_stmm6 = 30, 1133 debugserver_stmm7 = 31, 1134 debugserver_fctrl = 32, 1135 debugserver_fcw = debugserver_fctrl, 1136 debugserver_fstat = 33, 1137 debugserver_fsw = debugserver_fstat, 1138 debugserver_ftag = 34, 1139 debugserver_ftw = debugserver_ftag, 1140 debugserver_fiseg = 35, 1141 debugserver_fpu_cs = debugserver_fiseg, 1142 debugserver_fioff = 36, 1143 debugserver_ip = debugserver_fioff, 1144 debugserver_foseg = 37, 1145 debugserver_fpu_ds = debugserver_foseg, 1146 debugserver_fooff = 38, 1147 debugserver_dp = debugserver_fooff, 1148 debugserver_fop = 39, 1149 debugserver_xmm0 = 40, 1150 debugserver_xmm1 = 41, 1151 debugserver_xmm2 = 42, 1152 debugserver_xmm3 = 43, 1153 debugserver_xmm4 = 44, 1154 debugserver_xmm5 = 45, 1155 debugserver_xmm6 = 46, 1156 debugserver_xmm7 = 47, 1157 debugserver_xmm8 = 48, 1158 debugserver_xmm9 = 49, 1159 debugserver_xmm10 = 50, 1160 debugserver_xmm11 = 51, 1161 debugserver_xmm12 = 52, 1162 debugserver_xmm13 = 53, 1163 debugserver_xmm14 = 54, 1164 debugserver_xmm15 = 55, 1165 debugserver_mxcsr = 56, 1166 debugserver_ymm0 = debugserver_xmm0, 1167 debugserver_ymm1 = debugserver_xmm1, 1168 debugserver_ymm2 = debugserver_xmm2, 1169 debugserver_ymm3 = debugserver_xmm3, 1170 debugserver_ymm4 = debugserver_xmm4, 1171 debugserver_ymm5 = debugserver_xmm5, 1172 debugserver_ymm6 = debugserver_xmm6, 1173 debugserver_ymm7 = debugserver_xmm7, 1174 debugserver_ymm8 = debugserver_xmm8, 1175 debugserver_ymm9 = debugserver_xmm9, 1176 debugserver_ymm10 = debugserver_xmm10, 1177 debugserver_ymm11 = debugserver_xmm11, 1178 debugserver_ymm12 = debugserver_xmm12, 1179 debugserver_ymm13 = debugserver_xmm13, 1180 debugserver_ymm14 = debugserver_xmm14, 1181 debugserver_ymm15 = debugserver_xmm15 1182 }; 1183 1184 #define GPR_OFFSET(reg) (offsetof(DNBArchImplX86_64::GPR, __##reg)) 1185 #define FPU_OFFSET(reg) \ 1186 (offsetof(DNBArchImplX86_64::FPU, __fpu_##reg) + \ 1187 offsetof(DNBArchImplX86_64::Context, fpu.no_avx)) 1188 #define AVX_OFFSET(reg) \ 1189 (offsetof(DNBArchImplX86_64::AVX, __fpu_##reg) + \ 1190 offsetof(DNBArchImplX86_64::Context, fpu.avx)) 1191 #define EXC_OFFSET(reg) \ 1192 (offsetof(DNBArchImplX86_64::EXC, __##reg) + \ 1193 offsetof(DNBArchImplX86_64::Context, exc)) 1194 #define AVX_OFFSET_YMM(n) (AVX_OFFSET(ymmh0) + (32 * n)) 1195 1196 #define GPR_SIZE(reg) (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg)) 1197 #define FPU_SIZE_UINT(reg) \ 1198 (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg)) 1199 #define FPU_SIZE_MMST(reg) \ 1200 (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg)) 1201 #define FPU_SIZE_XMM(reg) \ 1202 (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg)) 1203 #define FPU_SIZE_YMM(reg) (32) 1204 #define EXC_SIZE(reg) (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg)) 1205 1206 // These macros will auto define the register name, alt name, register size, 1207 // register offset, encoding, format and native register. This ensures that 1208 // the register state structures are defined correctly and have the correct 1209 // sizes and offsets. 1210 #define DEFINE_GPR(reg) \ 1211 { \ 1212 e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, GPR_SIZE(reg), \ 1213 GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, \ 1214 INVALID_NUB_REGNUM, debugserver_##reg, NULL, g_invalidate_##reg \ 1215 } 1216 #define DEFINE_GPR_ALT(reg, alt, gen) \ 1217 { \ 1218 e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ 1219 GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, \ 1220 debugserver_##reg, NULL, g_invalidate_##reg \ 1221 } 1222 #define DEFINE_GPR_ALT2(reg, alt) \ 1223 { \ 1224 e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ 1225 GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ 1226 INVALID_NUB_REGNUM, debugserver_##reg, NULL, NULL \ 1227 } 1228 #define DEFINE_GPR_ALT3(reg, alt, gen) \ 1229 { \ 1230 e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ 1231 GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gen, \ 1232 debugserver_##reg, NULL, NULL \ 1233 } 1234 #define DEFINE_GPR_ALT4(reg, alt, gen) \ 1235 { \ 1236 e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), \ 1237 GPR_OFFSET(reg), ehframe_dwarf_##reg, ehframe_dwarf_##reg, gen, \ 1238 debugserver_##reg, NULL, NULL \ 1239 } 1240 1241 #define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ 1242 { \ 1243 e_regSetGPR, gpr_##reg32, #reg32, NULL, Uint, Hex, 4, 0, \ 1244 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ 1245 INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 \ 1246 } 1247 #define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ 1248 { \ 1249 e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0, \ 1250 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ 1251 INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 \ 1252 } 1253 #define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ 1254 { \ 1255 e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 1, INVALID_NUB_REGNUM, \ 1256 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ 1257 g_contained_##reg64, g_invalidate_##reg64 \ 1258 } 1259 #define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ 1260 { \ 1261 e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 0, INVALID_NUB_REGNUM, \ 1262 INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, \ 1263 g_contained_##reg64, g_invalidate_##reg64 \ 1264 } 1265 1266 // General purpose registers for 64 bit 1267 1268 const char *g_contained_rax[] = {"rax", NULL}; 1269 const char *g_contained_rbx[] = {"rbx", NULL}; 1270 const char *g_contained_rcx[] = {"rcx", NULL}; 1271 const char *g_contained_rdx[] = {"rdx", NULL}; 1272 const char *g_contained_rdi[] = {"rdi", NULL}; 1273 const char *g_contained_rsi[] = {"rsi", NULL}; 1274 const char *g_contained_rbp[] = {"rbp", NULL}; 1275 const char *g_contained_rsp[] = {"rsp", NULL}; 1276 const char *g_contained_r8[] = {"r8", NULL}; 1277 const char *g_contained_r9[] = {"r9", NULL}; 1278 const char *g_contained_r10[] = {"r10", NULL}; 1279 const char *g_contained_r11[] = {"r11", NULL}; 1280 const char *g_contained_r12[] = {"r12", NULL}; 1281 const char *g_contained_r13[] = {"r13", NULL}; 1282 const char *g_contained_r14[] = {"r14", NULL}; 1283 const char *g_contained_r15[] = {"r15", NULL}; 1284 1285 const char *g_invalidate_rax[] = {"rax", "eax", "ax", "ah", "al", NULL}; 1286 const char *g_invalidate_rbx[] = {"rbx", "ebx", "bx", "bh", "bl", NULL}; 1287 const char *g_invalidate_rcx[] = {"rcx", "ecx", "cx", "ch", "cl", NULL}; 1288 const char *g_invalidate_rdx[] = {"rdx", "edx", "dx", "dh", "dl", NULL}; 1289 const char *g_invalidate_rdi[] = {"rdi", "edi", "di", "dil", NULL}; 1290 const char *g_invalidate_rsi[] = {"rsi", "esi", "si", "sil", NULL}; 1291 const char *g_invalidate_rbp[] = {"rbp", "ebp", "bp", "bpl", NULL}; 1292 const char *g_invalidate_rsp[] = {"rsp", "esp", "sp", "spl", NULL}; 1293 const char *g_invalidate_r8[] = {"r8", "r8d", "r8w", "r8l", NULL}; 1294 const char *g_invalidate_r9[] = {"r9", "r9d", "r9w", "r9l", NULL}; 1295 const char *g_invalidate_r10[] = {"r10", "r10d", "r10w", "r10l", NULL}; 1296 const char *g_invalidate_r11[] = {"r11", "r11d", "r11w", "r11l", NULL}; 1297 const char *g_invalidate_r12[] = {"r12", "r12d", "r12w", "r12l", NULL}; 1298 const char *g_invalidate_r13[] = {"r13", "r13d", "r13w", "r13l", NULL}; 1299 const char *g_invalidate_r14[] = {"r14", "r14d", "r14w", "r14l", NULL}; 1300 const char *g_invalidate_r15[] = {"r15", "r15d", "r15w", "r15l", NULL}; 1301 1302 const DNBRegisterInfo DNBArchImplX86_64::g_gpr_registers[] = { 1303 DEFINE_GPR(rax), 1304 DEFINE_GPR(rbx), 1305 DEFINE_GPR_ALT(rcx, "arg4", GENERIC_REGNUM_ARG4), 1306 DEFINE_GPR_ALT(rdx, "arg3", GENERIC_REGNUM_ARG3), 1307 DEFINE_GPR_ALT(rdi, "arg1", GENERIC_REGNUM_ARG1), 1308 DEFINE_GPR_ALT(rsi, "arg2", GENERIC_REGNUM_ARG2), 1309 DEFINE_GPR_ALT(rbp, "fp", GENERIC_REGNUM_FP), 1310 DEFINE_GPR_ALT(rsp, "sp", GENERIC_REGNUM_SP), 1311 DEFINE_GPR_ALT(r8, "arg5", GENERIC_REGNUM_ARG5), 1312 DEFINE_GPR_ALT(r9, "arg6", GENERIC_REGNUM_ARG6), 1313 DEFINE_GPR(r10), 1314 DEFINE_GPR(r11), 1315 DEFINE_GPR(r12), 1316 DEFINE_GPR(r13), 1317 DEFINE_GPR(r14), 1318 DEFINE_GPR(r15), 1319 DEFINE_GPR_ALT4(rip, "pc", GENERIC_REGNUM_PC), 1320 DEFINE_GPR_ALT3(rflags, "flags", GENERIC_REGNUM_FLAGS), 1321 DEFINE_GPR_ALT2(cs, NULL), 1322 DEFINE_GPR_ALT2(fs, NULL), 1323 DEFINE_GPR_ALT2(gs, NULL), 1324 DEFINE_GPR_PSEUDO_32(eax, rax), 1325 DEFINE_GPR_PSEUDO_32(ebx, rbx), 1326 DEFINE_GPR_PSEUDO_32(ecx, rcx), 1327 DEFINE_GPR_PSEUDO_32(edx, rdx), 1328 DEFINE_GPR_PSEUDO_32(edi, rdi), 1329 DEFINE_GPR_PSEUDO_32(esi, rsi), 1330 DEFINE_GPR_PSEUDO_32(ebp, rbp), 1331 DEFINE_GPR_PSEUDO_32(esp, rsp), 1332 DEFINE_GPR_PSEUDO_32(r8d, r8), 1333 DEFINE_GPR_PSEUDO_32(r9d, r9), 1334 DEFINE_GPR_PSEUDO_32(r10d, r10), 1335 DEFINE_GPR_PSEUDO_32(r11d, r11), 1336 DEFINE_GPR_PSEUDO_32(r12d, r12), 1337 DEFINE_GPR_PSEUDO_32(r13d, r13), 1338 DEFINE_GPR_PSEUDO_32(r14d, r14), 1339 DEFINE_GPR_PSEUDO_32(r15d, r15), 1340 DEFINE_GPR_PSEUDO_16(ax, rax), 1341 DEFINE_GPR_PSEUDO_16(bx, rbx), 1342 DEFINE_GPR_PSEUDO_16(cx, rcx), 1343 DEFINE_GPR_PSEUDO_16(dx, rdx), 1344 DEFINE_GPR_PSEUDO_16(di, rdi), 1345 DEFINE_GPR_PSEUDO_16(si, rsi), 1346 DEFINE_GPR_PSEUDO_16(bp, rbp), 1347 DEFINE_GPR_PSEUDO_16(sp, rsp), 1348 DEFINE_GPR_PSEUDO_16(r8w, r8), 1349 DEFINE_GPR_PSEUDO_16(r9w, r9), 1350 DEFINE_GPR_PSEUDO_16(r10w, r10), 1351 DEFINE_GPR_PSEUDO_16(r11w, r11), 1352 DEFINE_GPR_PSEUDO_16(r12w, r12), 1353 DEFINE_GPR_PSEUDO_16(r13w, r13), 1354 DEFINE_GPR_PSEUDO_16(r14w, r14), 1355 DEFINE_GPR_PSEUDO_16(r15w, r15), 1356 DEFINE_GPR_PSEUDO_8H(ah, rax), 1357 DEFINE_GPR_PSEUDO_8H(bh, rbx), 1358 DEFINE_GPR_PSEUDO_8H(ch, rcx), 1359 DEFINE_GPR_PSEUDO_8H(dh, rdx), 1360 DEFINE_GPR_PSEUDO_8L(al, rax), 1361 DEFINE_GPR_PSEUDO_8L(bl, rbx), 1362 DEFINE_GPR_PSEUDO_8L(cl, rcx), 1363 DEFINE_GPR_PSEUDO_8L(dl, rdx), 1364 DEFINE_GPR_PSEUDO_8L(dil, rdi), 1365 DEFINE_GPR_PSEUDO_8L(sil, rsi), 1366 DEFINE_GPR_PSEUDO_8L(bpl, rbp), 1367 DEFINE_GPR_PSEUDO_8L(spl, rsp), 1368 DEFINE_GPR_PSEUDO_8L(r8l, r8), 1369 DEFINE_GPR_PSEUDO_8L(r9l, r9), 1370 DEFINE_GPR_PSEUDO_8L(r10l, r10), 1371 DEFINE_GPR_PSEUDO_8L(r11l, r11), 1372 DEFINE_GPR_PSEUDO_8L(r12l, r12), 1373 DEFINE_GPR_PSEUDO_8L(r13l, r13), 1374 DEFINE_GPR_PSEUDO_8L(r14l, r14), 1375 DEFINE_GPR_PSEUDO_8L(r15l, r15)}; 1376 1377 // Floating point registers 64 bit 1378 const DNBRegisterInfo DNBArchImplX86_64::g_fpu_registers_no_avx[] = { 1379 {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), 1380 FPU_OFFSET(fcw), -1U, -1U, -1U, -1U, NULL, NULL}, 1381 {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), 1382 FPU_OFFSET(fsw), -1U, -1U, -1U, -1U, NULL, NULL}, 1383 {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */, 1384 FPU_OFFSET(ftw), -1U, -1U, -1U, -1U, NULL, NULL}, 1385 {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), 1386 FPU_OFFSET(fop), -1U, -1U, -1U, -1U, NULL, NULL}, 1387 {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), 1388 FPU_OFFSET(ip), -1U, -1U, -1U, -1U, NULL, NULL}, 1389 {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), 1390 FPU_OFFSET(cs), -1U, -1U, -1U, -1U, NULL, NULL}, 1391 {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), 1392 FPU_OFFSET(dp), -1U, -1U, -1U, -1U, NULL, NULL}, 1393 {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), 1394 FPU_OFFSET(ds), -1U, -1U, -1U, -1U, NULL, NULL}, 1395 {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), 1396 FPU_OFFSET(mxcsr), -1U, -1U, -1U, -1U, NULL, NULL}, 1397 {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, 1398 FPU_SIZE_UINT(mxcsrmask), FPU_OFFSET(mxcsrmask), -1U, -1U, -1U, -1U, NULL, 1399 NULL}, 1400 1401 {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, 1402 FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), ehframe_dwarf_stmm0, 1403 ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL}, 1404 {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, 1405 FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), ehframe_dwarf_stmm1, 1406 ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL}, 1407 {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, 1408 FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), ehframe_dwarf_stmm2, 1409 ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL}, 1410 {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, 1411 FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), ehframe_dwarf_stmm3, 1412 ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL}, 1413 {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, 1414 FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), ehframe_dwarf_stmm4, 1415 ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL}, 1416 {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, 1417 FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), ehframe_dwarf_stmm5, 1418 ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL}, 1419 {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, 1420 FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), ehframe_dwarf_stmm6, 1421 ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL}, 1422 {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, 1423 FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), ehframe_dwarf_stmm7, 1424 ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL}, 1425 1426 {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, 1427 FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), ehframe_dwarf_xmm0, 1428 ehframe_dwarf_xmm0, -1U, debugserver_xmm0, NULL, NULL}, 1429 {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, 1430 FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), ehframe_dwarf_xmm1, 1431 ehframe_dwarf_xmm1, -1U, debugserver_xmm1, NULL, NULL}, 1432 {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, 1433 FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), ehframe_dwarf_xmm2, 1434 ehframe_dwarf_xmm2, -1U, debugserver_xmm2, NULL, NULL}, 1435 {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, 1436 FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), ehframe_dwarf_xmm3, 1437 ehframe_dwarf_xmm3, -1U, debugserver_xmm3, NULL, NULL}, 1438 {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, 1439 FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), ehframe_dwarf_xmm4, 1440 ehframe_dwarf_xmm4, -1U, debugserver_xmm4, NULL, NULL}, 1441 {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, 1442 FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), ehframe_dwarf_xmm5, 1443 ehframe_dwarf_xmm5, -1U, debugserver_xmm5, NULL, NULL}, 1444 {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, 1445 FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), ehframe_dwarf_xmm6, 1446 ehframe_dwarf_xmm6, -1U, debugserver_xmm6, NULL, NULL}, 1447 {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, 1448 FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), ehframe_dwarf_xmm7, 1449 ehframe_dwarf_xmm7, -1U, debugserver_xmm7, NULL, NULL}, 1450 {e_regSetFPU, fpu_xmm8, "xmm8", NULL, Vector, VectorOfUInt8, 1451 FPU_SIZE_XMM(xmm8), FPU_OFFSET(xmm8), ehframe_dwarf_xmm8, 1452 ehframe_dwarf_xmm8, -1U, debugserver_xmm8, NULL, NULL}, 1453 {e_regSetFPU, fpu_xmm9, "xmm9", NULL, Vector, VectorOfUInt8, 1454 FPU_SIZE_XMM(xmm9), FPU_OFFSET(xmm9), ehframe_dwarf_xmm9, 1455 ehframe_dwarf_xmm9, -1U, debugserver_xmm9, NULL, NULL}, 1456 {e_regSetFPU, fpu_xmm10, "xmm10", NULL, Vector, VectorOfUInt8, 1457 FPU_SIZE_XMM(xmm10), FPU_OFFSET(xmm10), ehframe_dwarf_xmm10, 1458 ehframe_dwarf_xmm10, -1U, debugserver_xmm10, NULL, NULL}, 1459 {e_regSetFPU, fpu_xmm11, "xmm11", NULL, Vector, VectorOfUInt8, 1460 FPU_SIZE_XMM(xmm11), FPU_OFFSET(xmm11), ehframe_dwarf_xmm11, 1461 ehframe_dwarf_xmm11, -1U, debugserver_xmm11, NULL, NULL}, 1462 {e_regSetFPU, fpu_xmm12, "xmm12", NULL, Vector, VectorOfUInt8, 1463 FPU_SIZE_XMM(xmm12), FPU_OFFSET(xmm12), ehframe_dwarf_xmm12, 1464 ehframe_dwarf_xmm12, -1U, debugserver_xmm12, NULL, NULL}, 1465 {e_regSetFPU, fpu_xmm13, "xmm13", NULL, Vector, VectorOfUInt8, 1466 FPU_SIZE_XMM(xmm13), FPU_OFFSET(xmm13), ehframe_dwarf_xmm13, 1467 ehframe_dwarf_xmm13, -1U, debugserver_xmm13, NULL, NULL}, 1468 {e_regSetFPU, fpu_xmm14, "xmm14", NULL, Vector, VectorOfUInt8, 1469 FPU_SIZE_XMM(xmm14), FPU_OFFSET(xmm14), ehframe_dwarf_xmm14, 1470 ehframe_dwarf_xmm14, -1U, debugserver_xmm14, NULL, NULL}, 1471 {e_regSetFPU, fpu_xmm15, "xmm15", NULL, Vector, VectorOfUInt8, 1472 FPU_SIZE_XMM(xmm15), FPU_OFFSET(xmm15), ehframe_dwarf_xmm15, 1473 ehframe_dwarf_xmm15, -1U, debugserver_xmm15, NULL, NULL}, 1474 }; 1475 1476 static const char *g_contained_ymm0[] = {"ymm0", NULL}; 1477 static const char *g_contained_ymm1[] = {"ymm1", NULL}; 1478 static const char *g_contained_ymm2[] = {"ymm2", NULL}; 1479 static const char *g_contained_ymm3[] = {"ymm3", NULL}; 1480 static const char *g_contained_ymm4[] = {"ymm4", NULL}; 1481 static const char *g_contained_ymm5[] = {"ymm5", NULL}; 1482 static const char *g_contained_ymm6[] = {"ymm6", NULL}; 1483 static const char *g_contained_ymm7[] = {"ymm7", NULL}; 1484 static const char *g_contained_ymm8[] = {"ymm8", NULL}; 1485 static const char *g_contained_ymm9[] = {"ymm9", NULL}; 1486 static const char *g_contained_ymm10[] = {"ymm10", NULL}; 1487 static const char *g_contained_ymm11[] = {"ymm11", NULL}; 1488 static const char *g_contained_ymm12[] = {"ymm12", NULL}; 1489 static const char *g_contained_ymm13[] = {"ymm13", NULL}; 1490 static const char *g_contained_ymm14[] = {"ymm14", NULL}; 1491 static const char *g_contained_ymm15[] = {"ymm15", NULL}; 1492 1493 const DNBRegisterInfo DNBArchImplX86_64::g_fpu_registers_avx[] = { 1494 {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw), 1495 AVX_OFFSET(fcw), -1U, -1U, -1U, -1U, NULL, NULL}, 1496 {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw), 1497 AVX_OFFSET(fsw), -1U, -1U, -1U, -1U, NULL, NULL}, 1498 {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */, 1499 AVX_OFFSET(ftw), -1U, -1U, -1U, -1U, NULL, NULL}, 1500 {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop), 1501 AVX_OFFSET(fop), -1U, -1U, -1U, -1U, NULL, NULL}, 1502 {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip), 1503 AVX_OFFSET(ip), -1U, -1U, -1U, -1U, NULL, NULL}, 1504 {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs), 1505 AVX_OFFSET(cs), -1U, -1U, -1U, -1U, NULL, NULL}, 1506 {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp), 1507 AVX_OFFSET(dp), -1U, -1U, -1U, -1U, NULL, NULL}, 1508 {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds), 1509 AVX_OFFSET(ds), -1U, -1U, -1U, -1U, NULL, NULL}, 1510 {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr), 1511 AVX_OFFSET(mxcsr), -1U, -1U, -1U, -1U, NULL, NULL}, 1512 {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex, 1513 FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), -1U, -1U, -1U, -1U, NULL, 1514 NULL}, 1515 1516 {e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, 1517 FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), ehframe_dwarf_stmm0, 1518 ehframe_dwarf_stmm0, -1U, debugserver_stmm0, NULL, NULL}, 1519 {e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, 1520 FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), ehframe_dwarf_stmm1, 1521 ehframe_dwarf_stmm1, -1U, debugserver_stmm1, NULL, NULL}, 1522 {e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, 1523 FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), ehframe_dwarf_stmm2, 1524 ehframe_dwarf_stmm2, -1U, debugserver_stmm2, NULL, NULL}, 1525 {e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, 1526 FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), ehframe_dwarf_stmm3, 1527 ehframe_dwarf_stmm3, -1U, debugserver_stmm3, NULL, NULL}, 1528 {e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, 1529 FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), ehframe_dwarf_stmm4, 1530 ehframe_dwarf_stmm4, -1U, debugserver_stmm4, NULL, NULL}, 1531 {e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, 1532 FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), ehframe_dwarf_stmm5, 1533 ehframe_dwarf_stmm5, -1U, debugserver_stmm5, NULL, NULL}, 1534 {e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, 1535 FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), ehframe_dwarf_stmm6, 1536 ehframe_dwarf_stmm6, -1U, debugserver_stmm6, NULL, NULL}, 1537 {e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, 1538 FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), ehframe_dwarf_stmm7, 1539 ehframe_dwarf_stmm7, -1U, debugserver_stmm7, NULL, NULL}, 1540 1541 {e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8, 1542 FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), ehframe_dwarf_ymm0, 1543 ehframe_dwarf_ymm0, -1U, debugserver_ymm0, NULL, NULL}, 1544 {e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8, 1545 FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), ehframe_dwarf_ymm1, 1546 ehframe_dwarf_ymm1, -1U, debugserver_ymm1, NULL, NULL}, 1547 {e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8, 1548 FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), ehframe_dwarf_ymm2, 1549 ehframe_dwarf_ymm2, -1U, debugserver_ymm2, NULL, NULL}, 1550 {e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8, 1551 FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), ehframe_dwarf_ymm3, 1552 ehframe_dwarf_ymm3, -1U, debugserver_ymm3, NULL, NULL}, 1553 {e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8, 1554 FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), ehframe_dwarf_ymm4, 1555 ehframe_dwarf_ymm4, -1U, debugserver_ymm4, NULL, NULL}, 1556 {e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8, 1557 FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), ehframe_dwarf_ymm5, 1558 ehframe_dwarf_ymm5, -1U, debugserver_ymm5, NULL, NULL}, 1559 {e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8, 1560 FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), ehframe_dwarf_ymm6, 1561 ehframe_dwarf_ymm6, -1U, debugserver_ymm6, NULL, NULL}, 1562 {e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8, 1563 FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), ehframe_dwarf_ymm7, 1564 ehframe_dwarf_ymm7, -1U, debugserver_ymm7, NULL, NULL}, 1565 {e_regSetFPU, fpu_ymm8, "ymm8", NULL, Vector, VectorOfUInt8, 1566 FPU_SIZE_YMM(ymm8), AVX_OFFSET_YMM(8), ehframe_dwarf_ymm8, 1567 ehframe_dwarf_ymm8, -1U, debugserver_ymm8, NULL, NULL}, 1568 {e_regSetFPU, fpu_ymm9, "ymm9", NULL, Vector, VectorOfUInt8, 1569 FPU_SIZE_YMM(ymm9), AVX_OFFSET_YMM(9), ehframe_dwarf_ymm9, 1570 ehframe_dwarf_ymm9, -1U, debugserver_ymm9, NULL, NULL}, 1571 {e_regSetFPU, fpu_ymm10, "ymm10", NULL, Vector, VectorOfUInt8, 1572 FPU_SIZE_YMM(ymm10), AVX_OFFSET_YMM(10), ehframe_dwarf_ymm10, 1573 ehframe_dwarf_ymm10, -1U, debugserver_ymm10, NULL, NULL}, 1574 {e_regSetFPU, fpu_ymm11, "ymm11", NULL, Vector, VectorOfUInt8, 1575 FPU_SIZE_YMM(ymm11), AVX_OFFSET_YMM(11), ehframe_dwarf_ymm11, 1576 ehframe_dwarf_ymm11, -1U, debugserver_ymm11, NULL, NULL}, 1577 {e_regSetFPU, fpu_ymm12, "ymm12", NULL, Vector, VectorOfUInt8, 1578 FPU_SIZE_YMM(ymm12), AVX_OFFSET_YMM(12), ehframe_dwarf_ymm12, 1579 ehframe_dwarf_ymm12, -1U, debugserver_ymm12, NULL, NULL}, 1580 {e_regSetFPU, fpu_ymm13, "ymm13", NULL, Vector, VectorOfUInt8, 1581 FPU_SIZE_YMM(ymm13), AVX_OFFSET_YMM(13), ehframe_dwarf_ymm13, 1582 ehframe_dwarf_ymm13, -1U, debugserver_ymm13, NULL, NULL}, 1583 {e_regSetFPU, fpu_ymm14, "ymm14", NULL, Vector, VectorOfUInt8, 1584 FPU_SIZE_YMM(ymm14), AVX_OFFSET_YMM(14), ehframe_dwarf_ymm14, 1585 ehframe_dwarf_ymm14, -1U, debugserver_ymm14, NULL, NULL}, 1586 {e_regSetFPU, fpu_ymm15, "ymm15", NULL, Vector, VectorOfUInt8, 1587 FPU_SIZE_YMM(ymm15), AVX_OFFSET_YMM(15), ehframe_dwarf_ymm15, 1588 ehframe_dwarf_ymm15, -1U, debugserver_ymm15, NULL, NULL}, 1589 1590 {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, 1591 FPU_SIZE_XMM(xmm0), 0, ehframe_dwarf_xmm0, ehframe_dwarf_xmm0, -1U, 1592 debugserver_xmm0, g_contained_ymm0, NULL}, 1593 {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, 1594 FPU_SIZE_XMM(xmm1), 0, ehframe_dwarf_xmm1, ehframe_dwarf_xmm1, -1U, 1595 debugserver_xmm1, g_contained_ymm1, NULL}, 1596 {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, 1597 FPU_SIZE_XMM(xmm2), 0, ehframe_dwarf_xmm2, ehframe_dwarf_xmm2, -1U, 1598 debugserver_xmm2, g_contained_ymm2, NULL}, 1599 {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, 1600 FPU_SIZE_XMM(xmm3), 0, ehframe_dwarf_xmm3, ehframe_dwarf_xmm3, -1U, 1601 debugserver_xmm3, g_contained_ymm3, NULL}, 1602 {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, 1603 FPU_SIZE_XMM(xmm4), 0, ehframe_dwarf_xmm4, ehframe_dwarf_xmm4, -1U, 1604 debugserver_xmm4, g_contained_ymm4, NULL}, 1605 {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, 1606 FPU_SIZE_XMM(xmm5), 0, ehframe_dwarf_xmm5, ehframe_dwarf_xmm5, -1U, 1607 debugserver_xmm5, g_contained_ymm5, NULL}, 1608 {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, 1609 FPU_SIZE_XMM(xmm6), 0, ehframe_dwarf_xmm6, ehframe_dwarf_xmm6, -1U, 1610 debugserver_xmm6, g_contained_ymm6, NULL}, 1611 {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, 1612 FPU_SIZE_XMM(xmm7), 0, ehframe_dwarf_xmm7, ehframe_dwarf_xmm7, -1U, 1613 debugserver_xmm7, g_contained_ymm7, NULL}, 1614 {e_regSetFPU, fpu_xmm8, "xmm8", NULL, Vector, VectorOfUInt8, 1615 FPU_SIZE_XMM(xmm8), 0, ehframe_dwarf_xmm8, ehframe_dwarf_xmm8, -1U, 1616 debugserver_xmm8, g_contained_ymm8, NULL}, 1617 {e_regSetFPU, fpu_xmm9, "xmm9", NULL, Vector, VectorOfUInt8, 1618 FPU_SIZE_XMM(xmm9), 0, ehframe_dwarf_xmm9, ehframe_dwarf_xmm9, -1U, 1619 debugserver_xmm9, g_contained_ymm9, NULL}, 1620 {e_regSetFPU, fpu_xmm10, "xmm10", NULL, Vector, VectorOfUInt8, 1621 FPU_SIZE_XMM(xmm10), 0, ehframe_dwarf_xmm10, ehframe_dwarf_xmm10, -1U, 1622 debugserver_xmm10, g_contained_ymm10, NULL}, 1623 {e_regSetFPU, fpu_xmm11, "xmm11", NULL, Vector, VectorOfUInt8, 1624 FPU_SIZE_XMM(xmm11), 0, ehframe_dwarf_xmm11, ehframe_dwarf_xmm11, -1U, 1625 debugserver_xmm11, g_contained_ymm11, NULL}, 1626 {e_regSetFPU, fpu_xmm12, "xmm12", NULL, Vector, VectorOfUInt8, 1627 FPU_SIZE_XMM(xmm12), 0, ehframe_dwarf_xmm12, ehframe_dwarf_xmm12, -1U, 1628 debugserver_xmm12, g_contained_ymm12, NULL}, 1629 {e_regSetFPU, fpu_xmm13, "xmm13", NULL, Vector, VectorOfUInt8, 1630 FPU_SIZE_XMM(xmm13), 0, ehframe_dwarf_xmm13, ehframe_dwarf_xmm13, -1U, 1631 debugserver_xmm13, g_contained_ymm13, NULL}, 1632 {e_regSetFPU, fpu_xmm14, "xmm14", NULL, Vector, VectorOfUInt8, 1633 FPU_SIZE_XMM(xmm14), 0, ehframe_dwarf_xmm14, ehframe_dwarf_xmm14, -1U, 1634 debugserver_xmm14, g_contained_ymm14, NULL}, 1635 {e_regSetFPU, fpu_xmm15, "xmm15", NULL, Vector, VectorOfUInt8, 1636 FPU_SIZE_XMM(xmm15), 0, ehframe_dwarf_xmm15, ehframe_dwarf_xmm15, -1U, 1637 debugserver_xmm15, g_contained_ymm15, NULL} 1638 1639 }; 1640 1641 // Exception registers 1642 1643 const DNBRegisterInfo DNBArchImplX86_64::g_exc_registers[] = { 1644 {e_regSetEXC, exc_trapno, "trapno", NULL, Uint, Hex, EXC_SIZE(trapno), 1645 EXC_OFFSET(trapno), -1U, -1U, -1U, -1U, NULL, NULL}, 1646 {e_regSetEXC, exc_err, "err", NULL, Uint, Hex, EXC_SIZE(err), 1647 EXC_OFFSET(err), -1U, -1U, -1U, -1U, NULL, NULL}, 1648 {e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, 1649 EXC_SIZE(faultvaddr), EXC_OFFSET(faultvaddr), -1U, -1U, -1U, -1U, NULL, 1650 NULL}}; 1651 1652 // Number of registers in each register set 1653 const size_t DNBArchImplX86_64::k_num_gpr_registers = 1654 sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo); 1655 const size_t DNBArchImplX86_64::k_num_fpu_registers_no_avx = 1656 sizeof(g_fpu_registers_no_avx) / sizeof(DNBRegisterInfo); 1657 const size_t DNBArchImplX86_64::k_num_fpu_registers_avx = 1658 sizeof(g_fpu_registers_avx) / sizeof(DNBRegisterInfo); 1659 const size_t DNBArchImplX86_64::k_num_exc_registers = 1660 sizeof(g_exc_registers) / sizeof(DNBRegisterInfo); 1661 const size_t DNBArchImplX86_64::k_num_all_registers_no_avx = 1662 k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers; 1663 const size_t DNBArchImplX86_64::k_num_all_registers_avx = 1664 k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers; 1665 1666 //---------------------------------------------------------------------- 1667 // Register set definitions. The first definitions at register set index 1668 // of zero is for all registers, followed by other registers sets. The 1669 // register information for the all register set need not be filled in. 1670 //---------------------------------------------------------------------- 1671 const DNBRegisterSetInfo DNBArchImplX86_64::g_reg_sets_no_avx[] = { 1672 {"x86_64 Registers", NULL, k_num_all_registers_no_avx}, 1673 {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, 1674 {"Floating Point Registers", g_fpu_registers_no_avx, 1675 k_num_fpu_registers_no_avx}, 1676 {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; 1677 1678 const DNBRegisterSetInfo DNBArchImplX86_64::g_reg_sets_avx[] = { 1679 {"x86_64 Registers", NULL, k_num_all_registers_avx}, 1680 {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers}, 1681 {"Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx}, 1682 {"Exception State Registers", g_exc_registers, k_num_exc_registers}}; 1683 1684 // Total number of register sets for this architecture 1685 const size_t DNBArchImplX86_64::k_num_register_sets = 1686 sizeof(g_reg_sets_avx) / sizeof(DNBRegisterSetInfo); 1687 1688 DNBArchProtocol *DNBArchImplX86_64::Create(MachThread *thread) { 1689 DNBArchImplX86_64 *obj = new DNBArchImplX86_64(thread); 1690 return obj; 1691 } 1692 1693 const uint8_t * 1694 DNBArchImplX86_64::SoftwareBreakpointOpcode(nub_size_t byte_size) { 1695 static const uint8_t g_breakpoint_opcode[] = {0xCC}; 1696 if (byte_size == 1) 1697 return g_breakpoint_opcode; 1698 return NULL; 1699 } 1700 1701 const DNBRegisterSetInfo * 1702 DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets) { 1703 *num_reg_sets = k_num_register_sets; 1704 1705 if (CPUHasAVX() || FORCE_AVX_REGS) 1706 return g_reg_sets_avx; 1707 else 1708 return g_reg_sets_no_avx; 1709 } 1710 1711 void DNBArchImplX86_64::Initialize() { 1712 DNBArchPluginInfo arch_plugin_info = { 1713 CPU_TYPE_X86_64, DNBArchImplX86_64::Create, 1714 DNBArchImplX86_64::GetRegisterSetInfo, 1715 DNBArchImplX86_64::SoftwareBreakpointOpcode}; 1716 1717 // Register this arch plug-in with the main protocol class 1718 DNBArchProtocol::RegisterArchPlugin(arch_plugin_info); 1719 } 1720 1721 bool DNBArchImplX86_64::GetRegisterValue(uint32_t set, uint32_t reg, 1722 DNBRegisterValue *value) { 1723 if (set == REGISTER_SET_GENERIC) { 1724 switch (reg) { 1725 case GENERIC_REGNUM_PC: // Program Counter 1726 set = e_regSetGPR; 1727 reg = gpr_rip; 1728 break; 1729 1730 case GENERIC_REGNUM_SP: // Stack Pointer 1731 set = e_regSetGPR; 1732 reg = gpr_rsp; 1733 break; 1734 1735 case GENERIC_REGNUM_FP: // Frame Pointer 1736 set = e_regSetGPR; 1737 reg = gpr_rbp; 1738 break; 1739 1740 case GENERIC_REGNUM_FLAGS: // Processor flags register 1741 set = e_regSetGPR; 1742 reg = gpr_rflags; 1743 break; 1744 1745 case GENERIC_REGNUM_RA: // Return Address 1746 default: 1747 return false; 1748 } 1749 } 1750 1751 if (GetRegisterState(set, false) != KERN_SUCCESS) 1752 return false; 1753 1754 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 1755 if (regInfo) { 1756 value->info = *regInfo; 1757 switch (set) { 1758 case e_regSetGPR: 1759 if (reg < k_num_gpr_registers) { 1760 value->value.uint64 = ((uint64_t *)(&m_state.context.gpr))[reg]; 1761 return true; 1762 } 1763 break; 1764 1765 case e_regSetFPU: 1766 if (reg > fpu_xmm15 && !(CPUHasAVX() || FORCE_AVX_REGS)) 1767 return false; 1768 switch (reg) { 1769 1770 case fpu_fcw: 1771 value->value.uint16 = 1772 *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)); 1773 return true; 1774 case fpu_fsw: 1775 value->value.uint16 = 1776 *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)); 1777 return true; 1778 case fpu_ftw: 1779 memcpy (&value->value.uint16, &m_state.context.fpu.no_avx.__fpu_ftw, 2); 1780 return true; 1781 case fpu_fop: 1782 value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop; 1783 return true; 1784 case fpu_ip: 1785 value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip; 1786 return true; 1787 case fpu_cs: 1788 value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs; 1789 return true; 1790 case fpu_dp: 1791 value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp; 1792 return true; 1793 case fpu_ds: 1794 value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds; 1795 return true; 1796 case fpu_mxcsr: 1797 value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr; 1798 return true; 1799 case fpu_mxcsrmask: 1800 value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask; 1801 return true; 1802 1803 case fpu_stmm0: 1804 case fpu_stmm1: 1805 case fpu_stmm2: 1806 case fpu_stmm3: 1807 case fpu_stmm4: 1808 case fpu_stmm5: 1809 case fpu_stmm6: 1810 case fpu_stmm7: 1811 memcpy(&value->value.uint8, 1812 &m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), 10); 1813 return true; 1814 1815 case fpu_xmm0: 1816 case fpu_xmm1: 1817 case fpu_xmm2: 1818 case fpu_xmm3: 1819 case fpu_xmm4: 1820 case fpu_xmm5: 1821 case fpu_xmm6: 1822 case fpu_xmm7: 1823 case fpu_xmm8: 1824 case fpu_xmm9: 1825 case fpu_xmm10: 1826 case fpu_xmm11: 1827 case fpu_xmm12: 1828 case fpu_xmm13: 1829 case fpu_xmm14: 1830 case fpu_xmm15: 1831 memcpy(&value->value.uint8, 1832 &m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), 16); 1833 return true; 1834 1835 case fpu_ymm0: 1836 case fpu_ymm1: 1837 case fpu_ymm2: 1838 case fpu_ymm3: 1839 case fpu_ymm4: 1840 case fpu_ymm5: 1841 case fpu_ymm6: 1842 case fpu_ymm7: 1843 case fpu_ymm8: 1844 case fpu_ymm9: 1845 case fpu_ymm10: 1846 case fpu_ymm11: 1847 case fpu_ymm12: 1848 case fpu_ymm13: 1849 case fpu_ymm14: 1850 case fpu_ymm15: 1851 memcpy(&value->value.uint8, 1852 &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), 16); 1853 memcpy((&value->value.uint8) + 16, 1854 &m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), 16); 1855 return true; 1856 } 1857 break; 1858 1859 case e_regSetEXC: 1860 switch (reg) { 1861 case exc_trapno: 1862 value->value.uint32 = m_state.context.exc.__trapno; 1863 return true; 1864 case exc_err: 1865 value->value.uint32 = m_state.context.exc.__err; 1866 return true; 1867 case exc_faultvaddr: 1868 value->value.uint64 = m_state.context.exc.__faultvaddr; 1869 return true; 1870 } 1871 break; 1872 } 1873 } 1874 return false; 1875 } 1876 1877 bool DNBArchImplX86_64::SetRegisterValue(uint32_t set, uint32_t reg, 1878 const DNBRegisterValue *value) { 1879 if (set == REGISTER_SET_GENERIC) { 1880 switch (reg) { 1881 case GENERIC_REGNUM_PC: // Program Counter 1882 set = e_regSetGPR; 1883 reg = gpr_rip; 1884 break; 1885 1886 case GENERIC_REGNUM_SP: // Stack Pointer 1887 set = e_regSetGPR; 1888 reg = gpr_rsp; 1889 break; 1890 1891 case GENERIC_REGNUM_FP: // Frame Pointer 1892 set = e_regSetGPR; 1893 reg = gpr_rbp; 1894 break; 1895 1896 case GENERIC_REGNUM_FLAGS: // Processor flags register 1897 set = e_regSetGPR; 1898 reg = gpr_rflags; 1899 break; 1900 1901 case GENERIC_REGNUM_RA: // Return Address 1902 default: 1903 return false; 1904 } 1905 } 1906 1907 if (GetRegisterState(set, false) != KERN_SUCCESS) 1908 return false; 1909 1910 bool success = false; 1911 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 1912 if (regInfo) { 1913 switch (set) { 1914 case e_regSetGPR: 1915 if (reg < k_num_gpr_registers) { 1916 ((uint64_t *)(&m_state.context.gpr))[reg] = value->value.uint64; 1917 success = true; 1918 } 1919 break; 1920 if (reg > fpu_xmm15 && !(CPUHasAVX() || FORCE_AVX_REGS)) 1921 return false; 1922 case e_regSetFPU: 1923 switch (reg) { 1924 case fpu_fcw: 1925 *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = 1926 value->value.uint16; 1927 success = true; 1928 break; 1929 case fpu_fsw: 1930 *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = 1931 value->value.uint16; 1932 success = true; 1933 break; 1934 case fpu_ftw: 1935 memcpy (&m_state.context.fpu.no_avx.__fpu_ftw, &value->value.uint8, 2); 1936 success = true; 1937 break; 1938 case fpu_fop: 1939 m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16; 1940 success = true; 1941 break; 1942 case fpu_ip: 1943 m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32; 1944 success = true; 1945 break; 1946 case fpu_cs: 1947 m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16; 1948 success = true; 1949 break; 1950 case fpu_dp: 1951 m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32; 1952 success = true; 1953 break; 1954 case fpu_ds: 1955 m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16; 1956 success = true; 1957 break; 1958 case fpu_mxcsr: 1959 m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32; 1960 success = true; 1961 break; 1962 case fpu_mxcsrmask: 1963 m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32; 1964 success = true; 1965 break; 1966 1967 case fpu_stmm0: 1968 case fpu_stmm1: 1969 case fpu_stmm2: 1970 case fpu_stmm3: 1971 case fpu_stmm4: 1972 case fpu_stmm5: 1973 case fpu_stmm6: 1974 case fpu_stmm7: 1975 memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), 1976 &value->value.uint8, 10); 1977 success = true; 1978 break; 1979 1980 case fpu_xmm0: 1981 case fpu_xmm1: 1982 case fpu_xmm2: 1983 case fpu_xmm3: 1984 case fpu_xmm4: 1985 case fpu_xmm5: 1986 case fpu_xmm6: 1987 case fpu_xmm7: 1988 case fpu_xmm8: 1989 case fpu_xmm9: 1990 case fpu_xmm10: 1991 case fpu_xmm11: 1992 case fpu_xmm12: 1993 case fpu_xmm13: 1994 case fpu_xmm14: 1995 case fpu_xmm15: 1996 memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), 1997 &value->value.uint8, 16); 1998 success = true; 1999 break; 2000 2001 case fpu_ymm0: 2002 case fpu_ymm1: 2003 case fpu_ymm2: 2004 case fpu_ymm3: 2005 case fpu_ymm4: 2006 case fpu_ymm5: 2007 case fpu_ymm6: 2008 case fpu_ymm7: 2009 case fpu_ymm8: 2010 case fpu_ymm9: 2011 case fpu_ymm10: 2012 case fpu_ymm11: 2013 case fpu_ymm12: 2014 case fpu_ymm13: 2015 case fpu_ymm14: 2016 case fpu_ymm15: 2017 memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), 2018 &value->value.uint8, 16); 2019 memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), 2020 (&value->value.uint8) + 16, 16); 2021 return true; 2022 } 2023 break; 2024 2025 case e_regSetEXC: 2026 switch (reg) { 2027 case exc_trapno: 2028 m_state.context.exc.__trapno = value->value.uint32; 2029 success = true; 2030 break; 2031 case exc_err: 2032 m_state.context.exc.__err = value->value.uint32; 2033 success = true; 2034 break; 2035 case exc_faultvaddr: 2036 m_state.context.exc.__faultvaddr = value->value.uint64; 2037 success = true; 2038 break; 2039 } 2040 break; 2041 } 2042 } 2043 2044 if (success) 2045 return SetRegisterState(set) == KERN_SUCCESS; 2046 return false; 2047 } 2048 2049 uint32_t DNBArchImplX86_64::GetRegisterContextSize() { 2050 static uint32_t g_cached_size = 0; 2051 if (g_cached_size == 0) { 2052 if (CPUHasAVX() || FORCE_AVX_REGS) { 2053 for (size_t i = 0; i < k_num_fpu_registers_avx; ++i) { 2054 if (g_fpu_registers_avx[i].value_regs == NULL) 2055 g_cached_size += g_fpu_registers_avx[i].size; 2056 } 2057 } else { 2058 for (size_t i = 0; i < k_num_fpu_registers_no_avx; ++i) { 2059 if (g_fpu_registers_no_avx[i].value_regs == NULL) 2060 g_cached_size += g_fpu_registers_no_avx[i].size; 2061 } 2062 } 2063 DNBLogThreaded("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, " 2064 "FPU = %u, EXC = %zu", 2065 sizeof(GPR), g_cached_size, sizeof(EXC)); 2066 g_cached_size += sizeof(GPR); 2067 g_cached_size += sizeof(EXC); 2068 DNBLogThreaded( 2069 "DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u", 2070 g_cached_size); 2071 } 2072 return g_cached_size; 2073 } 2074 2075 nub_size_t DNBArchImplX86_64::GetRegisterContext(void *buf, 2076 nub_size_t buf_len) { 2077 uint32_t size = GetRegisterContextSize(); 2078 2079 if (buf && buf_len) { 2080 bool force = false; 2081 kern_return_t kret; 2082 2083 if ((kret = GetGPRState(force)) != KERN_SUCCESS) { 2084 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf " 2085 "= %p, len = %llu) error: GPR regs failed " 2086 "to read: %u ", 2087 buf, (uint64_t)buf_len, kret); 2088 size = 0; 2089 } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) { 2090 DNBLogThreadedIf( 2091 LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = " 2092 "%llu) error: %s regs failed to read: %u", 2093 buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); 2094 size = 0; 2095 } else if ((kret = GetEXCState(force)) != KERN_SUCCESS) { 2096 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf " 2097 "= %p, len = %llu) error: EXC regs failed " 2098 "to read: %u", 2099 buf, (uint64_t)buf_len, kret); 2100 size = 0; 2101 } else { 2102 uint8_t *p = (uint8_t *)buf; 2103 // Copy the GPR registers 2104 memcpy(p, &m_state.context.gpr, sizeof(GPR)); 2105 p += sizeof(GPR); 2106 2107 // Walk around the gaps in the FPU regs 2108 memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5); 2109 p += 5; 2110 memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8); 2111 p += 8; 2112 memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6); 2113 p += 6; 2114 memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8); 2115 p += 8; 2116 2117 // Work around the padding between the stmm registers as they are 16 2118 // byte structs with 10 bytes of the value in each 2119 for (size_t i = 0; i < 8; ++i) { 2120 memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10); 2121 p += 10; 2122 } 2123 2124 if (CPUHasAVX() || FORCE_AVX_REGS) { 2125 // Interleave the XMM and YMMH registers to make the YMM registers 2126 for (size_t i = 0; i < 16; ++i) { 2127 memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16); 2128 p += 16; 2129 memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16); 2130 p += 16; 2131 } 2132 } else { 2133 // Copy the XMM registers in a single block 2134 memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 16 * 16); 2135 p += 16 * 16; 2136 } 2137 2138 // Copy the exception registers 2139 memcpy(p, &m_state.context.exc, sizeof(EXC)); 2140 p += sizeof(EXC); 2141 2142 // make sure we end up with exactly what we think we should have 2143 size_t bytes_written = p - (uint8_t *)buf; 2144 UNUSED_IF_ASSERT_DISABLED(bytes_written); 2145 assert(bytes_written == size); 2146 } 2147 } 2148 2149 DNBLogThreadedIf( 2150 LOG_THREAD, 2151 "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) => %u", buf, 2152 (uint64_t)buf_len, size); 2153 // Return the size of the register context even if NULL was passed in 2154 return size; 2155 } 2156 2157 nub_size_t DNBArchImplX86_64::SetRegisterContext(const void *buf, 2158 nub_size_t buf_len) { 2159 uint32_t size = GetRegisterContextSize(); 2160 if (buf == NULL || buf_len == 0) 2161 size = 0; 2162 2163 if (size) { 2164 if (size > buf_len) 2165 size = static_cast<uint32_t>(buf_len); 2166 2167 uint8_t *p = (uint8_t *)buf; 2168 // Copy the GPR registers 2169 memcpy(&m_state.context.gpr, p, sizeof(GPR)); 2170 p += sizeof(GPR); 2171 2172 // Copy fcw through mxcsrmask as there is no padding 2173 memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5); 2174 p += 5; 2175 memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8); 2176 p += 8; 2177 memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6); 2178 p += 6; 2179 memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8); 2180 p += 8; 2181 2182 // Work around the padding between the stmm registers as they are 16 2183 // byte structs with 10 bytes of the value in each 2184 for (size_t i = 0; i < 8; ++i) { 2185 memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10); 2186 p += 10; 2187 } 2188 2189 if (CPUHasAVX() || FORCE_AVX_REGS) { 2190 // Interleave the XMM and YMMH registers to make the YMM registers 2191 for (size_t i = 0; i < 16; ++i) { 2192 memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16); 2193 p += 16; 2194 memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16); 2195 p += 16; 2196 } 2197 } else { 2198 // Copy the XMM registers in a single block 2199 memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 16 * 16); 2200 p += 16 * 16; 2201 } 2202 2203 // Copy the exception registers 2204 memcpy(&m_state.context.exc, p, sizeof(EXC)); 2205 p += sizeof(EXC); 2206 2207 // make sure we end up with exactly what we think we should have 2208 size_t bytes_written = p - (uint8_t *)buf; 2209 UNUSED_IF_ASSERT_DISABLED(bytes_written); 2210 assert(bytes_written == size); 2211 2212 kern_return_t kret; 2213 if ((kret = SetGPRState()) != KERN_SUCCESS) 2214 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf " 2215 "= %p, len = %llu) error: GPR regs failed " 2216 "to write: %u", 2217 buf, (uint64_t)buf_len, kret); 2218 if ((kret = SetFPUState()) != KERN_SUCCESS) 2219 DNBLogThreadedIf( 2220 LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = " 2221 "%llu) error: %s regs failed to write: %u", 2222 buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); 2223 if ((kret = SetEXCState()) != KERN_SUCCESS) 2224 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf " 2225 "= %p, len = %llu) error: EXP regs failed " 2226 "to write: %u", 2227 buf, (uint64_t)buf_len, kret); 2228 } 2229 DNBLogThreadedIf( 2230 LOG_THREAD, 2231 "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) => %llu", 2232 buf, (uint64_t)buf_len, (uint64_t)size); 2233 return size; 2234 } 2235 2236 uint32_t DNBArchImplX86_64::SaveRegisterState() { 2237 kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); 2238 DNBLogThreadedIf( 2239 LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u " 2240 "(SetGPRState() for stop_count = %u)", 2241 m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); 2242 2243 // Always re-read the registers because above we call thread_abort_safely(); 2244 bool force = true; 2245 2246 if ((kret = GetGPRState(force)) != KERN_SUCCESS) { 2247 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () " 2248 "error: GPR regs failed to read: %u ", 2249 kret); 2250 } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) { 2251 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () " 2252 "error: %s regs failed to read: %u", 2253 CPUHasAVX() ? "AVX" : "FPU", kret); 2254 } else { 2255 const uint32_t save_id = GetNextRegisterStateSaveID(); 2256 m_saved_register_states[save_id] = m_state.context; 2257 return save_id; 2258 } 2259 return 0; 2260 } 2261 bool DNBArchImplX86_64::RestoreRegisterState(uint32_t save_id) { 2262 SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); 2263 if (pos != m_saved_register_states.end()) { 2264 m_state.context.gpr = pos->second.gpr; 2265 m_state.context.fpu = pos->second.fpu; 2266 m_state.SetError(e_regSetGPR, Read, 0); 2267 m_state.SetError(e_regSetFPU, Read, 0); 2268 kern_return_t kret; 2269 bool success = true; 2270 if ((kret = SetGPRState()) != KERN_SUCCESS) { 2271 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState " 2272 "(save_id = %u) error: GPR regs failed to " 2273 "write: %u", 2274 save_id, kret); 2275 success = false; 2276 } else if ((kret = SetFPUState()) != KERN_SUCCESS) { 2277 DNBLogThreadedIf(LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState " 2278 "(save_id = %u) error: %s regs failed to " 2279 "write: %u", 2280 save_id, CPUHasAVX() ? "AVX" : "FPU", kret); 2281 success = false; 2282 } 2283 m_saved_register_states.erase(pos); 2284 return success; 2285 } 2286 return false; 2287 } 2288 2289 kern_return_t DNBArchImplX86_64::GetRegisterState(int set, bool force) { 2290 switch (set) { 2291 case e_regSetALL: 2292 return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); 2293 case e_regSetGPR: 2294 return GetGPRState(force); 2295 case e_regSetFPU: 2296 return GetFPUState(force); 2297 case e_regSetEXC: 2298 return GetEXCState(force); 2299 default: 2300 break; 2301 } 2302 return KERN_INVALID_ARGUMENT; 2303 } 2304 2305 kern_return_t DNBArchImplX86_64::SetRegisterState(int set) { 2306 // Make sure we have a valid context to set. 2307 if (RegisterSetStateIsValid(set)) { 2308 switch (set) { 2309 case e_regSetALL: 2310 return SetGPRState() | SetFPUState() | SetEXCState(); 2311 case e_regSetGPR: 2312 return SetGPRState(); 2313 case e_regSetFPU: 2314 return SetFPUState(); 2315 case e_regSetEXC: 2316 return SetEXCState(); 2317 default: 2318 break; 2319 } 2320 } 2321 return KERN_INVALID_ARGUMENT; 2322 } 2323 2324 bool DNBArchImplX86_64::RegisterSetStateIsValid(int set) const { 2325 return m_state.RegsAreValid(set); 2326 } 2327 2328 #endif // #if defined (__i386__) || defined (__x86_64__) 2329