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