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