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