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 #include <sys/types.h> 18 #include <sys/sysctl.h> 19 20 #include "MacOSX/x86_64/DNBArchImplX86_64.h" 21 #include "../HasAVX.h" 22 #include "DNBLog.h" 23 #include "MachThread.h" 24 #include "MachProcess.h" 25 #include <mach/mach.h> 26 #include <stdlib.h> 27 28 #if defined (LLDB_DEBUGSERVER_RELEASE) || defined (LLDB_DEBUGSERVER_DEBUG) 29 enum debugState { 30 debugStateUnknown, 31 debugStateOff, 32 debugStateOn 33 }; 34 35 static debugState sFPUDebugState = debugStateUnknown; 36 static debugState sAVXForceState = debugStateUnknown; 37 38 static bool DebugFPURegs () 39 { 40 if (sFPUDebugState == debugStateUnknown) 41 { 42 if (getenv("DNB_DEBUG_FPU_REGS")) 43 sFPUDebugState = debugStateOn; 44 else 45 sFPUDebugState = debugStateOff; 46 } 47 48 return (sFPUDebugState == debugStateOn); 49 } 50 51 static bool ForceAVXRegs () 52 { 53 if (sFPUDebugState == debugStateUnknown) 54 { 55 if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS")) 56 sAVXForceState = debugStateOn; 57 else 58 sAVXForceState = debugStateOff; 59 } 60 61 return (sAVXForceState == debugStateOn); 62 } 63 64 #define DEBUG_FPU_REGS (DebugFPURegs()) 65 #define FORCE_AVX_REGS (ForceAVXRegs()) 66 #else 67 #define DEBUG_FPU_REGS (0) 68 #define FORCE_AVX_REGS (0) 69 #endif 70 71 72 extern "C" bool 73 CPUHasAVX() 74 { 75 enum AVXPresence 76 { 77 eAVXUnknown = -1, 78 eAVXNotPresent = 0, 79 eAVXPresent = 1 80 }; 81 82 static AVXPresence g_has_avx = eAVXUnknown; 83 if (g_has_avx == eAVXUnknown) 84 { 85 g_has_avx = eAVXNotPresent; 86 87 // Only xnu-2020 or later has AVX support, any versions before 88 // this have a busted thread_get_state RPC where it would truncate 89 // the thread state buffer (<rdar://problem/10122874>). So we need to 90 // verify the kernel version number manually or disable AVX support. 91 int mib[2]; 92 char buffer[1024]; 93 size_t length = sizeof(buffer); 94 uint64_t xnu_version = 0; 95 mib[0] = CTL_KERN; 96 mib[1] = KERN_VERSION; 97 int err = ::sysctl(mib, 2, &buffer, &length, NULL, 0); 98 if (err == 0) 99 { 100 const char *xnu = strstr (buffer, "xnu-"); 101 if (xnu) 102 { 103 const char *xnu_version_cstr = xnu + 4; 104 xnu_version = strtoull (xnu_version_cstr, NULL, 0); 105 if (xnu_version >= 2020 && xnu_version != ULLONG_MAX) 106 { 107 if (::HasAVX()) 108 { 109 g_has_avx = eAVXPresent; 110 } 111 } 112 } 113 } 114 DNBLogThreadedIf (LOG_THREAD, "CPUHasAVX(): g_has_avx = %i (err = %i, errno = %i, xnu_version = %llu)", g_has_avx, err, errno, xnu_version); 115 } 116 117 return (g_has_avx == eAVXPresent); 118 } 119 120 uint64_t 121 DNBArchImplX86_64::GetPC(uint64_t failValue) 122 { 123 // Get program counter 124 if (GetGPRState(false) == KERN_SUCCESS) 125 return m_state.context.gpr.__rip; 126 return failValue; 127 } 128 129 kern_return_t 130 DNBArchImplX86_64::SetPC(uint64_t value) 131 { 132 // Get program counter 133 kern_return_t err = GetGPRState(false); 134 if (err == KERN_SUCCESS) 135 { 136 m_state.context.gpr.__rip = value; 137 err = SetGPRState(); 138 } 139 return err == KERN_SUCCESS; 140 } 141 142 uint64_t 143 DNBArchImplX86_64::GetSP(uint64_t failValue) 144 { 145 // Get stack pointer 146 if (GetGPRState(false) == KERN_SUCCESS) 147 return m_state.context.gpr.__rsp; 148 return failValue; 149 } 150 151 // Uncomment the value below to verify the values in the debugger. 152 //#define DEBUG_GPR_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED 153 154 kern_return_t 155 DNBArchImplX86_64::GetGPRState(bool force) 156 { 157 if (force || m_state.GetError(e_regSetGPR, Read)) 158 { 159 #if DEBUG_GPR_VALUES 160 m_state.context.gpr.__rax = ('a' << 8) + 'x'; 161 m_state.context.gpr.__rbx = ('b' << 8) + 'x'; 162 m_state.context.gpr.__rcx = ('c' << 8) + 'x'; 163 m_state.context.gpr.__rdx = ('d' << 8) + 'x'; 164 m_state.context.gpr.__rdi = ('d' << 8) + 'i'; 165 m_state.context.gpr.__rsi = ('s' << 8) + 'i'; 166 m_state.context.gpr.__rbp = ('b' << 8) + 'p'; 167 m_state.context.gpr.__rsp = ('s' << 8) + 'p'; 168 m_state.context.gpr.__r8 = ('r' << 8) + '8'; 169 m_state.context.gpr.__r9 = ('r' << 8) + '9'; 170 m_state.context.gpr.__r10 = ('r' << 8) + 'a'; 171 m_state.context.gpr.__r11 = ('r' << 8) + 'b'; 172 m_state.context.gpr.__r12 = ('r' << 8) + 'c'; 173 m_state.context.gpr.__r13 = ('r' << 8) + 'd'; 174 m_state.context.gpr.__r14 = ('r' << 8) + 'e'; 175 m_state.context.gpr.__r15 = ('r' << 8) + 'f'; 176 m_state.context.gpr.__rip = ('i' << 8) + 'p'; 177 m_state.context.gpr.__rflags = ('f' << 8) + 'l'; 178 m_state.context.gpr.__cs = ('c' << 8) + 's'; 179 m_state.context.gpr.__fs = ('f' << 8) + 's'; 180 m_state.context.gpr.__gs = ('g' << 8) + 's'; 181 m_state.SetError(e_regSetGPR, Read, 0); 182 #else 183 mach_msg_type_number_t count = e_regSetWordSizeGPR; 184 m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count)); 185 DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" 186 "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" 187 "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" 188 "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" 189 "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" 190 "\n\trip = %16.16llx" 191 "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", 192 m_thread->MachPortNumber(), x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT, 193 m_state.GetError(e_regSetGPR, Read), 194 m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx, 195 m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi, 196 m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8, 197 m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11, 198 m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14, 199 m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags, 200 m_state.context.gpr.__cs,m_state.context.gpr.__fs, m_state.context.gpr.__gs); 201 202 // DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x" 203 // "\n\trax = %16.16llx" 204 // "\n\trbx = %16.16llx" 205 // "\n\trcx = %16.16llx" 206 // "\n\trdx = %16.16llx" 207 // "\n\trdi = %16.16llx" 208 // "\n\trsi = %16.16llx" 209 // "\n\trbp = %16.16llx" 210 // "\n\trsp = %16.16llx" 211 // "\n\t r8 = %16.16llx" 212 // "\n\t r9 = %16.16llx" 213 // "\n\tr10 = %16.16llx" 214 // "\n\tr11 = %16.16llx" 215 // "\n\tr12 = %16.16llx" 216 // "\n\tr13 = %16.16llx" 217 // "\n\tr14 = %16.16llx" 218 // "\n\tr15 = %16.16llx" 219 // "\n\trip = %16.16llx" 220 // "\n\tflg = %16.16llx" 221 // "\n\t cs = %16.16llx" 222 // "\n\t fs = %16.16llx" 223 // "\n\t gs = %16.16llx", 224 // m_thread->MachPortNumber(), 225 // x86_THREAD_STATE64, 226 // x86_THREAD_STATE64_COUNT, 227 // m_state.GetError(e_regSetGPR, Read), 228 // m_state.context.gpr.__rax, 229 // m_state.context.gpr.__rbx, 230 // m_state.context.gpr.__rcx, 231 // m_state.context.gpr.__rdx, 232 // m_state.context.gpr.__rdi, 233 // m_state.context.gpr.__rsi, 234 // m_state.context.gpr.__rbp, 235 // m_state.context.gpr.__rsp, 236 // m_state.context.gpr.__r8, 237 // m_state.context.gpr.__r9, 238 // m_state.context.gpr.__r10, 239 // m_state.context.gpr.__r11, 240 // m_state.context.gpr.__r12, 241 // m_state.context.gpr.__r13, 242 // m_state.context.gpr.__r14, 243 // m_state.context.gpr.__r15, 244 // m_state.context.gpr.__rip, 245 // m_state.context.gpr.__rflags, 246 // m_state.context.gpr.__cs, 247 // m_state.context.gpr.__fs, 248 // m_state.context.gpr.__gs); 249 #endif 250 } 251 return m_state.GetError(e_regSetGPR, Read); 252 } 253 254 // Uncomment the value below to verify the values in the debugger. 255 //#define DEBUG_FPU_REGS 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED 256 257 kern_return_t 258 DNBArchImplX86_64::GetFPUState(bool force) 259 { 260 if (force || m_state.GetError(e_regSetFPU, Read)) 261 { 262 if (DEBUG_FPU_REGS) { 263 if (CPUHasAVX() || FORCE_AVX_REGS) 264 { 265 m_state.context.fpu.avx.__fpu_reserved[0] = -1; 266 m_state.context.fpu.avx.__fpu_reserved[1] = -1; 267 *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234; 268 *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678; 269 m_state.context.fpu.avx.__fpu_ftw = 1; 270 m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX; 271 m_state.context.fpu.avx.__fpu_fop = 2; 272 m_state.context.fpu.avx.__fpu_ip = 3; 273 m_state.context.fpu.avx.__fpu_cs = 4; 274 m_state.context.fpu.avx.__fpu_rsrv2 = UINT8_MAX; 275 m_state.context.fpu.avx.__fpu_dp = 5; 276 m_state.context.fpu.avx.__fpu_ds = 6; 277 m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX; 278 m_state.context.fpu.avx.__fpu_mxcsr = 8; 279 m_state.context.fpu.avx.__fpu_mxcsrmask = 9; 280 int i; 281 for (i=0; i<16; ++i) 282 { 283 if (i<10) 284 { 285 m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a'; 286 m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b'; 287 m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c'; 288 m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd'; 289 m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e'; 290 m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f'; 291 m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g'; 292 m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h'; 293 } 294 else 295 { 296 m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; 297 m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; 298 m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; 299 m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; 300 m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; 301 m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; 302 m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; 303 m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; 304 } 305 306 m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0' + 2 * i; 307 m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1' + 2 * i; 308 m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2' + 2 * i; 309 m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3' + 2 * i; 310 m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4' + 2 * i; 311 m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5' + 2 * i; 312 m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6' + 2 * i; 313 m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7' + 2 * i; 314 m_state.context.fpu.avx.__fpu_xmm8.__xmm_reg[i] = '8' + 2 * i; 315 m_state.context.fpu.avx.__fpu_xmm9.__xmm_reg[i] = '9' + 2 * i; 316 m_state.context.fpu.avx.__fpu_xmm10.__xmm_reg[i] = 'A' + 2 * i; 317 m_state.context.fpu.avx.__fpu_xmm11.__xmm_reg[i] = 'B' + 2 * i; 318 m_state.context.fpu.avx.__fpu_xmm12.__xmm_reg[i] = 'C' + 2 * i; 319 m_state.context.fpu.avx.__fpu_xmm13.__xmm_reg[i] = 'D' + 2 * i; 320 m_state.context.fpu.avx.__fpu_xmm14.__xmm_reg[i] = 'E' + 2 * i; 321 m_state.context.fpu.avx.__fpu_xmm15.__xmm_reg[i] = 'F' + 2 * i; 322 323 m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0' + i; 324 m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1' + i; 325 m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2' + i; 326 m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3' + i; 327 m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4' + i; 328 m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5' + i; 329 m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6' + i; 330 m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7' + i; 331 m_state.context.fpu.avx.__fpu_ymmh8.__xmm_reg[i] = '8' + i; 332 m_state.context.fpu.avx.__fpu_ymmh9.__xmm_reg[i] = '9' + i; 333 m_state.context.fpu.avx.__fpu_ymmh10.__xmm_reg[i] = 'A' + i; 334 m_state.context.fpu.avx.__fpu_ymmh11.__xmm_reg[i] = 'B' + i; 335 m_state.context.fpu.avx.__fpu_ymmh12.__xmm_reg[i] = 'C' + i; 336 m_state.context.fpu.avx.__fpu_ymmh13.__xmm_reg[i] = 'D' + i; 337 m_state.context.fpu.avx.__fpu_ymmh14.__xmm_reg[i] = 'E' + i; 338 m_state.context.fpu.avx.__fpu_ymmh15.__xmm_reg[i] = 'F' + i; 339 } 340 for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i) 341 m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN; 342 m_state.context.fpu.avx.__fpu_reserved1 = -1; 343 for (i=0; i<sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i) 344 m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN; 345 m_state.SetError(e_regSetFPU, Read, 0); 346 } 347 else 348 { 349 m_state.context.fpu.no_avx.__fpu_reserved[0] = -1; 350 m_state.context.fpu.no_avx.__fpu_reserved[1] = -1; 351 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234; 352 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678; 353 m_state.context.fpu.no_avx.__fpu_ftw = 1; 354 m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX; 355 m_state.context.fpu.no_avx.__fpu_fop = 2; 356 m_state.context.fpu.no_avx.__fpu_ip = 3; 357 m_state.context.fpu.no_avx.__fpu_cs = 4; 358 m_state.context.fpu.no_avx.__fpu_rsrv2 = 5; 359 m_state.context.fpu.no_avx.__fpu_dp = 6; 360 m_state.context.fpu.no_avx.__fpu_ds = 7; 361 m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX; 362 m_state.context.fpu.no_avx.__fpu_mxcsr = 8; 363 m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9; 364 int i; 365 for (i=0; i<16; ++i) 366 { 367 if (i<10) 368 { 369 m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a'; 370 m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b'; 371 m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c'; 372 m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd'; 373 m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e'; 374 m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f'; 375 m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g'; 376 m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h'; 377 } 378 else 379 { 380 m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; 381 m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; 382 m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; 383 m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; 384 m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; 385 m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; 386 m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; 387 m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; 388 } 389 390 m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0'; 391 m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1'; 392 m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2'; 393 m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3'; 394 m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4'; 395 m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5'; 396 m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6'; 397 m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7'; 398 m_state.context.fpu.no_avx.__fpu_xmm8.__xmm_reg[i] = '8'; 399 m_state.context.fpu.no_avx.__fpu_xmm9.__xmm_reg[i] = '9'; 400 m_state.context.fpu.no_avx.__fpu_xmm10.__xmm_reg[i] = 'A'; 401 m_state.context.fpu.no_avx.__fpu_xmm11.__xmm_reg[i] = 'B'; 402 m_state.context.fpu.no_avx.__fpu_xmm12.__xmm_reg[i] = 'C'; 403 m_state.context.fpu.no_avx.__fpu_xmm13.__xmm_reg[i] = 'D'; 404 m_state.context.fpu.no_avx.__fpu_xmm14.__xmm_reg[i] = 'E'; 405 m_state.context.fpu.no_avx.__fpu_xmm15.__xmm_reg[i] = 'F'; 406 } 407 for (i=0; i<sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i) 408 m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN; 409 m_state.context.fpu.no_avx.__fpu_reserved1 = -1; 410 m_state.SetError(e_regSetFPU, Read, 0); 411 } 412 } 413 else 414 { 415 if (CPUHasAVX() || FORCE_AVX_REGS) 416 { 417 mach_msg_type_number_t count = e_regSetWordSizeAVX; 418 m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, &count)); 419 DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &avx, %u (%u passed in) carp) => 0x%8.8x", 420 m_thread->MachPortNumber(), __x86_64_AVX_STATE, (uint32_t)count, 421 e_regSetWordSizeAVX, m_state.GetError(e_regSetFPU, Read)); 422 } 423 else 424 { 425 mach_msg_type_number_t count = e_regSetWordSizeFPU; 426 m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, &count)); 427 DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &fpu, %u (%u passed in) => 0x%8.8x", 428 m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, (uint32_t)count, 429 e_regSetWordSizeFPU, m_state.GetError(e_regSetFPU, Read)); 430 } 431 } 432 } 433 return m_state.GetError(e_regSetFPU, Read); 434 } 435 436 kern_return_t 437 DNBArchImplX86_64::GetEXCState(bool force) 438 { 439 if (force || m_state.GetError(e_regSetEXC, Read)) 440 { 441 mach_msg_type_number_t count = e_regSetWordSizeEXC; 442 m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count)); 443 } 444 return m_state.GetError(e_regSetEXC, Read); 445 } 446 447 kern_return_t 448 DNBArchImplX86_64::SetGPRState() 449 { 450 kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); 451 DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); 452 453 m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR)); 454 DNBLogThreadedIf (LOG_THREAD, "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" 455 "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" 456 "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" 457 "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" 458 "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" 459 "\n\trip = %16.16llx" 460 "\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", 461 m_thread->MachPortNumber(), __x86_64_THREAD_STATE, e_regSetWordSizeGPR, 462 m_state.GetError(e_regSetGPR, Write), 463 m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx, 464 m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi, 465 m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8, 466 m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11, 467 m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14, 468 m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags, 469 m_state.context.gpr.__cs, m_state.context.gpr.__fs, m_state.context.gpr.__gs); 470 return m_state.GetError(e_regSetGPR, Write); 471 } 472 473 kern_return_t 474 DNBArchImplX86_64::SetFPUState() 475 { 476 if (DEBUG_FPU_REGS) 477 { 478 m_state.SetError(e_regSetFPU, Write, 0); 479 return m_state.GetError(e_regSetFPU, Write); 480 } 481 else 482 { 483 if (CPUHasAVX() || FORCE_AVX_REGS) 484 { 485 m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, e_regSetWordSizeAVX)); 486 return m_state.GetError(e_regSetFPU, Write); 487 } 488 else 489 { 490 m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, e_regSetWordSizeFPU)); 491 return m_state.GetError(e_regSetFPU, Write); 492 } 493 } 494 } 495 496 kern_return_t 497 DNBArchImplX86_64::SetEXCState() 498 { 499 m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, e_regSetWordSizeEXC)); 500 return m_state.GetError(e_regSetEXC, Write); 501 } 502 503 kern_return_t 504 DNBArchImplX86_64::GetDBGState(bool force) 505 { 506 if (force || m_state.GetError(e_regSetDBG, Read)) 507 { 508 mach_msg_type_number_t count = e_regSetWordSizeDBG; 509 m_state.SetError(e_regSetDBG, Read, ::thread_get_state(m_thread->MachPortNumber(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, &count)); 510 } 511 return m_state.GetError(e_regSetDBG, Read); 512 } 513 514 kern_return_t 515 DNBArchImplX86_64::SetDBGState(bool also_set_on_task) 516 { 517 m_state.SetError(e_regSetDBG, Write, ::thread_set_state(m_thread->MachPortNumber(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG)); 518 if (also_set_on_task) 519 { 520 kern_return_t kret = ::task_set_state(m_thread->Process()->Task().TaskPort(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG); 521 if (kret != KERN_SUCCESS) 522 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::SetDBGState failed to set debug control register state: 0x%8.8x.", kret); 523 } 524 return m_state.GetError(e_regSetDBG, Write); 525 } 526 527 void 528 DNBArchImplX86_64::ThreadWillResume() 529 { 530 // Do we need to step this thread? If so, let the mach thread tell us so. 531 if (m_thread->IsStepping()) 532 { 533 // This is the primary thread, let the arch do anything it needs 534 EnableHardwareSingleStep(true); 535 } 536 537 // Reset the debug status register, if necessary, before we resume. 538 kern_return_t kret = GetDBGState(false); 539 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret); 540 if (kret != KERN_SUCCESS) 541 return; 542 543 DBG &debug_state = m_state.context.dbg; 544 bool need_reset = false; 545 uint32_t i, num = NumSupportedHardwareWatchpoints(); 546 for (i = 0; i < num; ++i) 547 if (IsWatchpointHit(debug_state, i)) 548 need_reset = true; 549 550 if (need_reset) 551 { 552 ClearWatchpointHits(debug_state); 553 kret = SetDBGState(false); 554 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret); 555 } 556 } 557 558 bool 559 DNBArchImplX86_64::ThreadDidStop() 560 { 561 bool success = true; 562 563 m_state.InvalidateAllRegisterStates(); 564 565 // Are we stepping a single instruction? 566 if (GetGPRState(true) == KERN_SUCCESS) 567 { 568 // We are single stepping, was this the primary thread? 569 if (m_thread->IsStepping()) 570 { 571 // This was the primary thread, we need to clear the trace 572 // bit if so. 573 success = EnableHardwareSingleStep(false) == KERN_SUCCESS; 574 } 575 else 576 { 577 // The MachThread will automatically restore the suspend count 578 // in ThreadDidStop(), so we don't need to do anything here if 579 // we weren't the primary thread the last time 580 } 581 } 582 return success; 583 } 584 585 bool 586 DNBArchImplX86_64::NotifyException(MachException::Data& exc) 587 { 588 switch (exc.exc_type) 589 { 590 case EXC_BAD_ACCESS: 591 break; 592 case EXC_BAD_INSTRUCTION: 593 break; 594 case EXC_ARITHMETIC: 595 break; 596 case EXC_EMULATION: 597 break; 598 case EXC_SOFTWARE: 599 break; 600 case EXC_BREAKPOINT: 601 if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) 602 { 603 // exc_code = EXC_I386_BPT 604 // 605 nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS); 606 if (pc != INVALID_NUB_ADDRESS && pc > 0) 607 { 608 pc -= 1; 609 // Check for a breakpoint at one byte prior to the current PC value 610 // since the PC will be just past the trap. 611 612 DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(pc); 613 if (bp) 614 { 615 // Backup the PC for i386 since the trap was taken and the PC 616 // is at the address following the single byte trap instruction. 617 if (m_state.context.gpr.__rip > 0) 618 { 619 m_state.context.gpr.__rip = pc; 620 // Write the new PC back out 621 SetGPRState (); 622 } 623 } 624 return true; 625 } 626 } 627 else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) 628 { 629 // exc_code = EXC_I386_SGL 630 // 631 // Check whether this corresponds to a watchpoint hit event. 632 // If yes, set the exc_sub_code to the data break address. 633 nub_addr_t addr = 0; 634 uint32_t hw_index = GetHardwareWatchpointHit(addr); 635 if (hw_index != INVALID_NUB_HW_INDEX) 636 { 637 exc.exc_data[1] = addr; 638 // Piggyback the hw_index in the exc.data. 639 exc.exc_data.push_back(hw_index); 640 } 641 642 return true; 643 } 644 break; 645 case EXC_SYSCALL: 646 break; 647 case EXC_MACH_SYSCALL: 648 break; 649 case EXC_RPC_ALERT: 650 break; 651 } 652 return false; 653 } 654 655 uint32_t 656 DNBArchImplX86_64::NumSupportedHardwareWatchpoints() 657 { 658 // Available debug address registers: dr0, dr1, dr2, dr3. 659 return 4; 660 } 661 662 static uint32_t 663 size_and_rw_bits(nub_size_t size, bool read, bool write) 664 { 665 uint32_t rw; 666 if (read) { 667 rw = 0x3; // READ or READ/WRITE 668 } else if (write) { 669 rw = 0x1; // WRITE 670 } else { 671 assert(0 && "read and write cannot both be false"); 672 } 673 674 switch (size) { 675 case 1: 676 return rw; 677 case 2: 678 return (0x1 << 2) | rw; 679 case 4: 680 return (0x3 << 2) | rw; 681 case 8: 682 return (0x2 << 2) | rw; 683 default: 684 assert(0 && "invalid size, must be one of 1, 2, 4, or 8"); 685 } 686 } 687 void 688 DNBArchImplX86_64::SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write) 689 { 690 // Set both dr7 (debug control register) and dri (debug address register). 691 692 // dr7{7-0} encodes the local/gloabl enable bits: 693 // global enable --. .-- local enable 694 // | | 695 // v v 696 // dr0 -> bits{1-0} 697 // dr1 -> bits{3-2} 698 // dr2 -> bits{5-4} 699 // dr3 -> bits{7-6} 700 // 701 // dr7{31-16} encodes the rw/len bits: 702 // b_x+3, b_x+2, b_x+1, b_x 703 // where bits{x+1, x} => rw 704 // 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io read-or-write (unused) 705 // and bits{x+3, x+2} => len 706 // 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte 707 // 708 // dr0 -> bits{19-16} 709 // dr1 -> bits{23-20} 710 // dr2 -> bits{27-24} 711 // dr3 -> bits{31-28} 712 debug_state.__dr7 |= (1 << (2*hw_index) | 713 size_and_rw_bits(size, read, write) << (16+4*hw_index)); 714 switch (hw_index) { 715 case 0: 716 debug_state.__dr0 = addr; break; 717 case 1: 718 debug_state.__dr1 = addr; break; 719 case 2: 720 debug_state.__dr2 = addr; break; 721 case 3: 722 debug_state.__dr3 = addr; break; 723 default: 724 assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); 725 } 726 return; 727 } 728 729 void 730 DNBArchImplX86_64::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) 731 { 732 debug_state.__dr7 &= ~(3 << (2*hw_index)); 733 switch (hw_index) { 734 case 0: 735 debug_state.__dr0 = 0; break; 736 case 1: 737 debug_state.__dr1 = 0; break; 738 case 2: 739 debug_state.__dr2 = 0; break; 740 case 3: 741 debug_state.__dr3 = 0; break; 742 default: 743 assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); 744 } 745 return; 746 } 747 748 bool 749 DNBArchImplX86_64::IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index) 750 { 751 // Check dr7 (debug control register) for local/global enable bits: 752 // global enable --. .-- local enable 753 // | | 754 // v v 755 // dr0 -> bits{1-0} 756 // dr1 -> bits{3-2} 757 // dr2 -> bits{5-4} 758 // dr3 -> bits{7-6} 759 return (debug_state.__dr7 & (3 << (2*hw_index))) == 0; 760 } 761 762 // Resets local copy of debug status register to wait for the next debug exception. 763 void 764 DNBArchImplX86_64::ClearWatchpointHits(DBG &debug_state) 765 { 766 // See also IsWatchpointHit(). 767 debug_state.__dr6 = 0; 768 return; 769 } 770 771 bool 772 DNBArchImplX86_64::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index) 773 { 774 // Check dr6 (debug status register) whether a watchpoint hits: 775 // is watchpoint hit? 776 // | 777 // v 778 // dr0 -> bits{0} 779 // dr1 -> bits{1} 780 // dr2 -> bits{2} 781 // dr3 -> bits{3} 782 return (debug_state.__dr6 & (1 << hw_index)); 783 } 784 785 nub_addr_t 786 DNBArchImplX86_64::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) 787 { 788 switch (hw_index) { 789 case 0: 790 return debug_state.__dr0; 791 case 1: 792 return debug_state.__dr1; 793 case 2: 794 return debug_state.__dr2; 795 case 3: 796 return debug_state.__dr3; 797 default: 798 assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); 799 } 800 } 801 802 bool 803 DNBArchImplX86_64::StartTransForHWP() 804 { 805 if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back) 806 DNBLogError ("%s inconsistent state detected, expected %d or %d, got: %d", __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state); 807 m_2pc_dbg_checkpoint = m_state.context.dbg; 808 m_2pc_trans_state = Trans_Pending; 809 return true; 810 } 811 bool 812 DNBArchImplX86_64::RollbackTransForHWP() 813 { 814 m_state.context.dbg = m_2pc_dbg_checkpoint; 815 if (m_2pc_trans_state != Trans_Pending) 816 DNBLogError ("%s inconsistent state detected, expected %d, got: %d", __FUNCTION__, Trans_Pending, m_2pc_trans_state); 817 m_2pc_trans_state = Trans_Rolled_Back; 818 kern_return_t kret = SetDBGState(false); 819 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret); 820 821 if (kret == KERN_SUCCESS) 822 return true; 823 else 824 return false; 825 } 826 bool 827 DNBArchImplX86_64::FinishTransForHWP() 828 { 829 m_2pc_trans_state = Trans_Done; 830 return true; 831 } 832 DNBArchImplX86_64::DBG 833 DNBArchImplX86_64::GetDBGCheckpoint() 834 { 835 return m_2pc_dbg_checkpoint; 836 } 837 838 uint32_t 839 DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task) 840 { 841 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint(addr = 0x%llx, size = %llu, read = %u, write = %u)", (uint64_t)addr, (uint64_t)size, read, write); 842 843 const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints(); 844 845 // Can only watch 1, 2, 4, or 8 bytes. 846 if (!(size == 1 || size == 2 || size == 4 || size == 8)) 847 return INVALID_NUB_HW_INDEX; 848 849 // We must watch for either read or write 850 if (read == false && write == false) 851 return INVALID_NUB_HW_INDEX; 852 853 // Read the debug state 854 kern_return_t kret = GetDBGState(false); 855 856 if (kret == KERN_SUCCESS) 857 { 858 // Check to make sure we have the needed hardware support 859 uint32_t i = 0; 860 861 DBG &debug_state = m_state.context.dbg; 862 for (i = 0; i < num_hw_watchpoints; ++i) 863 { 864 if (IsWatchpointVacant(debug_state, i)) 865 break; 866 } 867 868 // See if we found an available hw breakpoint slot above 869 if (i < num_hw_watchpoints) 870 { 871 StartTransForHWP(); 872 873 // Modify our local copy of the debug state, first. 874 SetWatchpoint(debug_state, i, addr, size, read, write); 875 // Now set the watch point in the inferior. 876 kret = SetDBGState(also_set_on_task); 877 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret); 878 879 if (kret == KERN_SUCCESS) 880 return i; 881 else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. 882 m_state.context.dbg = GetDBGCheckpoint(); 883 } 884 else 885 { 886 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints); 887 } 888 } 889 return INVALID_NUB_HW_INDEX; 890 } 891 892 bool 893 DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task) 894 { 895 kern_return_t kret = GetDBGState(false); 896 897 const uint32_t num_hw_points = NumSupportedHardwareWatchpoints(); 898 if (kret == KERN_SUCCESS) 899 { 900 DBG &debug_state = m_state.context.dbg; 901 if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index)) 902 { 903 StartTransForHWP(); 904 905 // Modify our local copy of the debug state, first. 906 ClearWatchpoint(debug_state, hw_index); 907 // Now disable the watch point in the inferior. 908 kret = SetDBGState(also_set_on_task); 909 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::DisableHardwareWatchpoint( %u )", 910 hw_index); 911 912 if (kret == KERN_SUCCESS) 913 return true; 914 else // Revert to the previous debug state voluntarily. The transaction coordinator knows that we have failed. 915 m_state.context.dbg = GetDBGCheckpoint(); 916 } 917 } 918 return false; 919 } 920 921 // Iterate through the debug status register; return the index of the first hit. 922 uint32_t 923 DNBArchImplX86_64::GetHardwareWatchpointHit(nub_addr_t &addr) 924 { 925 // Read the debug state 926 kern_return_t kret = GetDBGState(true); 927 DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); 928 if (kret == KERN_SUCCESS) 929 { 930 DBG &debug_state = m_state.context.dbg; 931 uint32_t i, num = NumSupportedHardwareWatchpoints(); 932 for (i = 0; i < num; ++i) 933 { 934 if (IsWatchpointHit(debug_state, i)) 935 { 936 addr = GetWatchAddress(debug_state, i); 937 DNBLogThreadedIf(LOG_WATCHPOINTS, 938 "DNBArchImplX86_64::GetHardwareWatchpointHit() found => %u (addr = 0x%llx).", 939 i, 940 (uint64_t)addr); 941 return i; 942 } 943 } 944 } 945 return INVALID_NUB_HW_INDEX; 946 } 947 948 // Set the single step bit in the processor status register. 949 kern_return_t 950 DNBArchImplX86_64::EnableHardwareSingleStep (bool enable) 951 { 952 if (GetGPRState(false) == KERN_SUCCESS) 953 { 954 const uint32_t trace_bit = 0x100u; 955 if (enable) 956 m_state.context.gpr.__rflags |= trace_bit; 957 else 958 m_state.context.gpr.__rflags &= ~trace_bit; 959 return SetGPRState(); 960 } 961 return m_state.GetError(e_regSetGPR, Read); 962 } 963 964 965 //---------------------------------------------------------------------- 966 // Register information definitions 967 //---------------------------------------------------------------------- 968 969 enum 970 { 971 gpr_rax = 0, 972 gpr_rbx, 973 gpr_rcx, 974 gpr_rdx, 975 gpr_rdi, 976 gpr_rsi, 977 gpr_rbp, 978 gpr_rsp, 979 gpr_r8, 980 gpr_r9, 981 gpr_r10, 982 gpr_r11, 983 gpr_r12, 984 gpr_r13, 985 gpr_r14, 986 gpr_r15, 987 gpr_rip, 988 gpr_rflags, 989 gpr_cs, 990 gpr_fs, 991 gpr_gs, 992 gpr_eax, 993 gpr_ebx, 994 gpr_ecx, 995 gpr_edx, 996 gpr_edi, 997 gpr_esi, 998 gpr_ebp, 999 gpr_esp, 1000 gpr_r8d, // Low 32 bits or r8 1001 gpr_r9d, // Low 32 bits or r9 1002 gpr_r10d, // Low 32 bits or r10 1003 gpr_r11d, // Low 32 bits or r11 1004 gpr_r12d, // Low 32 bits or r12 1005 gpr_r13d, // Low 32 bits or r13 1006 gpr_r14d, // Low 32 bits or r14 1007 gpr_r15d, // Low 32 bits or r15 1008 gpr_ax , 1009 gpr_bx , 1010 gpr_cx , 1011 gpr_dx , 1012 gpr_di , 1013 gpr_si , 1014 gpr_bp , 1015 gpr_sp , 1016 gpr_r8w, // Low 16 bits or r8 1017 gpr_r9w, // Low 16 bits or r9 1018 gpr_r10w, // Low 16 bits or r10 1019 gpr_r11w, // Low 16 bits or r11 1020 gpr_r12w, // Low 16 bits or r12 1021 gpr_r13w, // Low 16 bits or r13 1022 gpr_r14w, // Low 16 bits or r14 1023 gpr_r15w, // Low 16 bits or r15 1024 gpr_ah , 1025 gpr_bh , 1026 gpr_ch , 1027 gpr_dh , 1028 gpr_al , 1029 gpr_bl , 1030 gpr_cl , 1031 gpr_dl , 1032 gpr_dil, 1033 gpr_sil, 1034 gpr_bpl, 1035 gpr_spl, 1036 gpr_r8l, // Low 8 bits or r8 1037 gpr_r9l, // Low 8 bits or r9 1038 gpr_r10l, // Low 8 bits or r10 1039 gpr_r11l, // Low 8 bits or r11 1040 gpr_r12l, // Low 8 bits or r12 1041 gpr_r13l, // Low 8 bits or r13 1042 gpr_r14l, // Low 8 bits or r14 1043 gpr_r15l, // Low 8 bits or r15 1044 k_num_gpr_regs 1045 }; 1046 1047 enum { 1048 fpu_fcw, 1049 fpu_fsw, 1050 fpu_ftw, 1051 fpu_fop, 1052 fpu_ip, 1053 fpu_cs, 1054 fpu_dp, 1055 fpu_ds, 1056 fpu_mxcsr, 1057 fpu_mxcsrmask, 1058 fpu_stmm0, 1059 fpu_stmm1, 1060 fpu_stmm2, 1061 fpu_stmm3, 1062 fpu_stmm4, 1063 fpu_stmm5, 1064 fpu_stmm6, 1065 fpu_stmm7, 1066 fpu_xmm0, 1067 fpu_xmm1, 1068 fpu_xmm2, 1069 fpu_xmm3, 1070 fpu_xmm4, 1071 fpu_xmm5, 1072 fpu_xmm6, 1073 fpu_xmm7, 1074 fpu_xmm8, 1075 fpu_xmm9, 1076 fpu_xmm10, 1077 fpu_xmm11, 1078 fpu_xmm12, 1079 fpu_xmm13, 1080 fpu_xmm14, 1081 fpu_xmm15, 1082 fpu_ymm0, 1083 fpu_ymm1, 1084 fpu_ymm2, 1085 fpu_ymm3, 1086 fpu_ymm4, 1087 fpu_ymm5, 1088 fpu_ymm6, 1089 fpu_ymm7, 1090 fpu_ymm8, 1091 fpu_ymm9, 1092 fpu_ymm10, 1093 fpu_ymm11, 1094 fpu_ymm12, 1095 fpu_ymm13, 1096 fpu_ymm14, 1097 fpu_ymm15, 1098 k_num_fpu_regs, 1099 1100 // Aliases 1101 fpu_fctrl = fpu_fcw, 1102 fpu_fstat = fpu_fsw, 1103 fpu_ftag = fpu_ftw, 1104 fpu_fiseg = fpu_cs, 1105 fpu_fioff = fpu_ip, 1106 fpu_foseg = fpu_ds, 1107 fpu_fooff = fpu_dp 1108 }; 1109 1110 enum { 1111 exc_trapno, 1112 exc_err, 1113 exc_faultvaddr, 1114 k_num_exc_regs, 1115 }; 1116 1117 1118 enum gcc_dwarf_regnums 1119 { 1120 gcc_dwarf_rax = 0, 1121 gcc_dwarf_rdx = 1, 1122 gcc_dwarf_rcx = 2, 1123 gcc_dwarf_rbx = 3, 1124 gcc_dwarf_rsi = 4, 1125 gcc_dwarf_rdi = 5, 1126 gcc_dwarf_rbp = 6, 1127 gcc_dwarf_rsp = 7, 1128 gcc_dwarf_r8, 1129 gcc_dwarf_r9, 1130 gcc_dwarf_r10, 1131 gcc_dwarf_r11, 1132 gcc_dwarf_r12, 1133 gcc_dwarf_r13, 1134 gcc_dwarf_r14, 1135 gcc_dwarf_r15, 1136 gcc_dwarf_rip, 1137 gcc_dwarf_xmm0, 1138 gcc_dwarf_xmm1, 1139 gcc_dwarf_xmm2, 1140 gcc_dwarf_xmm3, 1141 gcc_dwarf_xmm4, 1142 gcc_dwarf_xmm5, 1143 gcc_dwarf_xmm6, 1144 gcc_dwarf_xmm7, 1145 gcc_dwarf_xmm8, 1146 gcc_dwarf_xmm9, 1147 gcc_dwarf_xmm10, 1148 gcc_dwarf_xmm11, 1149 gcc_dwarf_xmm12, 1150 gcc_dwarf_xmm13, 1151 gcc_dwarf_xmm14, 1152 gcc_dwarf_xmm15, 1153 gcc_dwarf_stmm0, 1154 gcc_dwarf_stmm1, 1155 gcc_dwarf_stmm2, 1156 gcc_dwarf_stmm3, 1157 gcc_dwarf_stmm4, 1158 gcc_dwarf_stmm5, 1159 gcc_dwarf_stmm6, 1160 gcc_dwarf_stmm7, 1161 gcc_dwarf_ymm0 = gcc_dwarf_xmm0, 1162 gcc_dwarf_ymm1 = gcc_dwarf_xmm1, 1163 gcc_dwarf_ymm2 = gcc_dwarf_xmm2, 1164 gcc_dwarf_ymm3 = gcc_dwarf_xmm3, 1165 gcc_dwarf_ymm4 = gcc_dwarf_xmm4, 1166 gcc_dwarf_ymm5 = gcc_dwarf_xmm5, 1167 gcc_dwarf_ymm6 = gcc_dwarf_xmm6, 1168 gcc_dwarf_ymm7 = gcc_dwarf_xmm7, 1169 gcc_dwarf_ymm8 = gcc_dwarf_xmm8, 1170 gcc_dwarf_ymm9 = gcc_dwarf_xmm9, 1171 gcc_dwarf_ymm10 = gcc_dwarf_xmm10, 1172 gcc_dwarf_ymm11 = gcc_dwarf_xmm11, 1173 gcc_dwarf_ymm12 = gcc_dwarf_xmm12, 1174 gcc_dwarf_ymm13 = gcc_dwarf_xmm13, 1175 gcc_dwarf_ymm14 = gcc_dwarf_xmm14, 1176 gcc_dwarf_ymm15 = gcc_dwarf_xmm15 1177 }; 1178 1179 enum gdb_regnums 1180 { 1181 gdb_rax = 0, 1182 gdb_rbx = 1, 1183 gdb_rcx = 2, 1184 gdb_rdx = 3, 1185 gdb_rsi = 4, 1186 gdb_rdi = 5, 1187 gdb_rbp = 6, 1188 gdb_rsp = 7, 1189 gdb_r8 = 8, 1190 gdb_r9 = 9, 1191 gdb_r10 = 10, 1192 gdb_r11 = 11, 1193 gdb_r12 = 12, 1194 gdb_r13 = 13, 1195 gdb_r14 = 14, 1196 gdb_r15 = 15, 1197 gdb_rip = 16, 1198 gdb_rflags = 17, 1199 gdb_cs = 18, 1200 gdb_ss = 19, 1201 gdb_ds = 20, 1202 gdb_es = 21, 1203 gdb_fs = 22, 1204 gdb_gs = 23, 1205 gdb_stmm0 = 24, 1206 gdb_stmm1 = 25, 1207 gdb_stmm2 = 26, 1208 gdb_stmm3 = 27, 1209 gdb_stmm4 = 28, 1210 gdb_stmm5 = 29, 1211 gdb_stmm6 = 30, 1212 gdb_stmm7 = 31, 1213 gdb_fctrl = 32, gdb_fcw = gdb_fctrl, 1214 gdb_fstat = 33, gdb_fsw = gdb_fstat, 1215 gdb_ftag = 34, gdb_ftw = gdb_ftag, 1216 gdb_fiseg = 35, gdb_fpu_cs = gdb_fiseg, 1217 gdb_fioff = 36, gdb_ip = gdb_fioff, 1218 gdb_foseg = 37, gdb_fpu_ds = gdb_foseg, 1219 gdb_fooff = 38, gdb_dp = gdb_fooff, 1220 gdb_fop = 39, 1221 gdb_xmm0 = 40, 1222 gdb_xmm1 = 41, 1223 gdb_xmm2 = 42, 1224 gdb_xmm3 = 43, 1225 gdb_xmm4 = 44, 1226 gdb_xmm5 = 45, 1227 gdb_xmm6 = 46, 1228 gdb_xmm7 = 47, 1229 gdb_xmm8 = 48, 1230 gdb_xmm9 = 49, 1231 gdb_xmm10 = 50, 1232 gdb_xmm11 = 51, 1233 gdb_xmm12 = 52, 1234 gdb_xmm13 = 53, 1235 gdb_xmm14 = 54, 1236 gdb_xmm15 = 55, 1237 gdb_mxcsr = 56, 1238 gdb_ymm0 = gdb_xmm0, 1239 gdb_ymm1 = gdb_xmm1, 1240 gdb_ymm2 = gdb_xmm2, 1241 gdb_ymm3 = gdb_xmm3, 1242 gdb_ymm4 = gdb_xmm4, 1243 gdb_ymm5 = gdb_xmm5, 1244 gdb_ymm6 = gdb_xmm6, 1245 gdb_ymm7 = gdb_xmm7, 1246 gdb_ymm8 = gdb_xmm8, 1247 gdb_ymm9 = gdb_xmm9, 1248 gdb_ymm10 = gdb_xmm10, 1249 gdb_ymm11 = gdb_xmm11, 1250 gdb_ymm12 = gdb_xmm12, 1251 gdb_ymm13 = gdb_xmm13, 1252 gdb_ymm14 = gdb_xmm14, 1253 gdb_ymm15 = gdb_xmm15 1254 }; 1255 1256 #define GPR_OFFSET(reg) (offsetof (DNBArchImplX86_64::GPR, __##reg)) 1257 #define FPU_OFFSET(reg) (offsetof (DNBArchImplX86_64::FPU, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu.no_avx)) 1258 #define AVX_OFFSET(reg) (offsetof (DNBArchImplX86_64::AVX, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu.avx)) 1259 #define EXC_OFFSET(reg) (offsetof (DNBArchImplX86_64::EXC, __##reg) + offsetof (DNBArchImplX86_64::Context, exc)) 1260 #define AVX_OFFSET_YMM(n) (AVX_OFFSET(ymmh0) + (32 * n)) 1261 1262 #define GPR_SIZE(reg) (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg)) 1263 #define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg)) 1264 #define FPU_SIZE_MMST(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg)) 1265 #define FPU_SIZE_XMM(reg) (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg)) 1266 #define FPU_SIZE_YMM(reg) (32) 1267 #define EXC_SIZE(reg) (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg)) 1268 1269 // These macros will auto define the register name, alt name, register size, 1270 // register offset, encoding, format and native register. This ensures that 1271 // the register state structures are defined correctly and have the correct 1272 // sizes and offsets. 1273 #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, NULL, g_invalidate_##reg } 1274 #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, NULL, g_invalidate_##reg } 1275 #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, NULL, NULL } 1276 #define DEFINE_GPR_ALT3(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gen, gdb_##reg, NULL, NULL } 1277 #define DEFINE_GPR_ALT4(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, NULL, NULL } 1278 1279 #define DEFINE_GPR_PSEUDO_32(reg32,reg64) { e_regSetGPR, gpr_##reg32, #reg32, NULL, Uint, Hex, 4, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 } 1280 #define DEFINE_GPR_PSEUDO_16(reg16,reg64) { e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 } 1281 #define DEFINE_GPR_PSEUDO_8H(reg8,reg64) { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 1,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 } 1282 #define DEFINE_GPR_PSEUDO_8L(reg8,reg64) { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg64, g_invalidate_##reg64 } 1283 1284 // General purpose registers for 64 bit 1285 1286 const char *g_contained_rax[] = { "rax", NULL }; 1287 const char *g_contained_rbx[] = { "rbx", NULL }; 1288 const char *g_contained_rcx[] = { "rcx", NULL }; 1289 const char *g_contained_rdx[] = { "rdx", NULL }; 1290 const char *g_contained_rdi[] = { "rdi", NULL }; 1291 const char *g_contained_rsi[] = { "rsi", NULL }; 1292 const char *g_contained_rbp[] = { "rbp", NULL }; 1293 const char *g_contained_rsp[] = { "rsp", NULL }; 1294 const char *g_contained_r8[] = { "r8", NULL }; 1295 const char *g_contained_r9[] = { "r9", NULL }; 1296 const char *g_contained_r10[] = { "r10", NULL }; 1297 const char *g_contained_r11[] = { "r11", NULL }; 1298 const char *g_contained_r12[] = { "r12", NULL }; 1299 const char *g_contained_r13[] = { "r13", NULL }; 1300 const char *g_contained_r14[] = { "r14", NULL }; 1301 const char *g_contained_r15[] = { "r15", NULL }; 1302 1303 const char *g_invalidate_rax[] = { "rax", "eax", "ax", "ah", "al", NULL }; 1304 const char *g_invalidate_rbx[] = { "rbx", "ebx", "bx", "bh", "bl", NULL }; 1305 const char *g_invalidate_rcx[] = { "rcx", "ecx", "cx", "ch", "cl", NULL }; 1306 const char *g_invalidate_rdx[] = { "rdx", "edx", "dx", "dh", "dl", NULL }; 1307 const char *g_invalidate_rdi[] = { "rdi", "edi", "di", "dil", NULL }; 1308 const char *g_invalidate_rsi[] = { "rsi", "esi", "si", "sil", NULL }; 1309 const char *g_invalidate_rbp[] = { "rbp", "ebp", "bp", "bpl", NULL }; 1310 const char *g_invalidate_rsp[] = { "rsp", "esp", "sp", "spl", NULL }; 1311 const char *g_invalidate_r8 [] = { "r8", "r8d", "r8w", "r8l", NULL }; 1312 const char *g_invalidate_r9 [] = { "r9", "r9d", "r9w", "r9l", NULL }; 1313 const char *g_invalidate_r10[] = { "r10", "r10d", "r10w", "r10l", NULL }; 1314 const char *g_invalidate_r11[] = { "r11", "r11d", "r11w", "r11l", NULL }; 1315 const char *g_invalidate_r12[] = { "r12", "r12d", "r12w", "r12l", NULL }; 1316 const char *g_invalidate_r13[] = { "r13", "r13d", "r13w", "r13l", NULL }; 1317 const char *g_invalidate_r14[] = { "r14", "r14d", "r14w", "r14l", NULL }; 1318 const char *g_invalidate_r15[] = { "r15", "r15d", "r15w", "r15l", NULL }; 1319 1320 const DNBRegisterInfo 1321 DNBArchImplX86_64::g_gpr_registers[] = 1322 { 1323 DEFINE_GPR (rax), 1324 DEFINE_GPR (rbx), 1325 DEFINE_GPR_ALT (rcx , "arg4", GENERIC_REGNUM_ARG4), 1326 DEFINE_GPR_ALT (rdx , "arg3", GENERIC_REGNUM_ARG3), 1327 DEFINE_GPR_ALT (rdi , "arg1", GENERIC_REGNUM_ARG1), 1328 DEFINE_GPR_ALT (rsi , "arg2", GENERIC_REGNUM_ARG2), 1329 DEFINE_GPR_ALT (rbp , "fp" , GENERIC_REGNUM_FP), 1330 DEFINE_GPR_ALT (rsp , "sp" , GENERIC_REGNUM_SP), 1331 DEFINE_GPR_ALT (r8 , "arg5", GENERIC_REGNUM_ARG5), 1332 DEFINE_GPR_ALT (r9 , "arg6", GENERIC_REGNUM_ARG6), 1333 DEFINE_GPR (r10), 1334 DEFINE_GPR (r11), 1335 DEFINE_GPR (r12), 1336 DEFINE_GPR (r13), 1337 DEFINE_GPR (r14), 1338 DEFINE_GPR (r15), 1339 DEFINE_GPR_ALT4 (rip , "pc", GENERIC_REGNUM_PC), 1340 DEFINE_GPR_ALT3 (rflags, "flags", GENERIC_REGNUM_FLAGS), 1341 DEFINE_GPR_ALT2 (cs, NULL), 1342 DEFINE_GPR_ALT2 (fs, NULL), 1343 DEFINE_GPR_ALT2 (gs, NULL), 1344 DEFINE_GPR_PSEUDO_32 (eax, rax), 1345 DEFINE_GPR_PSEUDO_32 (ebx, rbx), 1346 DEFINE_GPR_PSEUDO_32 (ecx, rcx), 1347 DEFINE_GPR_PSEUDO_32 (edx, rdx), 1348 DEFINE_GPR_PSEUDO_32 (edi, rdi), 1349 DEFINE_GPR_PSEUDO_32 (esi, rsi), 1350 DEFINE_GPR_PSEUDO_32 (ebp, rbp), 1351 DEFINE_GPR_PSEUDO_32 (esp, rsp), 1352 DEFINE_GPR_PSEUDO_32 (r8d, r8), 1353 DEFINE_GPR_PSEUDO_32 (r9d, r9), 1354 DEFINE_GPR_PSEUDO_32 (r10d, r10), 1355 DEFINE_GPR_PSEUDO_32 (r11d, r11), 1356 DEFINE_GPR_PSEUDO_32 (r12d, r12), 1357 DEFINE_GPR_PSEUDO_32 (r13d, r13), 1358 DEFINE_GPR_PSEUDO_32 (r14d, r14), 1359 DEFINE_GPR_PSEUDO_32 (r15d, r15), 1360 DEFINE_GPR_PSEUDO_16 (ax , rax), 1361 DEFINE_GPR_PSEUDO_16 (bx , rbx), 1362 DEFINE_GPR_PSEUDO_16 (cx , rcx), 1363 DEFINE_GPR_PSEUDO_16 (dx , rdx), 1364 DEFINE_GPR_PSEUDO_16 (di , rdi), 1365 DEFINE_GPR_PSEUDO_16 (si , rsi), 1366 DEFINE_GPR_PSEUDO_16 (bp , rbp), 1367 DEFINE_GPR_PSEUDO_16 (sp , rsp), 1368 DEFINE_GPR_PSEUDO_16 (r8w, r8), 1369 DEFINE_GPR_PSEUDO_16 (r9w, r9), 1370 DEFINE_GPR_PSEUDO_16 (r10w, r10), 1371 DEFINE_GPR_PSEUDO_16 (r11w, r11), 1372 DEFINE_GPR_PSEUDO_16 (r12w, r12), 1373 DEFINE_GPR_PSEUDO_16 (r13w, r13), 1374 DEFINE_GPR_PSEUDO_16 (r14w, r14), 1375 DEFINE_GPR_PSEUDO_16 (r15w, r15), 1376 DEFINE_GPR_PSEUDO_8H (ah , rax), 1377 DEFINE_GPR_PSEUDO_8H (bh , rbx), 1378 DEFINE_GPR_PSEUDO_8H (ch , rcx), 1379 DEFINE_GPR_PSEUDO_8H (dh , rdx), 1380 DEFINE_GPR_PSEUDO_8L (al , rax), 1381 DEFINE_GPR_PSEUDO_8L (bl , rbx), 1382 DEFINE_GPR_PSEUDO_8L (cl , rcx), 1383 DEFINE_GPR_PSEUDO_8L (dl , rdx), 1384 DEFINE_GPR_PSEUDO_8L (dil, rdi), 1385 DEFINE_GPR_PSEUDO_8L (sil, rsi), 1386 DEFINE_GPR_PSEUDO_8L (bpl, rbp), 1387 DEFINE_GPR_PSEUDO_8L (spl, rsp), 1388 DEFINE_GPR_PSEUDO_8L (r8l, r8), 1389 DEFINE_GPR_PSEUDO_8L (r9l, r9), 1390 DEFINE_GPR_PSEUDO_8L (r10l, r10), 1391 DEFINE_GPR_PSEUDO_8L (r11l, r11), 1392 DEFINE_GPR_PSEUDO_8L (r12l, r12), 1393 DEFINE_GPR_PSEUDO_8L (r13l, r13), 1394 DEFINE_GPR_PSEUDO_8L (r14l, r14), 1395 DEFINE_GPR_PSEUDO_8L (r15l, r15) 1396 }; 1397 1398 // Floating point registers 64 bit 1399 const DNBRegisterInfo 1400 DNBArchImplX86_64::g_fpu_registers_no_avx[] = 1401 { 1402 { e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , FPU_OFFSET(fcw) , -1U, -1U, -1U, -1U, NULL, NULL }, 1403 { e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , FPU_OFFSET(fsw) , -1U, -1U, -1U, -1U, NULL, NULL }, 1404 { e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , FPU_OFFSET(ftw) , -1U, -1U, -1U, -1U, NULL, NULL }, 1405 { e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , FPU_OFFSET(fop) , -1U, -1U, -1U, -1U, NULL, NULL }, 1406 { e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , FPU_OFFSET(ip) , -1U, -1U, -1U, -1U, NULL, NULL }, 1407 { e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , FPU_OFFSET(cs) , -1U, -1U, -1U, -1U, NULL, NULL }, 1408 { e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , FPU_OFFSET(dp) , -1U, -1U, -1U, -1U, NULL, NULL }, 1409 { e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , FPU_OFFSET(ds) , -1U, -1U, -1U, -1U, NULL, NULL }, 1410 { e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , FPU_OFFSET(mxcsr) , -1U, -1U, -1U, -1U, NULL, NULL }, 1411 { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , -1U, -1U, -1U, -1U, NULL, NULL }, 1412 1413 { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), gcc_dwarf_stmm0, gcc_dwarf_stmm0, -1U, gdb_stmm0, NULL, NULL }, 1414 { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), gcc_dwarf_stmm1, gcc_dwarf_stmm1, -1U, gdb_stmm1, NULL, NULL }, 1415 { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), gcc_dwarf_stmm2, gcc_dwarf_stmm2, -1U, gdb_stmm2, NULL, NULL }, 1416 { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), gcc_dwarf_stmm3, gcc_dwarf_stmm3, -1U, gdb_stmm3, NULL, NULL }, 1417 { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), gcc_dwarf_stmm4, gcc_dwarf_stmm4, -1U, gdb_stmm4, NULL, NULL }, 1418 { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), gcc_dwarf_stmm5, gcc_dwarf_stmm5, -1U, gdb_stmm5, NULL, NULL }, 1419 { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), gcc_dwarf_stmm6, gcc_dwarf_stmm6, -1U, gdb_stmm6, NULL, NULL }, 1420 { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), gcc_dwarf_stmm7, gcc_dwarf_stmm7, -1U, gdb_stmm7, NULL, NULL }, 1421 1422 { e_regSetFPU, fpu_xmm0 , "xmm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0) , FPU_OFFSET(xmm0) , gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , -1U, gdb_xmm0 , NULL, NULL }, 1423 { e_regSetFPU, fpu_xmm1 , "xmm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1) , FPU_OFFSET(xmm1) , gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , -1U, gdb_xmm1 , NULL, NULL }, 1424 { e_regSetFPU, fpu_xmm2 , "xmm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2) , FPU_OFFSET(xmm2) , gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , -1U, gdb_xmm2 , NULL, NULL }, 1425 { e_regSetFPU, fpu_xmm3 , "xmm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3) , FPU_OFFSET(xmm3) , gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , -1U, gdb_xmm3 , NULL, NULL }, 1426 { e_regSetFPU, fpu_xmm4 , "xmm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4) , FPU_OFFSET(xmm4) , gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , -1U, gdb_xmm4 , NULL, NULL }, 1427 { e_regSetFPU, fpu_xmm5 , "xmm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5) , FPU_OFFSET(xmm5) , gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , -1U, gdb_xmm5 , NULL, NULL }, 1428 { e_regSetFPU, fpu_xmm6 , "xmm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6) , FPU_OFFSET(xmm6) , gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , -1U, gdb_xmm6 , NULL, NULL }, 1429 { e_regSetFPU, fpu_xmm7 , "xmm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7) , FPU_OFFSET(xmm7) , gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , -1U, gdb_xmm7 , NULL, NULL }, 1430 { e_regSetFPU, fpu_xmm8 , "xmm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8) , FPU_OFFSET(xmm8) , gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , -1U, gdb_xmm8 , NULL, NULL }, 1431 { e_regSetFPU, fpu_xmm9 , "xmm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9) , FPU_OFFSET(xmm9) , gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , -1U, gdb_xmm9 , NULL, NULL }, 1432 { e_regSetFPU, fpu_xmm10, "xmm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10) , FPU_OFFSET(xmm10), gcc_dwarf_xmm10, gcc_dwarf_xmm10, -1U, gdb_xmm10, NULL, NULL }, 1433 { e_regSetFPU, fpu_xmm11, "xmm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11) , FPU_OFFSET(xmm11), gcc_dwarf_xmm11, gcc_dwarf_xmm11, -1U, gdb_xmm11, NULL, NULL }, 1434 { e_regSetFPU, fpu_xmm12, "xmm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12) , FPU_OFFSET(xmm12), gcc_dwarf_xmm12, gcc_dwarf_xmm12, -1U, gdb_xmm12, NULL, NULL }, 1435 { e_regSetFPU, fpu_xmm13, "xmm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13) , FPU_OFFSET(xmm13), gcc_dwarf_xmm13, gcc_dwarf_xmm13, -1U, gdb_xmm13, NULL, NULL }, 1436 { e_regSetFPU, fpu_xmm14, "xmm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14) , FPU_OFFSET(xmm14), gcc_dwarf_xmm14, gcc_dwarf_xmm14, -1U, gdb_xmm14, NULL, NULL }, 1437 { e_regSetFPU, fpu_xmm15, "xmm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15) , FPU_OFFSET(xmm15), gcc_dwarf_xmm15, gcc_dwarf_xmm15, -1U, gdb_xmm15, NULL, NULL }, 1438 }; 1439 1440 static const char *g_contained_ymm0 [] = { "ymm0", NULL }; 1441 static const char *g_contained_ymm1 [] = { "ymm1", NULL }; 1442 static const char *g_contained_ymm2 [] = { "ymm2", NULL }; 1443 static const char *g_contained_ymm3 [] = { "ymm3", NULL }; 1444 static const char *g_contained_ymm4 [] = { "ymm4", NULL }; 1445 static const char *g_contained_ymm5 [] = { "ymm5", NULL }; 1446 static const char *g_contained_ymm6 [] = { "ymm6", NULL }; 1447 static const char *g_contained_ymm7 [] = { "ymm7", NULL }; 1448 static const char *g_contained_ymm8 [] = { "ymm8", NULL }; 1449 static const char *g_contained_ymm9 [] = { "ymm9", NULL }; 1450 static const char *g_contained_ymm10[] = { "ymm10", NULL }; 1451 static const char *g_contained_ymm11[] = { "ymm11", NULL }; 1452 static const char *g_contained_ymm12[] = { "ymm12", NULL }; 1453 static const char *g_contained_ymm13[] = { "ymm13", NULL }; 1454 static const char *g_contained_ymm14[] = { "ymm14", NULL }; 1455 static const char *g_contained_ymm15[] = { "ymm15", NULL }; 1456 1457 const DNBRegisterInfo 1458 DNBArchImplX86_64::g_fpu_registers_avx[] = 1459 { 1460 { e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , AVX_OFFSET(fcw) , -1U, -1U, -1U, -1U, NULL, NULL }, 1461 { e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , AVX_OFFSET(fsw) , -1U, -1U, -1U, -1U, NULL, NULL }, 1462 { e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , AVX_OFFSET(ftw) , -1U, -1U, -1U, -1U, NULL, NULL }, 1463 { e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , AVX_OFFSET(fop) , -1U, -1U, -1U, -1U, NULL, NULL }, 1464 { e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , AVX_OFFSET(ip) , -1U, -1U, -1U, -1U, NULL, NULL }, 1465 { e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , AVX_OFFSET(cs) , -1U, -1U, -1U, -1U, NULL, NULL }, 1466 { e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , AVX_OFFSET(dp) , -1U, -1U, -1U, -1U, NULL, NULL }, 1467 { e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , AVX_OFFSET(ds) , -1U, -1U, -1U, -1U, NULL, NULL }, 1468 { e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , AVX_OFFSET(mxcsr) , -1U, -1U, -1U, -1U, NULL, NULL }, 1469 { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , AVX_OFFSET(mxcsrmask) , -1U, -1U, -1U, -1U, NULL, NULL }, 1470 1471 { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), gcc_dwarf_stmm0, gcc_dwarf_stmm0, -1U, gdb_stmm0, NULL, NULL }, 1472 { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), gcc_dwarf_stmm1, gcc_dwarf_stmm1, -1U, gdb_stmm1, NULL, NULL }, 1473 { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), gcc_dwarf_stmm2, gcc_dwarf_stmm2, -1U, gdb_stmm2, NULL, NULL }, 1474 { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), gcc_dwarf_stmm3, gcc_dwarf_stmm3, -1U, gdb_stmm3, NULL, NULL }, 1475 { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), gcc_dwarf_stmm4, gcc_dwarf_stmm4, -1U, gdb_stmm4, NULL, NULL }, 1476 { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), gcc_dwarf_stmm5, gcc_dwarf_stmm5, -1U, gdb_stmm5, NULL, NULL }, 1477 { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), gcc_dwarf_stmm6, gcc_dwarf_stmm6, -1U, gdb_stmm6, NULL, NULL }, 1478 { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), gcc_dwarf_stmm7, gcc_dwarf_stmm7, -1U, gdb_stmm7, NULL, NULL }, 1479 1480 { e_regSetFPU, fpu_ymm0 , "ymm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm0) , AVX_OFFSET_YMM(0) , gcc_dwarf_ymm0 , gcc_dwarf_ymm0 , -1U, gdb_ymm0, NULL, NULL }, 1481 { e_regSetFPU, fpu_ymm1 , "ymm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm1) , AVX_OFFSET_YMM(1) , gcc_dwarf_ymm1 , gcc_dwarf_ymm1 , -1U, gdb_ymm1, NULL, NULL }, 1482 { e_regSetFPU, fpu_ymm2 , "ymm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm2) , AVX_OFFSET_YMM(2) , gcc_dwarf_ymm2 , gcc_dwarf_ymm2 , -1U, gdb_ymm2, NULL, NULL }, 1483 { e_regSetFPU, fpu_ymm3 , "ymm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm3) , AVX_OFFSET_YMM(3) , gcc_dwarf_ymm3 , gcc_dwarf_ymm3 , -1U, gdb_ymm3, NULL, NULL }, 1484 { e_regSetFPU, fpu_ymm4 , "ymm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm4) , AVX_OFFSET_YMM(4) , gcc_dwarf_ymm4 , gcc_dwarf_ymm4 , -1U, gdb_ymm4, NULL, NULL }, 1485 { e_regSetFPU, fpu_ymm5 , "ymm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm5) , AVX_OFFSET_YMM(5) , gcc_dwarf_ymm5 , gcc_dwarf_ymm5 , -1U, gdb_ymm5, NULL, NULL }, 1486 { e_regSetFPU, fpu_ymm6 , "ymm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm6) , AVX_OFFSET_YMM(6) , gcc_dwarf_ymm6 , gcc_dwarf_ymm6 , -1U, gdb_ymm6, NULL, NULL }, 1487 { e_regSetFPU, fpu_ymm7 , "ymm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm7) , AVX_OFFSET_YMM(7) , gcc_dwarf_ymm7 , gcc_dwarf_ymm7 , -1U, gdb_ymm7, NULL, NULL }, 1488 { e_regSetFPU, fpu_ymm8 , "ymm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm8) , AVX_OFFSET_YMM(8) , gcc_dwarf_ymm8 , gcc_dwarf_ymm8 , -1U, gdb_ymm8 , NULL, NULL }, 1489 { e_regSetFPU, fpu_ymm9 , "ymm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm9) , AVX_OFFSET_YMM(9) , gcc_dwarf_ymm9 , gcc_dwarf_ymm9 , -1U, gdb_ymm9 , NULL, NULL }, 1490 { e_regSetFPU, fpu_ymm10, "ymm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm10) , AVX_OFFSET_YMM(10), gcc_dwarf_ymm10, gcc_dwarf_ymm10, -1U, gdb_ymm10, NULL, NULL }, 1491 { e_regSetFPU, fpu_ymm11, "ymm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm11) , AVX_OFFSET_YMM(11), gcc_dwarf_ymm11, gcc_dwarf_ymm11, -1U, gdb_ymm11, NULL, NULL }, 1492 { e_regSetFPU, fpu_ymm12, "ymm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm12) , AVX_OFFSET_YMM(12), gcc_dwarf_ymm12, gcc_dwarf_ymm12, -1U, gdb_ymm12, NULL, NULL }, 1493 { e_regSetFPU, fpu_ymm13, "ymm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm13) , AVX_OFFSET_YMM(13), gcc_dwarf_ymm13, gcc_dwarf_ymm13, -1U, gdb_ymm13, NULL, NULL }, 1494 { e_regSetFPU, fpu_ymm14, "ymm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm14) , AVX_OFFSET_YMM(14), gcc_dwarf_ymm14, gcc_dwarf_ymm14, -1U, gdb_ymm14, NULL, NULL }, 1495 { e_regSetFPU, fpu_ymm15, "ymm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm15) , AVX_OFFSET_YMM(15), gcc_dwarf_ymm15, gcc_dwarf_ymm15, -1U, gdb_ymm15, NULL, NULL }, 1496 1497 { e_regSetFPU, fpu_xmm0 , "xmm0" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0) , 0, gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , -1U, gdb_xmm0 , g_contained_ymm0 , NULL }, 1498 { e_regSetFPU, fpu_xmm1 , "xmm1" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1) , 0, gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , -1U, gdb_xmm1 , g_contained_ymm1 , NULL }, 1499 { e_regSetFPU, fpu_xmm2 , "xmm2" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2) , 0, gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , -1U, gdb_xmm2 , g_contained_ymm2 , NULL }, 1500 { e_regSetFPU, fpu_xmm3 , "xmm3" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3) , 0, gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , -1U, gdb_xmm3 , g_contained_ymm3 , NULL }, 1501 { e_regSetFPU, fpu_xmm4 , "xmm4" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4) , 0, gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , -1U, gdb_xmm4 , g_contained_ymm4 , NULL }, 1502 { e_regSetFPU, fpu_xmm5 , "xmm5" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5) , 0, gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , -1U, gdb_xmm5 , g_contained_ymm5 , NULL }, 1503 { e_regSetFPU, fpu_xmm6 , "xmm6" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6) , 0, gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , -1U, gdb_xmm6 , g_contained_ymm6 , NULL }, 1504 { e_regSetFPU, fpu_xmm7 , "xmm7" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7) , 0, gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , -1U, gdb_xmm7 , g_contained_ymm7 , NULL }, 1505 { e_regSetFPU, fpu_xmm8 , "xmm8" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8) , 0, gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , -1U, gdb_xmm8 , g_contained_ymm8 , NULL }, 1506 { e_regSetFPU, fpu_xmm9 , "xmm9" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9) , 0, gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , -1U, gdb_xmm9 , g_contained_ymm9 , NULL }, 1507 { e_regSetFPU, fpu_xmm10, "xmm10" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10) , 0, gcc_dwarf_xmm10, gcc_dwarf_xmm10, -1U, gdb_xmm10, g_contained_ymm10, NULL }, 1508 { e_regSetFPU, fpu_xmm11, "xmm11" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11) , 0, gcc_dwarf_xmm11, gcc_dwarf_xmm11, -1U, gdb_xmm11, g_contained_ymm11, NULL }, 1509 { e_regSetFPU, fpu_xmm12, "xmm12" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12) , 0, gcc_dwarf_xmm12, gcc_dwarf_xmm12, -1U, gdb_xmm12, g_contained_ymm12, NULL }, 1510 { e_regSetFPU, fpu_xmm13, "xmm13" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13) , 0, gcc_dwarf_xmm13, gcc_dwarf_xmm13, -1U, gdb_xmm13, g_contained_ymm13, NULL }, 1511 { e_regSetFPU, fpu_xmm14, "xmm14" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14) , 0, gcc_dwarf_xmm14, gcc_dwarf_xmm14, -1U, gdb_xmm14, g_contained_ymm14, NULL }, 1512 { e_regSetFPU, fpu_xmm15, "xmm15" , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15) , 0, gcc_dwarf_xmm15, gcc_dwarf_xmm15, -1U, gdb_xmm15, g_contained_ymm15, NULL } 1513 1514 1515 }; 1516 1517 // Exception registers 1518 1519 const DNBRegisterInfo 1520 DNBArchImplX86_64::g_exc_registers[] = 1521 { 1522 { e_regSetEXC, exc_trapno, "trapno" , NULL, Uint, Hex, EXC_SIZE (trapno) , EXC_OFFSET (trapno) , -1U, -1U, -1U, -1U, NULL, NULL }, 1523 { e_regSetEXC, exc_err, "err" , NULL, Uint, Hex, EXC_SIZE (err) , EXC_OFFSET (err) , -1U, -1U, -1U, -1U, NULL, NULL }, 1524 { e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr) , -1U, -1U, -1U, -1U, NULL, NULL } 1525 }; 1526 1527 // Number of registers in each register set 1528 const size_t DNBArchImplX86_64::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); 1529 const size_t DNBArchImplX86_64::k_num_fpu_registers_no_avx = sizeof(g_fpu_registers_no_avx)/sizeof(DNBRegisterInfo); 1530 const size_t DNBArchImplX86_64::k_num_fpu_registers_avx = sizeof(g_fpu_registers_avx)/sizeof(DNBRegisterInfo); 1531 const size_t DNBArchImplX86_64::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); 1532 const size_t DNBArchImplX86_64::k_num_all_registers_no_avx = k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers; 1533 const size_t DNBArchImplX86_64::k_num_all_registers_avx = k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers; 1534 1535 //---------------------------------------------------------------------- 1536 // Register set definitions. The first definitions at register set index 1537 // of zero is for all registers, followed by other registers sets. The 1538 // register information for the all register set need not be filled in. 1539 //---------------------------------------------------------------------- 1540 const DNBRegisterSetInfo 1541 DNBArchImplX86_64::g_reg_sets_no_avx[] = 1542 { 1543 { "x86_64 Registers", NULL, k_num_all_registers_no_avx }, 1544 { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, 1545 { "Floating Point Registers", g_fpu_registers_no_avx, k_num_fpu_registers_no_avx }, 1546 { "Exception State Registers", g_exc_registers, k_num_exc_registers } 1547 }; 1548 1549 const DNBRegisterSetInfo 1550 DNBArchImplX86_64::g_reg_sets_avx[] = 1551 { 1552 { "x86_64 Registers", NULL, k_num_all_registers_avx }, 1553 { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, 1554 { "Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx }, 1555 { "Exception State Registers", g_exc_registers, k_num_exc_registers } 1556 }; 1557 1558 // Total number of register sets for this architecture 1559 const size_t DNBArchImplX86_64::k_num_register_sets = sizeof(g_reg_sets_avx)/sizeof(DNBRegisterSetInfo); 1560 1561 1562 DNBArchProtocol * 1563 DNBArchImplX86_64::Create (MachThread *thread) 1564 { 1565 DNBArchImplX86_64 *obj = new DNBArchImplX86_64 (thread); 1566 return obj; 1567 } 1568 1569 const uint8_t * const 1570 DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size) 1571 { 1572 static const uint8_t g_breakpoint_opcode[] = { 0xCC }; 1573 if (byte_size == 1) 1574 return g_breakpoint_opcode; 1575 return NULL; 1576 } 1577 1578 const DNBRegisterSetInfo * 1579 DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets) 1580 { 1581 *num_reg_sets = k_num_register_sets; 1582 1583 if (CPUHasAVX() || FORCE_AVX_REGS) 1584 return g_reg_sets_avx; 1585 else 1586 return g_reg_sets_no_avx; 1587 } 1588 1589 void 1590 DNBArchImplX86_64::Initialize() 1591 { 1592 DNBArchPluginInfo arch_plugin_info = 1593 { 1594 CPU_TYPE_X86_64, 1595 DNBArchImplX86_64::Create, 1596 DNBArchImplX86_64::GetRegisterSetInfo, 1597 DNBArchImplX86_64::SoftwareBreakpointOpcode 1598 }; 1599 1600 // Register this arch plug-in with the main protocol class 1601 DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); 1602 } 1603 1604 bool 1605 DNBArchImplX86_64::GetRegisterValue(int set, int reg, DNBRegisterValue *value) 1606 { 1607 if (set == REGISTER_SET_GENERIC) 1608 { 1609 switch (reg) 1610 { 1611 case GENERIC_REGNUM_PC: // Program Counter 1612 set = e_regSetGPR; 1613 reg = gpr_rip; 1614 break; 1615 1616 case GENERIC_REGNUM_SP: // Stack Pointer 1617 set = e_regSetGPR; 1618 reg = gpr_rsp; 1619 break; 1620 1621 case GENERIC_REGNUM_FP: // Frame Pointer 1622 set = e_regSetGPR; 1623 reg = gpr_rbp; 1624 break; 1625 1626 case GENERIC_REGNUM_FLAGS: // Processor flags register 1627 set = e_regSetGPR; 1628 reg = gpr_rflags; 1629 break; 1630 1631 case GENERIC_REGNUM_RA: // Return Address 1632 default: 1633 return false; 1634 } 1635 } 1636 1637 if (GetRegisterState(set, false) != KERN_SUCCESS) 1638 return false; 1639 1640 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 1641 if (regInfo) 1642 { 1643 value->info = *regInfo; 1644 switch (set) 1645 { 1646 case e_regSetGPR: 1647 if (reg < k_num_gpr_registers) 1648 { 1649 value->value.uint64 = ((uint64_t*)(&m_state.context.gpr))[reg]; 1650 return true; 1651 } 1652 break; 1653 1654 case e_regSetFPU: 1655 if (CPUHasAVX() || FORCE_AVX_REGS) 1656 { 1657 switch (reg) 1658 { 1659 case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)); return true; 1660 case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)); return true; 1661 case fpu_ftw: value->value.uint8 = m_state.context.fpu.avx.__fpu_ftw; return true; 1662 case fpu_fop: value->value.uint16 = m_state.context.fpu.avx.__fpu_fop; return true; 1663 case fpu_ip: value->value.uint32 = m_state.context.fpu.avx.__fpu_ip; return true; 1664 case fpu_cs: value->value.uint16 = m_state.context.fpu.avx.__fpu_cs; return true; 1665 case fpu_dp: value->value.uint32 = m_state.context.fpu.avx.__fpu_dp; return true; 1666 case fpu_ds: value->value.uint16 = m_state.context.fpu.avx.__fpu_ds; return true; 1667 case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr; return true; 1668 case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask; return true; 1669 1670 case fpu_stmm0: 1671 case fpu_stmm1: 1672 case fpu_stmm2: 1673 case fpu_stmm3: 1674 case fpu_stmm4: 1675 case fpu_stmm5: 1676 case fpu_stmm6: 1677 case fpu_stmm7: 1678 memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), 10); 1679 return true; 1680 1681 case fpu_xmm0: 1682 case fpu_xmm1: 1683 case fpu_xmm2: 1684 case fpu_xmm3: 1685 case fpu_xmm4: 1686 case fpu_xmm5: 1687 case fpu_xmm6: 1688 case fpu_xmm7: 1689 case fpu_xmm8: 1690 case fpu_xmm9: 1691 case fpu_xmm10: 1692 case fpu_xmm11: 1693 case fpu_xmm12: 1694 case fpu_xmm13: 1695 case fpu_xmm14: 1696 case fpu_xmm15: 1697 memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), 16); 1698 return true; 1699 1700 case fpu_ymm0: 1701 case fpu_ymm1: 1702 case fpu_ymm2: 1703 case fpu_ymm3: 1704 case fpu_ymm4: 1705 case fpu_ymm5: 1706 case fpu_ymm6: 1707 case fpu_ymm7: 1708 case fpu_ymm8: 1709 case fpu_ymm9: 1710 case fpu_ymm10: 1711 case fpu_ymm11: 1712 case fpu_ymm12: 1713 case fpu_ymm13: 1714 case fpu_ymm14: 1715 case fpu_ymm15: 1716 memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), 16); 1717 memcpy((&value->value.uint8) + 16, &m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), 16); 1718 return true; 1719 } 1720 } 1721 else 1722 { 1723 switch (reg) 1724 { 1725 case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)); return true; 1726 case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)); return true; 1727 case fpu_ftw: value->value.uint8 = m_state.context.fpu.no_avx.__fpu_ftw; return true; 1728 case fpu_fop: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop; return true; 1729 case fpu_ip: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip; return true; 1730 case fpu_cs: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs; return true; 1731 case fpu_dp: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp; return true; 1732 case fpu_ds: value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds; return true; 1733 case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr; return true; 1734 case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask; return true; 1735 1736 case fpu_stmm0: 1737 case fpu_stmm1: 1738 case fpu_stmm2: 1739 case fpu_stmm3: 1740 case fpu_stmm4: 1741 case fpu_stmm5: 1742 case fpu_stmm6: 1743 case fpu_stmm7: 1744 memcpy(&value->value.uint8, &m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), 10); 1745 return true; 1746 1747 case fpu_xmm0: 1748 case fpu_xmm1: 1749 case fpu_xmm2: 1750 case fpu_xmm3: 1751 case fpu_xmm4: 1752 case fpu_xmm5: 1753 case fpu_xmm6: 1754 case fpu_xmm7: 1755 case fpu_xmm8: 1756 case fpu_xmm9: 1757 case fpu_xmm10: 1758 case fpu_xmm11: 1759 case fpu_xmm12: 1760 case fpu_xmm13: 1761 case fpu_xmm14: 1762 case fpu_xmm15: 1763 memcpy(&value->value.uint8, &m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), 16); 1764 return true; 1765 } 1766 } 1767 break; 1768 1769 case e_regSetEXC: 1770 switch (reg) 1771 { 1772 case exc_trapno: value->value.uint32 = m_state.context.exc.__trapno; return true; 1773 case exc_err: value->value.uint32 = m_state.context.exc.__err; return true; 1774 case exc_faultvaddr:value->value.uint64 = m_state.context.exc.__faultvaddr; return true; 1775 } 1776 break; 1777 } 1778 } 1779 return false; 1780 } 1781 1782 1783 bool 1784 DNBArchImplX86_64::SetRegisterValue(int set, int reg, const DNBRegisterValue *value) 1785 { 1786 if (set == REGISTER_SET_GENERIC) 1787 { 1788 switch (reg) 1789 { 1790 case GENERIC_REGNUM_PC: // Program Counter 1791 set = e_regSetGPR; 1792 reg = gpr_rip; 1793 break; 1794 1795 case GENERIC_REGNUM_SP: // Stack Pointer 1796 set = e_regSetGPR; 1797 reg = gpr_rsp; 1798 break; 1799 1800 case GENERIC_REGNUM_FP: // Frame Pointer 1801 set = e_regSetGPR; 1802 reg = gpr_rbp; 1803 break; 1804 1805 case GENERIC_REGNUM_FLAGS: // Processor flags register 1806 set = e_regSetGPR; 1807 reg = gpr_rflags; 1808 break; 1809 1810 case GENERIC_REGNUM_RA: // Return Address 1811 default: 1812 return false; 1813 } 1814 } 1815 1816 if (GetRegisterState(set, false) != KERN_SUCCESS) 1817 return false; 1818 1819 bool success = false; 1820 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 1821 if (regInfo) 1822 { 1823 switch (set) 1824 { 1825 case e_regSetGPR: 1826 if (reg < k_num_gpr_registers) 1827 { 1828 ((uint64_t*)(&m_state.context.gpr))[reg] = value->value.uint64; 1829 success = true; 1830 } 1831 break; 1832 1833 case e_regSetFPU: 1834 if (CPUHasAVX() || FORCE_AVX_REGS) 1835 { 1836 switch (reg) 1837 { 1838 case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) = value->value.uint16; success = true; break; 1839 case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) = value->value.uint16; success = true; break; 1840 case fpu_ftw: m_state.context.fpu.avx.__fpu_ftw = value->value.uint8; success = true; break; 1841 case fpu_fop: m_state.context.fpu.avx.__fpu_fop = value->value.uint16; success = true; break; 1842 case fpu_ip: m_state.context.fpu.avx.__fpu_ip = value->value.uint32; success = true; break; 1843 case fpu_cs: m_state.context.fpu.avx.__fpu_cs = value->value.uint16; success = true; break; 1844 case fpu_dp: m_state.context.fpu.avx.__fpu_dp = value->value.uint32; success = true; break; 1845 case fpu_ds: m_state.context.fpu.avx.__fpu_ds = value->value.uint16; success = true; break; 1846 case fpu_mxcsr: m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32; success = true; break; 1847 case fpu_mxcsrmask: m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32; success = true; break; 1848 1849 case fpu_stmm0: 1850 case fpu_stmm1: 1851 case fpu_stmm2: 1852 case fpu_stmm3: 1853 case fpu_stmm4: 1854 case fpu_stmm5: 1855 case fpu_stmm6: 1856 case fpu_stmm7: 1857 memcpy (&m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10); 1858 success = true; 1859 break; 1860 1861 case fpu_xmm0: 1862 case fpu_xmm1: 1863 case fpu_xmm2: 1864 case fpu_xmm3: 1865 case fpu_xmm4: 1866 case fpu_xmm5: 1867 case fpu_xmm6: 1868 case fpu_xmm7: 1869 case fpu_xmm8: 1870 case fpu_xmm9: 1871 case fpu_xmm10: 1872 case fpu_xmm11: 1873 case fpu_xmm12: 1874 case fpu_xmm13: 1875 case fpu_xmm14: 1876 case fpu_xmm15: 1877 memcpy (&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16); 1878 success = true; 1879 break; 1880 1881 case fpu_ymm0: 1882 case fpu_ymm1: 1883 case fpu_ymm2: 1884 case fpu_ymm3: 1885 case fpu_ymm4: 1886 case fpu_ymm5: 1887 case fpu_ymm6: 1888 case fpu_ymm7: 1889 case fpu_ymm8: 1890 case fpu_ymm9: 1891 case fpu_ymm10: 1892 case fpu_ymm11: 1893 case fpu_ymm12: 1894 case fpu_ymm13: 1895 case fpu_ymm14: 1896 case fpu_ymm15: 1897 memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), &value->value.uint8, 16); 1898 memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), (&value->value.uint8) + 16, 16); 1899 return true; 1900 } 1901 } 1902 else 1903 { 1904 switch (reg) 1905 { 1906 case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = value->value.uint16; success = true; break; 1907 case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = value->value.uint16; success = true; break; 1908 case fpu_ftw: m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8; success = true; break; 1909 case fpu_fop: m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16; success = true; break; 1910 case fpu_ip: m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32; success = true; break; 1911 case fpu_cs: m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16; success = true; break; 1912 case fpu_dp: m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32; success = true; break; 1913 case fpu_ds: m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16; success = true; break; 1914 case fpu_mxcsr: m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32; success = true; break; 1915 case fpu_mxcsrmask: m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32; success = true; break; 1916 1917 case fpu_stmm0: 1918 case fpu_stmm1: 1919 case fpu_stmm2: 1920 case fpu_stmm3: 1921 case fpu_stmm4: 1922 case fpu_stmm5: 1923 case fpu_stmm6: 1924 case fpu_stmm7: 1925 memcpy (&m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10); 1926 success = true; 1927 break; 1928 1929 case fpu_xmm0: 1930 case fpu_xmm1: 1931 case fpu_xmm2: 1932 case fpu_xmm3: 1933 case fpu_xmm4: 1934 case fpu_xmm5: 1935 case fpu_xmm6: 1936 case fpu_xmm7: 1937 case fpu_xmm8: 1938 case fpu_xmm9: 1939 case fpu_xmm10: 1940 case fpu_xmm11: 1941 case fpu_xmm12: 1942 case fpu_xmm13: 1943 case fpu_xmm14: 1944 case fpu_xmm15: 1945 memcpy (&m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16); 1946 success = true; 1947 break; 1948 } 1949 } 1950 break; 1951 1952 case e_regSetEXC: 1953 switch (reg) 1954 { 1955 case exc_trapno: m_state.context.exc.__trapno = value->value.uint32; success = true; break; 1956 case exc_err: m_state.context.exc.__err = value->value.uint32; success = true; break; 1957 case exc_faultvaddr:m_state.context.exc.__faultvaddr = value->value.uint64; success = true; break; 1958 } 1959 break; 1960 } 1961 } 1962 1963 if (success) 1964 return SetRegisterState(set) == KERN_SUCCESS; 1965 return false; 1966 } 1967 1968 uint32_t 1969 DNBArchImplX86_64::GetRegisterContextSize() 1970 { 1971 static uint32_t g_cached_size = 0; 1972 if (g_cached_size == 0) 1973 { 1974 if (CPUHasAVX() || FORCE_AVX_REGS) 1975 { 1976 for (size_t i=0; i<k_num_fpu_registers_avx; ++i) 1977 { 1978 if (g_fpu_registers_avx[i].value_regs == NULL) 1979 g_cached_size += g_fpu_registers_avx[i].size; 1980 } 1981 } 1982 else 1983 { 1984 for (size_t i=0; i<k_num_fpu_registers_no_avx; ++i) 1985 { 1986 if (g_fpu_registers_no_avx[i].value_regs == NULL) 1987 g_cached_size += g_fpu_registers_no_avx[i].size; 1988 } 1989 } 1990 DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, FPU = %u, EXC = %zu", sizeof(GPR), g_cached_size, sizeof(EXC)); 1991 g_cached_size += sizeof(GPR); 1992 g_cached_size += sizeof(EXC); 1993 DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u", g_cached_size); 1994 } 1995 return g_cached_size; 1996 } 1997 1998 nub_size_t 1999 DNBArchImplX86_64::GetRegisterContext (void *buf, nub_size_t buf_len) 2000 { 2001 uint32_t size = GetRegisterContextSize(); 2002 2003 if (buf && buf_len) 2004 { 2005 bool force = false; 2006 kern_return_t kret; 2007 2008 if ((kret = GetGPRState(force)) != KERN_SUCCESS) 2009 { 2010 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to read: %u ", buf, (uint64_t)buf_len, kret); 2011 size = 0; 2012 } 2013 else 2014 if ((kret = GetFPUState(force)) != KERN_SUCCESS) 2015 { 2016 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) error: %s regs failed to read: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); 2017 size = 0; 2018 } 2019 else 2020 if ((kret = GetEXCState(force)) != KERN_SUCCESS) 2021 { 2022 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) error: EXC regs failed to read: %u", buf, (uint64_t)buf_len, kret); 2023 size = 0; 2024 } 2025 else 2026 { 2027 uint8_t *p = (uint8_t *)buf; 2028 // Copy the GPR registers 2029 memcpy(p, &m_state.context.gpr, sizeof(GPR)); 2030 p += sizeof(GPR); 2031 2032 if (CPUHasAVX() || FORCE_AVX_REGS) 2033 { 2034 // Walk around the gaps in the FPU regs 2035 memcpy(p, &m_state.context.fpu.avx.__fpu_fcw, 5); 2036 p += 5; 2037 memcpy(p, &m_state.context.fpu.avx.__fpu_fop, 8); 2038 p += 8; 2039 memcpy(p, &m_state.context.fpu.avx.__fpu_dp, 6); 2040 p += 6; 2041 memcpy(p, &m_state.context.fpu.avx.__fpu_mxcsr, 8); 2042 p += 8; 2043 2044 // Work around the padding between the stmm registers as they are 16 2045 // byte structs with 10 bytes of the value in each 2046 for (size_t i=0; i<8; ++i) 2047 { 2048 memcpy(p, &m_state.context.fpu.avx.__fpu_stmm0 + i, 10); 2049 p += 10; 2050 } 2051 2052 // Interleave the XMM and YMMH registers to make the YMM registers 2053 for (size_t i=0; i<16; ++i) 2054 { 2055 memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16); 2056 p += 16; 2057 memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16); 2058 p += 16; 2059 } 2060 } 2061 else 2062 { 2063 // Walk around the gaps in the FPU regs 2064 memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5); 2065 p += 5; 2066 memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8); 2067 p += 8; 2068 memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6); 2069 p += 6; 2070 memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8); 2071 p += 8; 2072 2073 // Work around the padding between the stmm registers as they are 16 2074 // byte structs with 10 bytes of the value in each 2075 for (size_t i=0; i<8; ++i) 2076 { 2077 memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10); 2078 p += 10; 2079 } 2080 2081 // Copy the XMM registers in a single block 2082 memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 16 * 16); 2083 p += 16 * 16; 2084 } 2085 2086 // Copy the exception registers 2087 memcpy(p, &m_state.context.exc, sizeof(EXC)); 2088 p += sizeof(EXC); 2089 2090 // make sure we end up with exactly what we think we should have 2091 size_t bytes_written = p - (uint8_t *)buf; 2092 assert (bytes_written == size); 2093 } 2094 2095 } 2096 2097 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %llu) => %u", buf, (uint64_t)buf_len, size); 2098 // Return the size of the register context even if NULL was passed in 2099 return size; 2100 } 2101 2102 nub_size_t 2103 DNBArchImplX86_64::SetRegisterContext (const void *buf, nub_size_t buf_len) 2104 { 2105 uint32_t size = GetRegisterContextSize(); 2106 if (buf == NULL || buf_len == 0) 2107 size = 0; 2108 2109 if (size) 2110 { 2111 if (size > buf_len) 2112 size = buf_len; 2113 2114 uint8_t *p = (uint8_t *)buf; 2115 // Copy the GPR registers 2116 memcpy(&m_state.context.gpr, p, sizeof(GPR)); 2117 p += sizeof(GPR); 2118 2119 if (CPUHasAVX() || FORCE_AVX_REGS) 2120 { 2121 // Walk around the gaps in the FPU regs 2122 memcpy(&m_state.context.fpu.avx.__fpu_fcw, p, 5); 2123 p += 5; 2124 memcpy(&m_state.context.fpu.avx.__fpu_fop, p, 8); 2125 p += 8; 2126 memcpy(&m_state.context.fpu.avx.__fpu_dp, p, 6); 2127 p += 6; 2128 memcpy(&m_state.context.fpu.avx.__fpu_mxcsr, p, 8); 2129 p += 8; 2130 2131 // Work around the padding between the stmm registers as they are 16 2132 // byte structs with 10 bytes of the value in each 2133 for (size_t i=0; i<8; ++i) 2134 { 2135 memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + i, p, 10); 2136 p += 10; 2137 } 2138 2139 // Interleave the XMM and YMMH registers to make the YMM registers 2140 for (size_t i=0; i<16; ++i) 2141 { 2142 memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16); 2143 p += 16; 2144 memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16); 2145 p += 16; 2146 } 2147 } 2148 else 2149 { 2150 // Copy fcw through mxcsrmask as there is no padding 2151 memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5); 2152 p += 5; 2153 memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8); 2154 p += 8; 2155 memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6); 2156 p += 6; 2157 memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8); 2158 p += 8; 2159 2160 // Work around the padding between the stmm registers as they are 16 2161 // byte structs with 10 bytes of the value in each 2162 for (size_t i=0; i<8; ++i) 2163 { 2164 memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10); 2165 p += 10; 2166 } 2167 2168 // Copy the XMM registers in a single block 2169 memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 16 * 16); 2170 p += 16 * 16; 2171 } 2172 2173 // Copy the exception registers 2174 memcpy(&m_state.context.exc, p, sizeof(EXC)); 2175 p += sizeof(EXC); 2176 2177 // make sure we end up with exactly what we think we should have 2178 size_t bytes_written = p - (uint8_t *)buf; 2179 assert (bytes_written == size); 2180 2181 kern_return_t kret; 2182 if ((kret = SetGPRState()) != KERN_SUCCESS) 2183 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to write: %u", buf, (uint64_t)buf_len, kret); 2184 if ((kret = SetFPUState()) != KERN_SUCCESS) 2185 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) error: %s regs failed to write: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret); 2186 if ((kret = SetEXCState()) != KERN_SUCCESS) 2187 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) error: EXP regs failed to write: %u", buf, (uint64_t)buf_len, kret); 2188 } 2189 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size); 2190 return size; 2191 } 2192 2193 uint32_t 2194 DNBArchImplX86_64::SaveRegisterState () 2195 { 2196 kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber()); 2197 DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); 2198 2199 // Always re-read the registers because above we call thread_abort_safely(); 2200 bool force = true; 2201 2202 if ((kret = GetGPRState(force)) != KERN_SUCCESS) 2203 { 2204 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () error: GPR regs failed to read: %u ", kret); 2205 } 2206 else if ((kret = GetFPUState(force)) != KERN_SUCCESS) 2207 { 2208 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SaveRegisterState () error: %s regs failed to read: %u", CPUHasAVX() ? "AVX" : "FPU", kret); 2209 } 2210 else 2211 { 2212 const uint32_t save_id = GetNextRegisterStateSaveID (); 2213 m_saved_register_states[save_id] = m_state.context; 2214 return save_id; 2215 } 2216 return 0; 2217 } 2218 bool 2219 DNBArchImplX86_64::RestoreRegisterState (uint32_t save_id) 2220 { 2221 SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id); 2222 if (pos != m_saved_register_states.end()) 2223 { 2224 m_state.context.gpr = pos->second.gpr; 2225 m_state.context.fpu = pos->second.fpu; 2226 m_state.SetError(e_regSetGPR, Read, 0); 2227 m_state.SetError(e_regSetFPU, Read, 0); 2228 kern_return_t kret; 2229 bool success = true; 2230 if ((kret = SetGPRState()) != KERN_SUCCESS) 2231 { 2232 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret); 2233 success = false; 2234 } 2235 else if ((kret = SetFPUState()) != KERN_SUCCESS) 2236 { 2237 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, CPUHasAVX() ? "AVX" : "FPU", kret); 2238 success = false; 2239 } 2240 m_saved_register_states.erase(pos); 2241 return success; 2242 } 2243 return false; 2244 } 2245 2246 2247 kern_return_t 2248 DNBArchImplX86_64::GetRegisterState(int set, bool force) 2249 { 2250 switch (set) 2251 { 2252 case e_regSetALL: return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); 2253 case e_regSetGPR: return GetGPRState(force); 2254 case e_regSetFPU: return GetFPUState(force); 2255 case e_regSetEXC: return GetEXCState(force); 2256 default: break; 2257 } 2258 return KERN_INVALID_ARGUMENT; 2259 } 2260 2261 kern_return_t 2262 DNBArchImplX86_64::SetRegisterState(int set) 2263 { 2264 // Make sure we have a valid context to set. 2265 if (RegisterSetStateIsValid(set)) 2266 { 2267 switch (set) 2268 { 2269 case e_regSetALL: return SetGPRState() | SetFPUState() | SetEXCState(); 2270 case e_regSetGPR: return SetGPRState(); 2271 case e_regSetFPU: return SetFPUState(); 2272 case e_regSetEXC: return SetEXCState(); 2273 default: break; 2274 } 2275 } 2276 return KERN_INVALID_ARGUMENT; 2277 } 2278 2279 bool 2280 DNBArchImplX86_64::RegisterSetStateIsValid (int set) const 2281 { 2282 return m_state.RegsAreValid(set); 2283 } 2284 2285 2286 2287 #endif // #if defined (__i386__) || defined (__x86_64__) 2288