DNBArchImplX86_64.cpp revision c71899ef308e6134d1b0ca5f30cbc64414855e1a
1//===-- DNBArchImplX86_64.cpp -----------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Created by Greg Clayton on 6/25/07. 11// 12//===----------------------------------------------------------------------===// 13 14#if defined (__i386__) || defined (__x86_64__) 15 16#include <sys/cdefs.h> 17 18#include "MacOSX/x86_64/DNBArchImplX86_64.h" 19#include "DNBLog.h" 20#include "MachThread.h" 21#include "MachProcess.h" 22 23uint64_t 24DNBArchImplX86_64::GetPC(uint64_t failValue) 25{ 26 // Get program counter 27 if (GetGPRState(false) == KERN_SUCCESS) 28 return m_state.context.gpr.__rip; 29 return failValue; 30} 31 32kern_return_t 33DNBArchImplX86_64::SetPC(uint64_t value) 34{ 35 // Get program counter 36 kern_return_t err = GetGPRState(false); 37 if (err == KERN_SUCCESS) 38 { 39 m_state.context.gpr.__rip = value; 40 err = SetGPRState(); 41 } 42 return err == KERN_SUCCESS; 43} 44 45uint64_t 46DNBArchImplX86_64::GetSP(uint64_t failValue) 47{ 48 // Get stack pointer 49 if (GetGPRState(false) == KERN_SUCCESS) 50 return m_state.context.gpr.__rsp; 51 return failValue; 52} 53 54// Uncomment the value below to verify the values in the debugger. 55//#define DEBUG_GPR_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED 56 57kern_return_t 58DNBArchImplX86_64::GetGPRState(bool force) 59{ 60 if (force || m_state.GetError(e_regSetGPR, Read)) 61 { 62#if DEBUG_GPR_VALUES 63 m_state.context.gpr.__rax = ('a' << 8) + 'x'; 64 m_state.context.gpr.__rbx = ('b' << 8) + 'x'; 65 m_state.context.gpr.__rcx = ('c' << 8) + 'x'; 66 m_state.context.gpr.__rdx = ('d' << 8) + 'x'; 67 m_state.context.gpr.__rdi = ('d' << 8) + 'i'; 68 m_state.context.gpr.__rsi = ('s' << 8) + 'i'; 69 m_state.context.gpr.__rbp = ('b' << 8) + 'p'; 70 m_state.context.gpr.__rsp = ('s' << 8) + 'p'; 71 m_state.context.gpr.__r8 = ('r' << 8) + '8'; 72 m_state.context.gpr.__r9 = ('r' << 8) + '9'; 73 m_state.context.gpr.__r10 = ('r' << 8) + 'a'; 74 m_state.context.gpr.__r11 = ('r' << 8) + 'b'; 75 m_state.context.gpr.__r12 = ('r' << 8) + 'c'; 76 m_state.context.gpr.__r13 = ('r' << 8) + 'd'; 77 m_state.context.gpr.__r14 = ('r' << 8) + 'e'; 78 m_state.context.gpr.__r15 = ('r' << 8) + 'f'; 79 m_state.context.gpr.__rip = ('i' << 8) + 'p'; 80 m_state.context.gpr.__rflags = ('f' << 8) + 'l'; 81 m_state.context.gpr.__cs = ('c' << 8) + 's'; 82 m_state.context.gpr.__fs = ('f' << 8) + 's'; 83 m_state.context.gpr.__gs = ('g' << 8) + 's'; 84 m_state.SetError(e_regSetGPR, Read, 0); 85#else 86 mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT; 87 m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->ThreadID(), x86_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, &count)); 88 DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" 89 "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" 90 "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" 91 "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" 92 "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" 93 "\n\trip = %16.16llx" 94 "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", 95 m_thread->ThreadID(), x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT, 96 m_state.GetError(e_regSetGPR, Read), 97 m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx, 98 m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi, 99 m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8, 100 m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11, 101 m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14, 102 m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags, 103 m_state.context.gpr.__cs,m_state.context.gpr.__fs, m_state.context.gpr.__gs); 104 105 // DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x" 106 // "\n\trax = %16.16llx" 107 // "\n\trbx = %16.16llx" 108 // "\n\trcx = %16.16llx" 109 // "\n\trdx = %16.16llx" 110 // "\n\trdi = %16.16llx" 111 // "\n\trsi = %16.16llx" 112 // "\n\trbp = %16.16llx" 113 // "\n\trsp = %16.16llx" 114 // "\n\t r8 = %16.16llx" 115 // "\n\t r9 = %16.16llx" 116 // "\n\tr10 = %16.16llx" 117 // "\n\tr11 = %16.16llx" 118 // "\n\tr12 = %16.16llx" 119 // "\n\tr13 = %16.16llx" 120 // "\n\tr14 = %16.16llx" 121 // "\n\tr15 = %16.16llx" 122 // "\n\trip = %16.16llx" 123 // "\n\tflg = %16.16llx" 124 // "\n\t cs = %16.16llx" 125 // "\n\t fs = %16.16llx" 126 // "\n\t gs = %16.16llx", 127 // m_thread->ThreadID(), 128 // x86_THREAD_STATE64, 129 // x86_THREAD_STATE64_COUNT, 130 // m_state.GetError(e_regSetGPR, Read), 131 // m_state.context.gpr.__rax, 132 // m_state.context.gpr.__rbx, 133 // m_state.context.gpr.__rcx, 134 // m_state.context.gpr.__rdx, 135 // m_state.context.gpr.__rdi, 136 // m_state.context.gpr.__rsi, 137 // m_state.context.gpr.__rbp, 138 // m_state.context.gpr.__rsp, 139 // m_state.context.gpr.__r8, 140 // m_state.context.gpr.__r9, 141 // m_state.context.gpr.__r10, 142 // m_state.context.gpr.__r11, 143 // m_state.context.gpr.__r12, 144 // m_state.context.gpr.__r13, 145 // m_state.context.gpr.__r14, 146 // m_state.context.gpr.__r15, 147 // m_state.context.gpr.__rip, 148 // m_state.context.gpr.__rflags, 149 // m_state.context.gpr.__cs, 150 // m_state.context.gpr.__fs, 151 // m_state.context.gpr.__gs); 152#endif 153 } 154 return m_state.GetError(e_regSetGPR, Read); 155} 156 157// Uncomment the value below to verify the values in the debugger. 158//#define DEBUG_FPU_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED 159 160kern_return_t 161DNBArchImplX86_64::GetFPUState(bool force) 162{ 163 if (force || m_state.GetError(e_regSetFPU, Read)) 164 { 165#if DEBUG_FPU_VALUES 166 m_state.context.fpu.__fpu_reserved[0] = -1; 167 m_state.context.fpu.__fpu_reserved[1] = -1; 168 *(uint16_t *)&(m_state.context.fpu.__fpu_fcw) = 0x1234; 169 *(uint16_t *)&(m_state.context.fpu.__fpu_fsw) = 0x5678; 170 m_state.context.fpu.__fpu_ftw = 1; 171 m_state.context.fpu.__fpu_rsrv1 = UINT8_MAX; 172 m_state.context.fpu.__fpu_fop = 2; 173 m_state.context.fpu.__fpu_ip = 3; 174 m_state.context.fpu.__fpu_cs = 4; 175 m_state.context.fpu.__fpu_rsrv2 = 5; 176 m_state.context.fpu.__fpu_dp = 6; 177 m_state.context.fpu.__fpu_ds = 7; 178 m_state.context.fpu.__fpu_rsrv3 = UINT16_MAX; 179 m_state.context.fpu.__fpu_mxcsr = 8; 180 m_state.context.fpu.__fpu_mxcsrmask = 9; 181 int i; 182 for (i=0; i<16; ++i) 183 { 184 if (i<10) 185 { 186 m_state.context.fpu.__fpu_stmm0.__mmst_reg[i] = 'a'; 187 m_state.context.fpu.__fpu_stmm1.__mmst_reg[i] = 'b'; 188 m_state.context.fpu.__fpu_stmm2.__mmst_reg[i] = 'c'; 189 m_state.context.fpu.__fpu_stmm3.__mmst_reg[i] = 'd'; 190 m_state.context.fpu.__fpu_stmm4.__mmst_reg[i] = 'e'; 191 m_state.context.fpu.__fpu_stmm5.__mmst_reg[i] = 'f'; 192 m_state.context.fpu.__fpu_stmm6.__mmst_reg[i] = 'g'; 193 m_state.context.fpu.__fpu_stmm7.__mmst_reg[i] = 'h'; 194 } 195 else 196 { 197 m_state.context.fpu.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; 198 m_state.context.fpu.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; 199 m_state.context.fpu.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; 200 m_state.context.fpu.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; 201 m_state.context.fpu.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; 202 m_state.context.fpu.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; 203 m_state.context.fpu.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; 204 m_state.context.fpu.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; 205 } 206 207 m_state.context.fpu.__fpu_xmm0.__xmm_reg[i] = '0'; 208 m_state.context.fpu.__fpu_xmm1.__xmm_reg[i] = '1'; 209 m_state.context.fpu.__fpu_xmm2.__xmm_reg[i] = '2'; 210 m_state.context.fpu.__fpu_xmm3.__xmm_reg[i] = '3'; 211 m_state.context.fpu.__fpu_xmm4.__xmm_reg[i] = '4'; 212 m_state.context.fpu.__fpu_xmm5.__xmm_reg[i] = '5'; 213 m_state.context.fpu.__fpu_xmm6.__xmm_reg[i] = '6'; 214 m_state.context.fpu.__fpu_xmm7.__xmm_reg[i] = '7'; 215 m_state.context.fpu.__fpu_xmm8.__xmm_reg[i] = '8'; 216 m_state.context.fpu.__fpu_xmm9.__xmm_reg[i] = '9'; 217 m_state.context.fpu.__fpu_xmm10.__xmm_reg[i] = 'A'; 218 m_state.context.fpu.__fpu_xmm11.__xmm_reg[i] = 'B'; 219 m_state.context.fpu.__fpu_xmm12.__xmm_reg[i] = 'C'; 220 m_state.context.fpu.__fpu_xmm13.__xmm_reg[i] = 'D'; 221 m_state.context.fpu.__fpu_xmm14.__xmm_reg[i] = 'E'; 222 m_state.context.fpu.__fpu_xmm15.__xmm_reg[i] = 'F'; 223 } 224 for (i=0; i<sizeof(m_state.context.fpu.__fpu_rsrv4); ++i) 225 m_state.context.fpu.__fpu_rsrv4[i] = INT8_MIN; 226 m_state.context.fpu.__fpu_reserved1 = -1; 227 m_state.SetError(e_regSetFPU, Read, 0); 228#else 229 mach_msg_type_number_t count = x86_FLOAT_STATE64_COUNT; 230 m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->ThreadID(), x86_FLOAT_STATE64, (thread_state_t)&m_state.context.fpu, &count)); 231#endif 232 } 233 return m_state.GetError(e_regSetFPU, Read); 234} 235 236kern_return_t 237DNBArchImplX86_64::GetEXCState(bool force) 238{ 239 if (force || m_state.GetError(e_regSetEXC, Read)) 240 { 241 mach_msg_type_number_t count = X86_EXCEPTION_STATE64_COUNT; 242 m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->ThreadID(), x86_EXCEPTION_STATE64, (thread_state_t)&m_state.context.exc, &count)); 243 } 244 return m_state.GetError(e_regSetEXC, Read); 245} 246 247kern_return_t 248DNBArchImplX86_64::SetGPRState() 249{ 250 m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->ThreadID(), x86_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, x86_THREAD_STATE64_COUNT)); 251 DNBLogThreadedIf (LOG_THREAD, "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" 252 "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" 253 "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" 254 "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" 255 "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" 256 "\n\trip = %16.16llx" 257 "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", 258 m_thread->ThreadID(), x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT, 259 m_state.GetError(e_regSetGPR, Write), 260 m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx, 261 m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi, 262 m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8, 263 m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11, 264 m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14, 265 m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags, 266 m_state.context.gpr.__cs, m_state.context.gpr.__fs, m_state.context.gpr.__gs); 267 return m_state.GetError(e_regSetGPR, Write); 268} 269 270kern_return_t 271DNBArchImplX86_64::SetFPUState() 272{ 273 m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), x86_FLOAT_STATE64, (thread_state_t)&m_state.context.fpu, x86_FLOAT_STATE64_COUNT)); 274 return m_state.GetError(e_regSetFPU, Write); 275} 276 277kern_return_t 278DNBArchImplX86_64::SetEXCState() 279{ 280 m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->ThreadID(), x86_EXCEPTION_STATE64, (thread_state_t)&m_state.context.exc, X86_EXCEPTION_STATE64_COUNT)); 281 return m_state.GetError(e_regSetEXC, Write); 282} 283 284void 285DNBArchImplX86_64::ThreadWillResume() 286{ 287 // Do we need to step this thread? If so, let the mach thread tell us so. 288 if (m_thread->IsStepping()) 289 { 290 // This is the primary thread, let the arch do anything it needs 291 EnableHardwareSingleStep(true) == KERN_SUCCESS; 292 } 293} 294 295bool 296DNBArchImplX86_64::ThreadDidStop() 297{ 298 bool success = true; 299 300 m_state.InvalidateAllRegisterStates(); 301 302 // Are we stepping a single instruction? 303 if (GetGPRState(true) == KERN_SUCCESS) 304 { 305 // We are single stepping, was this the primary thread? 306 if (m_thread->IsStepping()) 307 { 308 // This was the primary thread, we need to clear the trace 309 // bit if so. 310 success = EnableHardwareSingleStep(false) == KERN_SUCCESS; 311 } 312 else 313 { 314 // The MachThread will automatically restore the suspend count 315 // in ThreadDidStop(), so we don't need to do anything here if 316 // we weren't the primary thread the last time 317 } 318 } 319 return success; 320} 321 322bool 323DNBArchImplX86_64::NotifyException(MachException::Data& exc) 324{ 325 switch (exc.exc_type) 326 { 327 case EXC_BAD_ACCESS: 328 break; 329 case EXC_BAD_INSTRUCTION: 330 break; 331 case EXC_ARITHMETIC: 332 break; 333 case EXC_EMULATION: 334 break; 335 case EXC_SOFTWARE: 336 break; 337 case EXC_BREAKPOINT: 338 if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) 339 { 340 nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS); 341 if (pc != INVALID_NUB_ADDRESS && pc > 0) 342 { 343 pc -= 1; 344 // Check for a breakpoint at one byte prior to the current PC value 345 // since the PC will be just past the trap. 346 347 nub_break_t breakID = m_thread->Process()->Breakpoints().FindIDByAddress(pc); 348 if (NUB_BREAK_ID_IS_VALID(breakID)) 349 { 350 // Backup the PC for i386 since the trap was taken and the PC 351 // is at the address following the single byte trap instruction. 352 if (m_state.context.gpr.__rip > 0) 353 { 354 m_state.context.gpr.__rip = pc; 355 // Write the new PC back out 356 SetGPRState (); 357 } 358 } 359 return true; 360 } 361 } 362 break; 363 case EXC_SYSCALL: 364 break; 365 case EXC_MACH_SYSCALL: 366 break; 367 case EXC_RPC_ALERT: 368 break; 369 } 370 return false; 371} 372 373 374// Set the single step bit in the processor status register. 375kern_return_t 376DNBArchImplX86_64::EnableHardwareSingleStep (bool enable) 377{ 378 if (GetGPRState(false) == KERN_SUCCESS) 379 { 380 const uint32_t trace_bit = 0x100u; 381 if (enable) 382 m_state.context.gpr.__rflags |= trace_bit; 383 else 384 m_state.context.gpr.__rflags &= ~trace_bit; 385 return SetGPRState(); 386 } 387 return m_state.GetError(e_regSetGPR, Read); 388} 389 390 391//---------------------------------------------------------------------- 392// Register information defintions 393//---------------------------------------------------------------------- 394 395enum 396{ 397 gpr_rax = 0, 398 gpr_rbx, 399 gpr_rcx, 400 gpr_rdx, 401 gpr_rdi, 402 gpr_rsi, 403 gpr_rbp, 404 gpr_rsp, 405 gpr_r8, 406 gpr_r9, 407 gpr_r10, 408 gpr_r11, 409 gpr_r12, 410 gpr_r13, 411 gpr_r14, 412 gpr_r15, 413 gpr_rip, 414 gpr_rflags, 415 gpr_cs, 416 gpr_fs, 417 gpr_gs, 418 k_num_gpr_regs 419}; 420 421enum { 422 fpu_fcw, 423 fpu_fsw, 424 fpu_ftw, 425 fpu_fop, 426 fpu_ip, 427 fpu_cs, 428 fpu_dp, 429 fpu_ds, 430 fpu_mxcsr, 431 fpu_mxcsrmask, 432 fpu_stmm0, 433 fpu_stmm1, 434 fpu_stmm2, 435 fpu_stmm3, 436 fpu_stmm4, 437 fpu_stmm5, 438 fpu_stmm6, 439 fpu_stmm7, 440 fpu_xmm0, 441 fpu_xmm1, 442 fpu_xmm2, 443 fpu_xmm3, 444 fpu_xmm4, 445 fpu_xmm5, 446 fpu_xmm6, 447 fpu_xmm7, 448 fpu_xmm8, 449 fpu_xmm9, 450 fpu_xmm10, 451 fpu_xmm11, 452 fpu_xmm12, 453 fpu_xmm13, 454 fpu_xmm14, 455 fpu_xmm15, 456 k_num_fpu_regs, 457 458 // Aliases 459 fpu_fctrl = fpu_fcw, 460 fpu_fstat = fpu_fsw, 461 fpu_ftag = fpu_ftw, 462 fpu_fiseg = fpu_cs, 463 fpu_fioff = fpu_ip, 464 fpu_foseg = fpu_ds, 465 fpu_fooff = fpu_dp 466}; 467 468enum { 469 exc_trapno, 470 exc_err, 471 exc_faultvaddr, 472 k_num_exc_regs, 473}; 474 475 476enum gcc_dwarf_regnums 477{ 478 gcc_dwarf_rax = 0, 479 gcc_dwarf_rdx, 480 gcc_dwarf_rcx, 481 gcc_dwarf_rbx, 482 gcc_dwarf_rsi, 483 gcc_dwarf_rdi, 484 gcc_dwarf_rbp, 485 gcc_dwarf_rsp, 486 gcc_dwarf_r8, 487 gcc_dwarf_r9, 488 gcc_dwarf_r10, 489 gcc_dwarf_r11, 490 gcc_dwarf_r12, 491 gcc_dwarf_r13, 492 gcc_dwarf_r14, 493 gcc_dwarf_r15, 494 gcc_dwarf_rip, 495 gcc_dwarf_xmm0, 496 gcc_dwarf_xmm1, 497 gcc_dwarf_xmm2, 498 gcc_dwarf_xmm3, 499 gcc_dwarf_xmm4, 500 gcc_dwarf_xmm5, 501 gcc_dwarf_xmm6, 502 gcc_dwarf_xmm7, 503 gcc_dwarf_xmm8, 504 gcc_dwarf_xmm9, 505 gcc_dwarf_xmm10, 506 gcc_dwarf_xmm11, 507 gcc_dwarf_xmm12, 508 gcc_dwarf_xmm13, 509 gcc_dwarf_xmm14, 510 gcc_dwarf_xmm15, 511 gcc_dwarf_stmm0, 512 gcc_dwarf_stmm1, 513 gcc_dwarf_stmm2, 514 gcc_dwarf_stmm3, 515 gcc_dwarf_stmm4, 516 gcc_dwarf_stmm5, 517 gcc_dwarf_stmm6, 518 gcc_dwarf_stmm7, 519 520}; 521 522enum gdb_regnums 523{ 524 gdb_rax = 0, 525 gdb_rbx = 1, 526 gdb_rcx = 2, 527 gdb_rdx = 3, 528 gdb_rsi = 4, 529 gdb_rdi = 5, 530 gdb_rbp = 6, 531 gdb_rsp = 7, 532 gdb_r8 = 8, 533 gdb_r9 = 9, 534 gdb_r10 = 10, 535 gdb_r11 = 11, 536 gdb_r12 = 12, 537 gdb_r13 = 13, 538 gdb_r14 = 14, 539 gdb_r15 = 15, 540 gdb_rip = 16, 541 gdb_rflags = 17, 542 gdb_cs = 18, 543 gdb_ss = 19, 544 gdb_ds = 20, 545 gdb_es = 21, 546 gdb_fs = 22, 547 gdb_gs = 23, 548 gdb_stmm0 = 24, 549 gdb_stmm1 = 25, 550 gdb_stmm2 = 26, 551 gdb_stmm3 = 27, 552 gdb_stmm4 = 28, 553 gdb_stmm5 = 29, 554 gdb_stmm6 = 30, 555 gdb_stmm7 = 31, 556 gdb_fctrl = 32, gdb_fcw = gdb_fctrl, 557 gdb_fstat = 33, gdb_fsw = gdb_fstat, 558 gdb_ftag = 34, gdb_ftw = gdb_ftag, 559 gdb_fiseg = 35, gdb_fpu_cs = gdb_fiseg, 560 gdb_fioff = 36, gdb_ip = gdb_fioff, 561 gdb_foseg = 37, gdb_fpu_ds = gdb_foseg, 562 gdb_fooff = 38, gdb_dp = gdb_fooff, 563 gdb_fop = 39, 564 gdb_xmm0 = 40, 565 gdb_xmm1 = 41, 566 gdb_xmm2 = 42, 567 gdb_xmm3 = 43, 568 gdb_xmm4 = 44, 569 gdb_xmm5 = 45, 570 gdb_xmm6 = 46, 571 gdb_xmm7 = 47, 572 gdb_xmm8 = 48, 573 gdb_xmm9 = 49, 574 gdb_xmm10 = 50, 575 gdb_xmm11 = 51, 576 gdb_xmm12 = 52, 577 gdb_xmm13 = 53, 578 gdb_xmm14 = 54, 579 gdb_xmm15 = 55, 580 gdb_mxcsr = 56, 581}; 582 583#define GPR_OFFSET(reg) (offsetof (DNBArchImplX86_64::GPR, __##reg)) 584#define FPU_OFFSET(reg) (offsetof (DNBArchImplX86_64::FPU, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu)) 585#define EXC_OFFSET(reg) (offsetof (DNBArchImplX86_64::EXC, __##reg) + offsetof (DNBArchImplX86_64::Context, exc)) 586 587#define GPR_SIZE(reg) (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg)) 588#define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg)) 589#define FPU_SIZE_MMST(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg)) 590#define FPU_SIZE_XMM(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg)) 591#define EXC_SIZE(reg) (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg)) 592 593// These macros will auto define the register name, alt name, register size, 594// register offset, encoding, format and native register. This ensures that 595// the register state structures are defined correctly and have the correct 596// sizes and offsets. 597#define DEFINE_GPR(reg) { e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), gcc_dwarf_##reg, gcc_dwarf_##reg, INVALID_NUB_REGNUM, gdb_##reg } 598#define DEFINE_GPR_ALT(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), gcc_dwarf_##reg, gcc_dwarf_##reg, gen, gdb_##reg } 599#define DEFINE_GPR_ALT2(reg, alt) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gdb_##reg } 600 601// General purpose registers for 64 bit 602const DNBRegisterInfo 603DNBArchImplX86_64::g_gpr_registers[] = 604{ 605 DEFINE_GPR (rax), 606 DEFINE_GPR (rbx), 607 DEFINE_GPR (rcx), 608 DEFINE_GPR (rdx), 609 DEFINE_GPR (rdi), 610 DEFINE_GPR (rsi), 611 DEFINE_GPR_ALT (rbp, "fp", GENERIC_REGNUM_FP), 612 DEFINE_GPR_ALT (rsp, "sp", GENERIC_REGNUM_SP), 613 DEFINE_GPR (r8), 614 DEFINE_GPR (r9), 615 DEFINE_GPR (r10), 616 DEFINE_GPR (r11), 617 DEFINE_GPR (r12), 618 DEFINE_GPR (r13), 619 DEFINE_GPR (r14), 620 DEFINE_GPR (r15), 621 DEFINE_GPR_ALT (rip, "pc", GENERIC_REGNUM_PC), 622 DEFINE_GPR_ALT2 (rflags, "flags"), 623 DEFINE_GPR_ALT2 (cs, NULL), 624 DEFINE_GPR_ALT2 (fs, NULL), 625 DEFINE_GPR_ALT2 (gs, NULL), 626}; 627 628// Floating point registers 64 bit 629const DNBRegisterInfo 630DNBArchImplX86_64::g_fpu_registers[] = 631{ 632 { e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , FPU_OFFSET(fcw) , -1, -1, -1, -1 }, 633 { e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , FPU_OFFSET(fsw) , -1, -1, -1, -1 }, 634 { e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , FPU_OFFSET(ftw) , -1, -1, -1, -1 }, 635 { e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , FPU_OFFSET(fop) , -1, -1, -1, -1 }, 636 { e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , FPU_OFFSET(ip) , -1, -1, -1, -1 }, 637 { e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , FPU_OFFSET(cs) , -1, -1, -1, -1 }, 638 { e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , FPU_OFFSET(dp) , -1, -1, -1, -1 }, 639 { e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , FPU_OFFSET(ds) , -1, -1, -1, -1 }, 640 { e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , FPU_OFFSET(mxcsr) , -1, -1, -1, -1 }, 641 { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , -1, -1, -1, -1 }, 642 643 { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), gcc_dwarf_stmm0, gcc_dwarf_stmm0, -1, gdb_stmm0 }, 644 { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), gcc_dwarf_stmm1, gcc_dwarf_stmm1, -1, gdb_stmm1 }, 645 { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), gcc_dwarf_stmm2, gcc_dwarf_stmm2, -1, gdb_stmm2 }, 646 { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), gcc_dwarf_stmm3, gcc_dwarf_stmm3, -1, gdb_stmm3 }, 647 { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), gcc_dwarf_stmm4, gcc_dwarf_stmm4, -1, gdb_stmm4 }, 648 { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), gcc_dwarf_stmm5, gcc_dwarf_stmm5, -1, gdb_stmm5 }, 649 { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), gcc_dwarf_stmm6, gcc_dwarf_stmm6, -1, gdb_stmm6 }, 650 { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), gcc_dwarf_stmm7, gcc_dwarf_stmm7, -1, gdb_stmm7 }, 651 652 { e_regSetFPU, fpu_xmm0 , "xmm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0) , FPU_OFFSET(xmm0) , gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , -1, gdb_xmm0 }, 653 { e_regSetFPU, fpu_xmm1 , "xmm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1) , FPU_OFFSET(xmm1) , gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , -1, gdb_xmm1 }, 654 { e_regSetFPU, fpu_xmm2 , "xmm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2) , FPU_OFFSET(xmm2) , gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , -1, gdb_xmm2 }, 655 { e_regSetFPU, fpu_xmm3 , "xmm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3) , FPU_OFFSET(xmm3) , gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , -1, gdb_xmm3 }, 656 { e_regSetFPU, fpu_xmm4 , "xmm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4) , FPU_OFFSET(xmm4) , gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , -1, gdb_xmm4 }, 657 { e_regSetFPU, fpu_xmm5 , "xmm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5) , FPU_OFFSET(xmm5) , gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , -1, gdb_xmm5 }, 658 { e_regSetFPU, fpu_xmm6 , "xmm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6) , FPU_OFFSET(xmm6) , gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , -1, gdb_xmm6 }, 659 { e_regSetFPU, fpu_xmm7 , "xmm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7) , FPU_OFFSET(xmm7) , gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , -1, gdb_xmm7 }, 660 { e_regSetFPU, fpu_xmm8 , "xmm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8) , FPU_OFFSET(xmm8) , gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , -1, gdb_xmm8 }, 661 { e_regSetFPU, fpu_xmm9 , "xmm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9) , FPU_OFFSET(xmm9) , gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , -1, gdb_xmm9 }, 662 { e_regSetFPU, fpu_xmm10, "xmm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10) , FPU_OFFSET(xmm10), gcc_dwarf_xmm10, gcc_dwarf_xmm10, -1, gdb_xmm10 }, 663 { e_regSetFPU, fpu_xmm11, "xmm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11) , FPU_OFFSET(xmm11), gcc_dwarf_xmm11, gcc_dwarf_xmm11, -1, gdb_xmm11 }, 664 { e_regSetFPU, fpu_xmm12, "xmm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12) , FPU_OFFSET(xmm12), gcc_dwarf_xmm12, gcc_dwarf_xmm12, -1, gdb_xmm12 }, 665 { e_regSetFPU, fpu_xmm13, "xmm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13) , FPU_OFFSET(xmm13), gcc_dwarf_xmm13, gcc_dwarf_xmm13, -1, gdb_xmm13 }, 666 { e_regSetFPU, fpu_xmm14, "xmm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14) , FPU_OFFSET(xmm14), gcc_dwarf_xmm14, gcc_dwarf_xmm14, -1, gdb_xmm14 }, 667 { e_regSetFPU, fpu_xmm15, "xmm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15) , FPU_OFFSET(xmm15), gcc_dwarf_xmm15, gcc_dwarf_xmm15, -1, gdb_xmm15 }, 668}; 669 670// Exception registers 671 672const DNBRegisterInfo 673DNBArchImplX86_64::g_exc_registers[] = 674{ 675 { e_regSetEXC, exc_trapno, "trapno" , NULL, Uint, Hex, EXC_SIZE (trapno) , EXC_OFFSET (trapno) , -1, -1, -1, -1 }, 676 { e_regSetEXC, exc_err, "err" , NULL, Uint, Hex, EXC_SIZE (err) , EXC_OFFSET (err) , -1, -1, -1, -1 }, 677 { e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr) , -1, -1, -1, -1 } 678}; 679 680// Number of registers in each register set 681const size_t DNBArchImplX86_64::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); 682const size_t DNBArchImplX86_64::k_num_fpu_registers = sizeof(g_fpu_registers)/sizeof(DNBRegisterInfo); 683const size_t DNBArchImplX86_64::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); 684const size_t DNBArchImplX86_64::k_num_all_registers = k_num_gpr_registers + k_num_fpu_registers + k_num_exc_registers; 685 686//---------------------------------------------------------------------- 687// Register set definitions. The first definitions at register set index 688// of zero is for all registers, followed by other registers sets. The 689// register information for the all register set need not be filled in. 690//---------------------------------------------------------------------- 691const DNBRegisterSetInfo 692DNBArchImplX86_64::g_reg_sets[] = 693{ 694 { "x86_64 Registers", NULL, k_num_all_registers }, 695 { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, 696 { "Floating Point Registers", g_fpu_registers, k_num_fpu_registers }, 697 { "Exception State Registers", g_exc_registers, k_num_exc_registers } 698}; 699// Total number of register sets for this architecture 700const size_t DNBArchImplX86_64::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); 701 702 703DNBArchProtocol * 704DNBArchImplX86_64::Create (MachThread *thread) 705{ 706 return new DNBArchImplX86_64 (thread); 707} 708 709const uint8_t * const 710DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size) 711{ 712 static const uint8_t g_breakpoint_opcode[] = { 0xCC }; 713 if (byte_size == 1) 714 return g_breakpoint_opcode; 715 return NULL; 716} 717 718const DNBRegisterSetInfo * 719DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets) 720{ 721 *num_reg_sets = k_num_register_sets; 722 return g_reg_sets; 723} 724 725void 726DNBArchImplX86_64::Initialize() 727{ 728 DNBArchPluginInfo arch_plugin_info = 729 { 730 CPU_TYPE_X86_64, 731 DNBArchImplX86_64::Create, 732 DNBArchImplX86_64::GetRegisterSetInfo, 733 DNBArchImplX86_64::SoftwareBreakpointOpcode 734 }; 735 736 // Register this arch plug-in with the main protocol class 737 DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); 738} 739 740bool 741DNBArchImplX86_64::GetRegisterValue(int set, int reg, DNBRegisterValue *value) 742{ 743 if (set == REGISTER_SET_GENERIC) 744 { 745 switch (reg) 746 { 747 case GENERIC_REGNUM_PC: // Program Counter 748 set = e_regSetGPR; 749 reg = gpr_rip; 750 break; 751 752 case GENERIC_REGNUM_SP: // Stack Pointer 753 set = e_regSetGPR; 754 reg = gpr_rsp; 755 break; 756 757 case GENERIC_REGNUM_FP: // Frame Pointer 758 set = e_regSetGPR; 759 reg = gpr_rbp; 760 break; 761 762 case GENERIC_REGNUM_FLAGS: // Processor flags register 763 set = e_regSetGPR; 764 reg = gpr_rflags; 765 break; 766 767 case GENERIC_REGNUM_RA: // Return Address 768 default: 769 return false; 770 } 771 } 772 773 if (GetRegisterState(set, false) != KERN_SUCCESS) 774 return false; 775 776 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 777 if (regInfo) 778 { 779 value->info = *regInfo; 780 switch (set) 781 { 782 case e_regSetGPR: 783 if (reg < k_num_gpr_registers) 784 { 785 value->value.uint64 = ((uint64_t*)(&m_state.context.gpr))[reg]; 786 return true; 787 } 788 break; 789 790 case e_regSetFPU: 791 switch (reg) 792 { 793 case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.__fpu_fcw)); return true; 794 case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.__fpu_fsw)); return true; 795 case fpu_ftw: value->value.uint8 = m_state.context.fpu.__fpu_ftw; return true; 796 case fpu_fop: value->value.uint16 = m_state.context.fpu.__fpu_fop; return true; 797 case fpu_ip: value->value.uint32 = m_state.context.fpu.__fpu_ip; return true; 798 case fpu_cs: value->value.uint16 = m_state.context.fpu.__fpu_cs; return true; 799 case fpu_dp: value->value.uint32 = m_state.context.fpu.__fpu_dp; return true; 800 case fpu_ds: value->value.uint16 = m_state.context.fpu.__fpu_ds; return true; 801 case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.__fpu_mxcsr; return true; 802 case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.__fpu_mxcsrmask; return true; 803 804 case fpu_stmm0: 805 case fpu_stmm1: 806 case fpu_stmm2: 807 case fpu_stmm3: 808 case fpu_stmm4: 809 case fpu_stmm5: 810 case fpu_stmm6: 811 case fpu_stmm7: 812 memcpy(&value->value.uint8, &m_state.context.fpu.__fpu_stmm0 + (reg - fpu_stmm0), 10); 813 return true; 814 815 case fpu_xmm0: 816 case fpu_xmm1: 817 case fpu_xmm2: 818 case fpu_xmm3: 819 case fpu_xmm4: 820 case fpu_xmm5: 821 case fpu_xmm6: 822 case fpu_xmm7: 823 case fpu_xmm8: 824 case fpu_xmm9: 825 case fpu_xmm10: 826 case fpu_xmm11: 827 case fpu_xmm12: 828 case fpu_xmm13: 829 case fpu_xmm14: 830 case fpu_xmm15: 831 memcpy(&value->value.uint8, &m_state.context.fpu.__fpu_xmm0 + (reg - fpu_xmm0), 16); 832 return true; 833 } 834 break; 835 836 case e_regSetEXC: 837 switch (reg) 838 { 839 case exc_trapno: value->value.uint32 = m_state.context.exc.__trapno; return true; 840 case exc_err: value->value.uint32 = m_state.context.exc.__err; return true; 841 case exc_faultvaddr:value->value.uint64 = m_state.context.exc.__faultvaddr; return true; 842 } 843 break; 844 } 845 } 846 return false; 847} 848 849 850bool 851DNBArchImplX86_64::SetRegisterValue(int set, int reg, const DNBRegisterValue *value) 852{ 853 if (set == REGISTER_SET_GENERIC) 854 { 855 switch (reg) 856 { 857 case GENERIC_REGNUM_PC: // Program Counter 858 set = e_regSetGPR; 859 reg = gpr_rip; 860 break; 861 862 case GENERIC_REGNUM_SP: // Stack Pointer 863 set = e_regSetGPR; 864 reg = gpr_rsp; 865 break; 866 867 case GENERIC_REGNUM_FP: // Frame Pointer 868 set = e_regSetGPR; 869 reg = gpr_rbp; 870 break; 871 872 case GENERIC_REGNUM_FLAGS: // Processor flags register 873 set = e_regSetGPR; 874 reg = gpr_rflags; 875 break; 876 877 case GENERIC_REGNUM_RA: // Return Address 878 default: 879 return false; 880 } 881 } 882 883 if (GetRegisterState(set, false) != KERN_SUCCESS) 884 return false; 885 886 bool success = false; 887 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 888 if (regInfo) 889 { 890 switch (set) 891 { 892 case e_regSetGPR: 893 if (reg < k_num_gpr_registers) 894 { 895 ((uint64_t*)(&m_state.context.gpr))[reg] = value->value.uint64; 896 success = true; 897 } 898 break; 899 900 case e_regSetFPU: 901 switch (reg) 902 { 903 case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.__fpu_fcw)) = value->value.uint16; success = true; break; 904 case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.__fpu_fsw)) = value->value.uint16; success = true; break; 905 case fpu_ftw: m_state.context.fpu.__fpu_ftw = value->value.uint8; success = true; break; 906 case fpu_fop: m_state.context.fpu.__fpu_fop = value->value.uint16; success = true; break; 907 case fpu_ip: m_state.context.fpu.__fpu_ip = value->value.uint32; success = true; break; 908 case fpu_cs: m_state.context.fpu.__fpu_cs = value->value.uint16; success = true; break; 909 case fpu_dp: m_state.context.fpu.__fpu_dp = value->value.uint32; success = true; break; 910 case fpu_ds: m_state.context.fpu.__fpu_ds = value->value.uint16; success = true; break; 911 case fpu_mxcsr: m_state.context.fpu.__fpu_mxcsr = value->value.uint32; success = true; break; 912 case fpu_mxcsrmask: m_state.context.fpu.__fpu_mxcsrmask = value->value.uint32; success = true; break; 913 914 case fpu_stmm0: 915 case fpu_stmm1: 916 case fpu_stmm2: 917 case fpu_stmm3: 918 case fpu_stmm4: 919 case fpu_stmm5: 920 case fpu_stmm6: 921 case fpu_stmm7: 922 memcpy (&m_state.context.fpu.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10); 923 success = true; 924 break; 925 926 case fpu_xmm0: 927 case fpu_xmm1: 928 case fpu_xmm2: 929 case fpu_xmm3: 930 case fpu_xmm4: 931 case fpu_xmm5: 932 case fpu_xmm6: 933 case fpu_xmm7: 934 case fpu_xmm8: 935 case fpu_xmm9: 936 case fpu_xmm10: 937 case fpu_xmm11: 938 case fpu_xmm12: 939 case fpu_xmm13: 940 case fpu_xmm14: 941 case fpu_xmm15: 942 memcpy (&m_state.context.fpu.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16); 943 success = true; 944 break; 945 } 946 break; 947 948 case e_regSetEXC: 949 switch (reg) 950 { 951 case exc_trapno: m_state.context.exc.__trapno = value->value.uint32; success = true; break; 952 case exc_err: m_state.context.exc.__err = value->value.uint32; success = true; break; 953 case exc_faultvaddr:m_state.context.exc.__faultvaddr = value->value.uint64; success = true; break; 954 } 955 break; 956 } 957 } 958 959 if (success) 960 return SetRegisterState(set) == KERN_SUCCESS; 961 return false; 962} 963 964 965nub_size_t 966DNBArchImplX86_64::GetRegisterContext (void *buf, nub_size_t buf_len) 967{ 968 nub_size_t size = sizeof (m_state.context); 969 970 if (buf && buf_len) 971 { 972 if (size > buf_len) 973 size = buf_len; 974 975 bool force = false; 976 if (GetGPRState(force) | GetFPUState(force) | GetEXCState(force)) 977 return 0; 978 ::memcpy (buf, &m_state.context, size); 979 } 980 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); 981 // Return the size of the register context even if NULL was passed in 982 return size; 983} 984 985nub_size_t 986DNBArchImplX86_64::SetRegisterContext (const void *buf, nub_size_t buf_len) 987{ 988 nub_size_t size = sizeof (m_state.context); 989 if (buf == NULL || buf_len == 0) 990 size = 0; 991 992 if (size) 993 { 994 if (size > buf_len) 995 size = buf_len; 996 997 ::memcpy (&m_state.context, buf, size); 998 SetGPRState(); 999 SetFPUState(); 1000 SetEXCState(); 1001 } 1002 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); 1003 return size; 1004} 1005 1006 1007kern_return_t 1008DNBArchImplX86_64::GetRegisterState(int set, bool force) 1009{ 1010 switch (set) 1011 { 1012 case e_regSetALL: return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); 1013 case e_regSetGPR: return GetGPRState(force); 1014 case e_regSetFPU: return GetFPUState(force); 1015 case e_regSetEXC: return GetEXCState(force); 1016 default: break; 1017 } 1018 return KERN_INVALID_ARGUMENT; 1019} 1020 1021kern_return_t 1022DNBArchImplX86_64::SetRegisterState(int set) 1023{ 1024 // Make sure we have a valid context to set. 1025 if (RegisterSetStateIsValid(set)) 1026 { 1027 switch (set) 1028 { 1029 case e_regSetALL: return SetGPRState() | SetFPUState() | SetEXCState(); 1030 case e_regSetGPR: return SetGPRState(); 1031 case e_regSetFPU: return SetFPUState(); 1032 case e_regSetEXC: return SetEXCState(); 1033 default: break; 1034 } 1035 } 1036 return KERN_INVALID_ARGUMENT; 1037} 1038 1039bool 1040DNBArchImplX86_64::RegisterSetStateIsValid (int set) const 1041{ 1042 return m_state.RegsAreValid(set); 1043} 1044 1045 1046 1047#endif // #if defined (__i386__) || defined (__x86_64__) 1048