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