DNBArchImplI386.cpp revision 20d338fad87eba91de65aa9bec76e01c04472848
1//===-- DNBArchImplI386.cpp -------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Created by Greg Clayton on 6/25/07. 11// 12//===----------------------------------------------------------------------===// 13 14#if defined (__i386__) || defined (__x86_64__) 15 16#include <sys/cdefs.h> 17 18#include "MacOSX/i386/DNBArchImplI386.h" 19#include "DNBLog.h" 20#include "MachThread.h" 21#include "MachProcess.h" 22 23enum 24{ 25 gpr_eax = 0, 26 gpr_ebx = 1, 27 gpr_ecx = 2, 28 gpr_edx = 3, 29 gpr_edi = 4, 30 gpr_esi = 5, 31 gpr_ebp = 6, 32 gpr_esp = 7, 33 gpr_ss = 8, 34 gpr_eflags = 9, 35 gpr_eip = 10, 36 gpr_cs = 11, 37 gpr_ds = 12, 38 gpr_es = 13, 39 gpr_fs = 14, 40 gpr_gs = 15, 41 k_num_gpr_regs 42}; 43 44enum { 45 fpu_fcw, 46 fpu_fsw, 47 fpu_ftw, 48 fpu_fop, 49 fpu_ip, 50 fpu_cs, 51 fpu_dp, 52 fpu_ds, 53 fpu_mxcsr, 54 fpu_mxcsrmask, 55 fpu_stmm0, 56 fpu_stmm1, 57 fpu_stmm2, 58 fpu_stmm3, 59 fpu_stmm4, 60 fpu_stmm5, 61 fpu_stmm6, 62 fpu_stmm7, 63 fpu_xmm0, 64 fpu_xmm1, 65 fpu_xmm2, 66 fpu_xmm3, 67 fpu_xmm4, 68 fpu_xmm5, 69 fpu_xmm6, 70 fpu_xmm7, 71 k_num_fpu_regs, 72 73 // Aliases 74 fpu_fctrl = fpu_fcw, 75 fpu_fstat = fpu_fsw, 76 fpu_ftag = fpu_ftw, 77 fpu_fiseg = fpu_cs, 78 fpu_fioff = fpu_ip, 79 fpu_foseg = fpu_ds, 80 fpu_fooff = fpu_dp 81}; 82 83enum { 84 exc_trapno, 85 exc_err, 86 exc_faultvaddr, 87 k_num_exc_regs, 88}; 89 90 91enum 92{ 93 gcc_eax = 0, 94 gcc_ecx, 95 gcc_edx, 96 gcc_ebx, 97 gcc_ebp, 98 gcc_esp, 99 gcc_esi, 100 gcc_edi, 101 gcc_eip, 102 gcc_eflags 103}; 104 105enum 106{ 107 dwarf_eax = 0, 108 dwarf_ecx, 109 dwarf_edx, 110 dwarf_ebx, 111 dwarf_esp, 112 dwarf_ebp, 113 dwarf_esi, 114 dwarf_edi, 115 dwarf_eip, 116 dwarf_eflags, 117 dwarf_stmm0 = 11, 118 dwarf_stmm1, 119 dwarf_stmm2, 120 dwarf_stmm3, 121 dwarf_stmm4, 122 dwarf_stmm5, 123 dwarf_stmm6, 124 dwarf_stmm7, 125 dwarf_xmm0 = 21, 126 dwarf_xmm1, 127 dwarf_xmm2, 128 dwarf_xmm3, 129 dwarf_xmm4, 130 dwarf_xmm5, 131 dwarf_xmm6, 132 dwarf_xmm7 133}; 134 135enum 136{ 137 gdb_eax = 0, 138 gdb_ecx = 1, 139 gdb_edx = 2, 140 gdb_ebx = 3, 141 gdb_esp = 4, 142 gdb_ebp = 5, 143 gdb_esi = 6, 144 gdb_edi = 7, 145 gdb_eip = 8, 146 gdb_eflags = 9, 147 gdb_cs = 10, 148 gdb_ss = 11, 149 gdb_ds = 12, 150 gdb_es = 13, 151 gdb_fs = 14, 152 gdb_gs = 15, 153 gdb_stmm0 = 16, 154 gdb_stmm1 = 17, 155 gdb_stmm2 = 18, 156 gdb_stmm3 = 19, 157 gdb_stmm4 = 20, 158 gdb_stmm5 = 21, 159 gdb_stmm6 = 22, 160 gdb_stmm7 = 23, 161 gdb_fctrl = 24, gdb_fcw = gdb_fctrl, 162 gdb_fstat = 25, gdb_fsw = gdb_fstat, 163 gdb_ftag = 26, gdb_ftw = gdb_ftag, 164 gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg, 165 gdb_fioff = 28, gdb_ip = gdb_fioff, 166 gdb_foseg = 29, gdb_fpu_ds = gdb_foseg, 167 gdb_fooff = 30, gdb_dp = gdb_fooff, 168 gdb_fop = 31, 169 gdb_xmm0 = 32, 170 gdb_xmm1 = 33, 171 gdb_xmm2 = 34, 172 gdb_xmm3 = 35, 173 gdb_xmm4 = 36, 174 gdb_xmm5 = 37, 175 gdb_xmm6 = 38, 176 gdb_xmm7 = 39, 177 gdb_mxcsr = 40, 178 gdb_mm0 = 41, 179 gdb_mm1 = 42, 180 gdb_mm2 = 43, 181 gdb_mm3 = 44, 182 gdb_mm4 = 45, 183 gdb_mm5 = 46, 184 gdb_mm6 = 47, 185 gdb_mm7 = 48 186}; 187 188uint64_t 189DNBArchImplI386::GetPC(uint64_t failValue) 190{ 191 // Get program counter 192 if (GetGPRState(false) == KERN_SUCCESS) 193 return m_state.context.gpr.__eip; 194 return failValue; 195} 196 197kern_return_t 198DNBArchImplI386::SetPC(uint64_t value) 199{ 200 // Get program counter 201 kern_return_t err = GetGPRState(false); 202 if (err == KERN_SUCCESS) 203 { 204 m_state.context.gpr.__eip = value; 205 err = SetGPRState(); 206 } 207 return err == KERN_SUCCESS; 208} 209 210uint64_t 211DNBArchImplI386::GetSP(uint64_t failValue) 212{ 213 // Get stack pointer 214 if (GetGPRState(false) == KERN_SUCCESS) 215 return m_state.context.gpr.__esp; 216 return failValue; 217} 218 219// Uncomment the value below to verify the values in the debugger. 220//#define DEBUG_GPR_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED 221//#define SET_GPR(reg) m_state.context.gpr.__##reg = gpr_##reg 222 223kern_return_t 224DNBArchImplI386::GetGPRState(bool force) 225{ 226 if (force || m_state.GetError(e_regSetGPR, Read)) 227 { 228#if DEBUG_GPR_VALUES 229 SET_GPR(eax); 230 SET_GPR(ebx); 231 SET_GPR(ecx); 232 SET_GPR(edx); 233 SET_GPR(edi); 234 SET_GPR(esi); 235 SET_GPR(ebp); 236 SET_GPR(esp); 237 SET_GPR(ss); 238 SET_GPR(eflags); 239 SET_GPR(eip); 240 SET_GPR(cs); 241 SET_GPR(ds); 242 SET_GPR(es); 243 SET_GPR(fs); 244 SET_GPR(gs); 245 m_state.SetError(e_regSetGPR, Read, 0); 246#else 247 mach_msg_type_number_t count = e_regSetWordSizeGPR; 248 m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->ThreadID(), x86_THREAD_STATE32, (thread_state_t)&m_state.context.gpr, &count)); 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_VALUES 1 // DO NOT CHECK IN WITH THIS DEFINE ENABLED 256 257kern_return_t 258DNBArchImplI386::GetFPUState(bool force) 259{ 260 if (force || m_state.GetError(e_regSetFPU, Read)) 261 { 262#if DEBUG_FPU_VALUES 263 m_state.context.fpu.__fpu_reserved[0] = -1; 264 m_state.context.fpu.__fpu_reserved[1] = -1; 265 *(uint16_t *)&(m_state.context.fpu.__fpu_fcw) = 0x1234; 266 *(uint16_t *)&(m_state.context.fpu.__fpu_fsw) = 0x5678; 267 m_state.context.fpu.__fpu_ftw = 1; 268 m_state.context.fpu.__fpu_rsrv1 = UINT8_MAX; 269 m_state.context.fpu.__fpu_fop = 2; 270 m_state.context.fpu.__fpu_ip = 3; 271 m_state.context.fpu.__fpu_cs = 4; 272 m_state.context.fpu.__fpu_rsrv2 = 5; 273 m_state.context.fpu.__fpu_dp = 6; 274 m_state.context.fpu.__fpu_ds = 7; 275 m_state.context.fpu.__fpu_rsrv3 = UINT16_MAX; 276 m_state.context.fpu.__fpu_mxcsr = 8; 277 m_state.context.fpu.__fpu_mxcsrmask = 9; 278 int i; 279 for (i=0; i<16; ++i) 280 { 281 if (i<10) 282 { 283 m_state.context.fpu.__fpu_stmm0.__mmst_reg[i] = 'a'; 284 m_state.context.fpu.__fpu_stmm1.__mmst_reg[i] = 'b'; 285 m_state.context.fpu.__fpu_stmm2.__mmst_reg[i] = 'c'; 286 m_state.context.fpu.__fpu_stmm3.__mmst_reg[i] = 'd'; 287 m_state.context.fpu.__fpu_stmm4.__mmst_reg[i] = 'e'; 288 m_state.context.fpu.__fpu_stmm5.__mmst_reg[i] = 'f'; 289 m_state.context.fpu.__fpu_stmm6.__mmst_reg[i] = 'g'; 290 m_state.context.fpu.__fpu_stmm7.__mmst_reg[i] = 'h'; 291 } 292 else 293 { 294 m_state.context.fpu.__fpu_stmm0.__mmst_reg[i] = INT8_MIN; 295 m_state.context.fpu.__fpu_stmm1.__mmst_reg[i] = INT8_MIN; 296 m_state.context.fpu.__fpu_stmm2.__mmst_reg[i] = INT8_MIN; 297 m_state.context.fpu.__fpu_stmm3.__mmst_reg[i] = INT8_MIN; 298 m_state.context.fpu.__fpu_stmm4.__mmst_reg[i] = INT8_MIN; 299 m_state.context.fpu.__fpu_stmm5.__mmst_reg[i] = INT8_MIN; 300 m_state.context.fpu.__fpu_stmm6.__mmst_reg[i] = INT8_MIN; 301 m_state.context.fpu.__fpu_stmm7.__mmst_reg[i] = INT8_MIN; 302 } 303 304 m_state.context.fpu.__fpu_xmm0.__xmm_reg[i] = '0'; 305 m_state.context.fpu.__fpu_xmm1.__xmm_reg[i] = '1'; 306 m_state.context.fpu.__fpu_xmm2.__xmm_reg[i] = '2'; 307 m_state.context.fpu.__fpu_xmm3.__xmm_reg[i] = '3'; 308 m_state.context.fpu.__fpu_xmm4.__xmm_reg[i] = '4'; 309 m_state.context.fpu.__fpu_xmm5.__xmm_reg[i] = '5'; 310 m_state.context.fpu.__fpu_xmm6.__xmm_reg[i] = '6'; 311 m_state.context.fpu.__fpu_xmm7.__xmm_reg[i] = '7'; 312 } 313 for (i=0; i<sizeof(m_state.context.fpu.__fpu_rsrv4); ++i) 314 m_state.context.fpu.__fpu_rsrv4[i] = INT8_MIN; 315 m_state.context.fpu.__fpu_reserved1 = -1; 316 m_state.SetError(e_regSetFPU, Read, 0); 317#else 318 mach_msg_type_number_t count = e_regSetWordSizeFPR; 319 m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->ThreadID(), x86_FLOAT_STATE32, (thread_state_t)&m_state.context.fpu, &count)); 320#endif 321 } 322 return m_state.GetError(e_regSetFPU, Read); 323} 324 325kern_return_t 326DNBArchImplI386::GetEXCState(bool force) 327{ 328 if (force || m_state.GetError(e_regSetEXC, Read)) 329 { 330 mach_msg_type_number_t count = e_regSetWordSizeEXC; 331 m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->ThreadID(), x86_EXCEPTION_STATE32, (thread_state_t)&m_state.context.exc, &count)); 332 } 333 return m_state.GetError(e_regSetEXC, Read); 334} 335 336kern_return_t 337DNBArchImplI386::SetGPRState() 338{ 339 m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->ThreadID(), x86_THREAD_STATE32, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR)); 340 return m_state.GetError(e_regSetGPR, Write); 341} 342 343kern_return_t 344DNBArchImplI386::SetFPUState() 345{ 346 m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), x86_FLOAT_STATE32, (thread_state_t)&m_state.context.fpu, e_regSetWordSizeFPR)); 347 return m_state.GetError(e_regSetFPU, Write); 348} 349 350kern_return_t 351DNBArchImplI386::SetEXCState() 352{ 353 m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->ThreadID(), x86_EXCEPTION_STATE32, (thread_state_t)&m_state.context.exc, e_regSetWordSizeEXC)); 354 return m_state.GetError(e_regSetEXC, Write); 355} 356 357void 358DNBArchImplI386::ThreadWillResume() 359{ 360 // Do we need to step this thread? If so, let the mach thread tell us so. 361 if (m_thread->IsStepping()) 362 { 363 // This is the primary thread, let the arch do anything it needs 364 EnableHardwareSingleStep(true) == KERN_SUCCESS; 365 } 366} 367 368bool 369DNBArchImplI386::ThreadDidStop() 370{ 371 bool success = true; 372 373 m_state.InvalidateAllRegisterStates(); 374 375 // Are we stepping a single instruction? 376 if (GetGPRState(true) == KERN_SUCCESS) 377 { 378 // We are single stepping, was this the primary thread? 379 if (m_thread->IsStepping()) 380 { 381 // This was the primary thread, we need to clear the trace 382 // bit if so. 383 success = EnableHardwareSingleStep(false) == KERN_SUCCESS; 384 } 385 else 386 { 387 // The MachThread will automatically restore the suspend count 388 // in ThreadDidStop(), so we don't need to do anything here if 389 // we weren't the primary thread the last time 390 } 391 } 392 return success; 393} 394 395bool 396DNBArchImplI386::NotifyException(MachException::Data& exc) 397{ 398 switch (exc.exc_type) 399 { 400 case EXC_BAD_ACCESS: 401 break; 402 case EXC_BAD_INSTRUCTION: 403 break; 404 case EXC_ARITHMETIC: 405 break; 406 case EXC_EMULATION: 407 break; 408 case EXC_SOFTWARE: 409 break; 410 case EXC_BREAKPOINT: 411 if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) 412 { 413 nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS); 414 if (pc != INVALID_NUB_ADDRESS && pc > 0) 415 { 416 pc -= 1; 417 // Check for a breakpoint at one byte prior to the current PC value 418 // since the PC will be just past the trap. 419 420 nub_break_t breakID = m_thread->Process()->Breakpoints().FindIDByAddress(pc); 421 if (NUB_BREAK_ID_IS_VALID(breakID)) 422 { 423 // Backup the PC for i386 since the trap was taken and the PC 424 // is at the address following the single byte trap instruction. 425 if (m_state.context.gpr.__eip > 0) 426 { 427 m_state.context.gpr.__eip = pc; 428 // Write the new PC back out 429 SetGPRState (); 430 } 431 432 m_thread->SetCurrentBreakpoint(breakID); 433 } 434 return true; 435 } 436 } 437 break; 438 case EXC_SYSCALL: 439 break; 440 case EXC_MACH_SYSCALL: 441 break; 442 case EXC_RPC_ALERT: 443 break; 444 } 445 return false; 446} 447 448 449// Set the single step bit in the processor status register. 450kern_return_t 451DNBArchImplI386::EnableHardwareSingleStep (bool enable) 452{ 453 if (GetGPRState(false) == KERN_SUCCESS) 454 { 455 const uint32_t trace_bit = 0x100u; 456 if (enable) 457 m_state.context.gpr.__eflags |= trace_bit; 458 else 459 m_state.context.gpr.__eflags &= ~trace_bit; 460 return SetGPRState(); 461 } 462 return m_state.GetError(e_regSetGPR, Read); 463} 464 465 466//---------------------------------------------------------------------- 467// Register information defintions 468//---------------------------------------------------------------------- 469 470 471#define GPR_OFFSET(reg) (offsetof (DNBArchImplI386::GPR, __##reg)) 472#define FPU_OFFSET(reg) (offsetof (DNBArchImplI386::FPU, __fpu_##reg) + offsetof (DNBArchImplI386::Context, fpu)) 473#define EXC_OFFSET(reg) (offsetof (DNBArchImplI386::EXC, __##reg) + offsetof (DNBArchImplI386::Context, exc)) 474 475#define GPR_SIZE(reg) (sizeof(((DNBArchImplI386::GPR *)NULL)->__##reg)) 476#define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg)) 477#define FPU_SIZE_MMST(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__mmst_reg)) 478#define FPU_SIZE_XMM(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__xmm_reg)) 479#define EXC_SIZE(reg) (sizeof(((DNBArchImplI386::EXC *)NULL)->__##reg)) 480 481// These macros will auto define the register name, alt name, register size, 482// register offset, encoding, format and native register. This ensures that 483// the register state structures are defined correctly and have the correct 484// sizes and offsets. 485 486// General purpose registers for 64 bit 487const DNBRegisterInfo 488DNBArchImplI386::g_gpr_registers[] = 489{ 490{ e_regSetGPR, gpr_eax, "eax" , NULL , Uint, Hex, GPR_SIZE(eax), GPR_OFFSET(eax) , gcc_eax , dwarf_eax , -1 , gdb_eax }, 491{ e_regSetGPR, gpr_ebx, "ebx" , NULL , Uint, Hex, GPR_SIZE(ebx), GPR_OFFSET(ebx) , gcc_ebx , dwarf_ebx , -1 , gdb_ebx }, 492{ e_regSetGPR, gpr_ecx, "ecx" , NULL , Uint, Hex, GPR_SIZE(ecx), GPR_OFFSET(ecx) , gcc_ecx , dwarf_ecx , -1 , gdb_ecx }, 493{ e_regSetGPR, gpr_edx, "edx" , NULL , Uint, Hex, GPR_SIZE(edx), GPR_OFFSET(edx) , gcc_edx , dwarf_edx , -1 , gdb_edx }, 494{ e_regSetGPR, gpr_edi, "edi" , NULL , Uint, Hex, GPR_SIZE(edi), GPR_OFFSET(edi) , gcc_edi , dwarf_edi , -1 , gdb_edi }, 495{ e_regSetGPR, gpr_esi, "esi" , NULL , Uint, Hex, GPR_SIZE(esi), GPR_OFFSET(esi) , gcc_esi , dwarf_esi , -1 , gdb_esi }, 496{ e_regSetGPR, gpr_ebp, "ebp" , "fp" , Uint, Hex, GPR_SIZE(ebp), GPR_OFFSET(ebp) , gcc_ebp , dwarf_ebp , GENERIC_REGNUM_FP , gdb_ebp }, 497{ e_regSetGPR, gpr_esp, "esp" , "sp" , Uint, Hex, GPR_SIZE(esp), GPR_OFFSET(esp) , gcc_esp , dwarf_esp , GENERIC_REGNUM_SP , gdb_esp }, 498{ e_regSetGPR, gpr_ss, "ss" , NULL , Uint, Hex, GPR_SIZE(ss), GPR_OFFSET(ss) , -1 , -1 , -1 , gdb_ss }, 499{ e_regSetGPR, gpr_eflags, "eflags", "flags" , Uint, Hex, GPR_SIZE(eflags), GPR_OFFSET(eflags) , gcc_eflags, dwarf_eflags , GENERIC_REGNUM_FLAGS , gdb_eflags}, 500{ e_regSetGPR, gpr_eip, "eip" , "pc" , Uint, Hex, GPR_SIZE(eip), GPR_OFFSET(eip) , gcc_eip , dwarf_eip , GENERIC_REGNUM_PC , gdb_eip }, 501{ e_regSetGPR, gpr_cs, "cs" , NULL , Uint, Hex, GPR_SIZE(cs), GPR_OFFSET(cs) , -1 , -1 , -1 , gdb_cs }, 502{ e_regSetGPR, gpr_ds, "ds" , NULL , Uint, Hex, GPR_SIZE(ds), GPR_OFFSET(ds) , -1 , -1 , -1 , gdb_ds }, 503{ e_regSetGPR, gpr_es, "es" , NULL , Uint, Hex, GPR_SIZE(es), GPR_OFFSET(es) , -1 , -1 , -1 , gdb_es }, 504{ e_regSetGPR, gpr_fs, "fs" , NULL , Uint, Hex, GPR_SIZE(fs), GPR_OFFSET(fs) , -1 , -1 , -1 , gdb_fs }, 505{ e_regSetGPR, gpr_gs, "gs" , NULL , Uint, Hex, GPR_SIZE(gs), GPR_OFFSET(gs) , -1 , -1 , -1 , gdb_gs } 506}; 507 508 509const DNBRegisterInfo 510DNBArchImplI386::g_fpu_registers[] = 511{ 512{ e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , FPU_OFFSET(fcw) , -1, -1, -1, -1 }, 513{ e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , FPU_OFFSET(fsw) , -1, -1, -1, -1 }, 514{ e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , FPU_OFFSET(ftw) , -1, -1, -1, -1 }, 515{ e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , FPU_OFFSET(fop) , -1, -1, -1, -1 }, 516{ e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , FPU_OFFSET(ip) , -1, -1, -1, -1 }, 517{ e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , FPU_OFFSET(cs) , -1, -1, -1, -1 }, 518{ e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , FPU_OFFSET(dp) , -1, -1, -1, -1 }, 519{ e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , FPU_OFFSET(ds) , -1, -1, -1, -1 }, 520{ e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , FPU_OFFSET(mxcsr) , -1, -1, -1, -1 }, 521{ e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , -1, -1, -1, -1 }, 522 523{ e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), -1, dwarf_stmm0, -1, gdb_stmm0 }, 524{ e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), -1, dwarf_stmm1, -1, gdb_stmm1 }, 525{ e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), -1, dwarf_stmm2, -1, gdb_stmm2 }, 526{ e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), -1, dwarf_stmm3, -1, gdb_stmm3 }, 527{ e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), -1, dwarf_stmm4, -1, gdb_stmm4 }, 528{ e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), -1, dwarf_stmm5, -1, gdb_stmm5 }, 529{ e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), -1, dwarf_stmm6, -1, gdb_stmm6 }, 530{ e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), -1, dwarf_stmm7, -1, gdb_stmm7 }, 531 532{ e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), -1, dwarf_xmm0, -1, gdb_xmm0 }, 533{ e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), -1, dwarf_xmm1, -1, gdb_xmm1 }, 534{ e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), -1, dwarf_xmm2, -1, gdb_xmm2 }, 535{ e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), -1, dwarf_xmm3, -1, gdb_xmm3 }, 536{ e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), -1, dwarf_xmm4, -1, gdb_xmm4 }, 537{ e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), -1, dwarf_xmm5, -1, gdb_xmm5 }, 538{ e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), -1, dwarf_xmm6, -1, gdb_xmm6 }, 539{ e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), -1, dwarf_xmm7, -1, gdb_xmm7 } 540}; 541 542 543 544const DNBRegisterInfo 545DNBArchImplI386::g_exc_registers[] = 546{ 547{ e_regSetEXC, exc_trapno, "trapno" , NULL, Uint, Hex, EXC_SIZE (trapno) , EXC_OFFSET (trapno) , -1, -1, -1, -1 }, 548{ e_regSetEXC, exc_err, "err" , NULL, Uint, Hex, EXC_SIZE (err) , EXC_OFFSET (err) , -1, -1, -1, -1 }, 549{ e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr) , -1, -1, -1, -1 } 550}; 551 552// Number of registers in each register set 553const size_t DNBArchImplI386::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); 554const size_t DNBArchImplI386::k_num_fpu_registers = sizeof(g_fpu_registers)/sizeof(DNBRegisterInfo); 555const size_t DNBArchImplI386::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); 556const size_t DNBArchImplI386::k_num_all_registers = k_num_gpr_registers + k_num_fpu_registers + k_num_exc_registers; 557 558//---------------------------------------------------------------------- 559// Register set definitions. The first definitions at register set index 560// of zero is for all registers, followed by other registers sets. The 561// register information for the all register set need not be filled in. 562//---------------------------------------------------------------------- 563const DNBRegisterSetInfo 564DNBArchImplI386::g_reg_sets[] = 565{ 566 { "i386 Registers", NULL, k_num_all_registers }, 567 { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, 568 { "Floating Point Registers", g_fpu_registers, k_num_fpu_registers }, 569 { "Exception State Registers", g_exc_registers, k_num_exc_registers } 570}; 571// Total number of register sets for this architecture 572const size_t DNBArchImplI386::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); 573 574 575DNBArchProtocol * 576DNBArchImplI386::Create (MachThread *thread) 577{ 578 return new DNBArchImplI386 (thread); 579} 580 581const uint8_t * const 582DNBArchImplI386::SoftwareBreakpointOpcode (nub_size_t byte_size) 583{ 584 static const uint8_t g_breakpoint_opcode[] = { 0xCC }; 585 if (byte_size == 1) 586 return g_breakpoint_opcode; 587 return NULL; 588} 589 590const DNBRegisterSetInfo * 591DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) 592{ 593 *num_reg_sets = k_num_register_sets; 594 return g_reg_sets; 595} 596 597 598void 599DNBArchImplI386::Initialize() 600{ 601 DNBArchPluginInfo arch_plugin_info = 602 { 603 CPU_TYPE_I386, 604 DNBArchImplI386::Create, 605 DNBArchImplI386::GetRegisterSetInfo, 606 DNBArchImplI386::SoftwareBreakpointOpcode 607 }; 608 609 // Register this arch plug-in with the main protocol class 610 DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); 611} 612 613bool 614DNBArchImplI386::GetRegisterValue(int set, int reg, DNBRegisterValue *value) 615{ 616 if (set == REGISTER_SET_GENERIC) 617 { 618 switch (reg) 619 { 620 case GENERIC_REGNUM_PC: // Program Counter 621 set = e_regSetGPR; 622 reg = gpr_eip; 623 break; 624 625 case GENERIC_REGNUM_SP: // Stack Pointer 626 set = e_regSetGPR; 627 reg = gpr_esp; 628 break; 629 630 case GENERIC_REGNUM_FP: // Frame Pointer 631 set = e_regSetGPR; 632 reg = gpr_ebp; 633 break; 634 635 case GENERIC_REGNUM_FLAGS: // Processor flags register 636 set = e_regSetGPR; 637 reg = gpr_eflags; 638 break; 639 640 case GENERIC_REGNUM_RA: // Return Address 641 default: 642 return false; 643 } 644 } 645 646 if (GetRegisterState(set, false) != KERN_SUCCESS) 647 return false; 648 649 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 650 if (regInfo) 651 { 652 value->info = *regInfo; 653 switch (set) 654 { 655 case e_regSetGPR: 656 if (reg < k_num_gpr_registers) 657 { 658 value->value.uint32 = ((uint32_t*)(&m_state.context.gpr))[reg]; 659 return true; 660 } 661 break; 662 663 case e_regSetFPU: 664 switch (reg) 665 { 666 case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.__fpu_fcw)); return true; 667 case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.__fpu_fsw)); return true; 668 case fpu_ftw: value->value.uint8 = m_state.context.fpu.__fpu_ftw; return true; 669 case fpu_fop: value->value.uint16 = m_state.context.fpu.__fpu_fop; return true; 670 case fpu_ip: value->value.uint32 = m_state.context.fpu.__fpu_ip; return true; 671 case fpu_cs: value->value.uint16 = m_state.context.fpu.__fpu_cs; return true; 672 case fpu_dp: value->value.uint32 = m_state.context.fpu.__fpu_dp; return true; 673 case fpu_ds: value->value.uint16 = m_state.context.fpu.__fpu_ds; return true; 674 case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.__fpu_mxcsr; return true; 675 case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.__fpu_mxcsrmask; return true; 676 677 case fpu_stmm0: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm0.__mmst_reg, 10); return true; 678 case fpu_stmm1: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm1.__mmst_reg, 10); return true; 679 case fpu_stmm2: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm2.__mmst_reg, 10); return true; 680 case fpu_stmm3: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm3.__mmst_reg, 10); return true; 681 case fpu_stmm4: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm4.__mmst_reg, 10); return true; 682 case fpu_stmm5: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm5.__mmst_reg, 10); return true; 683 case fpu_stmm6: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm6.__mmst_reg, 10); return true; 684 case fpu_stmm7: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm7.__mmst_reg, 10); return true; 685 686 case fpu_xmm0: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm0.__xmm_reg, 16); return true; 687 case fpu_xmm1: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm1.__xmm_reg, 16); return true; 688 case fpu_xmm2: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm2.__xmm_reg, 16); return true; 689 case fpu_xmm3: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm3.__xmm_reg, 16); return true; 690 case fpu_xmm4: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm4.__xmm_reg, 16); return true; 691 case fpu_xmm5: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm5.__xmm_reg, 16); return true; 692 case fpu_xmm6: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm6.__xmm_reg, 16); return true; 693 case fpu_xmm7: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm7.__xmm_reg, 16); return true; 694 } 695 break; 696 697 case e_regSetEXC: 698 if (reg < k_num_exc_registers) 699 { 700 value->value.uint32 = (&m_state.context.exc.__trapno)[reg]; 701 return true; 702 } 703 break; 704 } 705 } 706 return false; 707} 708 709 710bool 711DNBArchImplI386::SetRegisterValue(int set, int reg, const DNBRegisterValue *value) 712{ 713 if (set == REGISTER_SET_GENERIC) 714 { 715 switch (reg) 716 { 717 case GENERIC_REGNUM_PC: // Program Counter 718 set = e_regSetGPR; 719 reg = gpr_eip; 720 break; 721 722 case GENERIC_REGNUM_SP: // Stack Pointer 723 set = e_regSetGPR; 724 reg = gpr_esp; 725 break; 726 727 case GENERIC_REGNUM_FP: // Frame Pointer 728 set = e_regSetGPR; 729 reg = gpr_ebp; 730 break; 731 732 case GENERIC_REGNUM_FLAGS: // Processor flags register 733 set = e_regSetGPR; 734 reg = gpr_eflags; 735 break; 736 737 case GENERIC_REGNUM_RA: // Return Address 738 default: 739 return false; 740 } 741 } 742 743 if (GetRegisterState(set, false) != KERN_SUCCESS) 744 return false; 745 746 bool success = false; 747 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 748 if (regInfo) 749 { 750 switch (set) 751 { 752 case e_regSetGPR: 753 if (reg < k_num_gpr_registers) 754 { 755 ((uint32_t*)(&m_state.context.gpr))[reg] = value->value.uint32; 756 success = true; 757 } 758 break; 759 760 case e_regSetFPU: 761 switch (reg) 762 { 763 case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.__fpu_fcw)) = value->value.uint16; success = true; break; 764 case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.__fpu_fsw)) = value->value.uint16; success = true; break; 765 case fpu_ftw: m_state.context.fpu.__fpu_ftw = value->value.uint8; success = true; break; 766 case fpu_fop: m_state.context.fpu.__fpu_fop = value->value.uint16; success = true; break; 767 case fpu_ip: m_state.context.fpu.__fpu_ip = value->value.uint32; success = true; break; 768 case fpu_cs: m_state.context.fpu.__fpu_cs = value->value.uint16; success = true; break; 769 case fpu_dp: m_state.context.fpu.__fpu_dp = value->value.uint32; success = true; break; 770 case fpu_ds: m_state.context.fpu.__fpu_ds = value->value.uint16; success = true; break; 771 case fpu_mxcsr: m_state.context.fpu.__fpu_mxcsr = value->value.uint32; success = true; break; 772 case fpu_mxcsrmask: m_state.context.fpu.__fpu_mxcsrmask = value->value.uint32; success = true; break; 773 774 case fpu_stmm0: memcpy (m_state.context.fpu.__fpu_stmm0.__mmst_reg, &value->value.uint8, 10); success = true; break; 775 case fpu_stmm1: memcpy (m_state.context.fpu.__fpu_stmm1.__mmst_reg, &value->value.uint8, 10); success = true; break; 776 case fpu_stmm2: memcpy (m_state.context.fpu.__fpu_stmm2.__mmst_reg, &value->value.uint8, 10); success = true; break; 777 case fpu_stmm3: memcpy (m_state.context.fpu.__fpu_stmm3.__mmst_reg, &value->value.uint8, 10); success = true; break; 778 case fpu_stmm4: memcpy (m_state.context.fpu.__fpu_stmm4.__mmst_reg, &value->value.uint8, 10); success = true; break; 779 case fpu_stmm5: memcpy (m_state.context.fpu.__fpu_stmm5.__mmst_reg, &value->value.uint8, 10); success = true; break; 780 case fpu_stmm6: memcpy (m_state.context.fpu.__fpu_stmm6.__mmst_reg, &value->value.uint8, 10); success = true; break; 781 case fpu_stmm7: memcpy (m_state.context.fpu.__fpu_stmm7.__mmst_reg, &value->value.uint8, 10); success = true; break; 782 783 case fpu_xmm0: memcpy(m_state.context.fpu.__fpu_xmm0.__xmm_reg, &value->value.uint8, 16); success = true; break; 784 case fpu_xmm1: memcpy(m_state.context.fpu.__fpu_xmm1.__xmm_reg, &value->value.uint8, 16); success = true; break; 785 case fpu_xmm2: memcpy(m_state.context.fpu.__fpu_xmm2.__xmm_reg, &value->value.uint8, 16); success = true; break; 786 case fpu_xmm3: memcpy(m_state.context.fpu.__fpu_xmm3.__xmm_reg, &value->value.uint8, 16); success = true; break; 787 case fpu_xmm4: memcpy(m_state.context.fpu.__fpu_xmm4.__xmm_reg, &value->value.uint8, 16); success = true; break; 788 case fpu_xmm5: memcpy(m_state.context.fpu.__fpu_xmm5.__xmm_reg, &value->value.uint8, 16); success = true; break; 789 case fpu_xmm6: memcpy(m_state.context.fpu.__fpu_xmm6.__xmm_reg, &value->value.uint8, 16); success = true; break; 790 case fpu_xmm7: memcpy(m_state.context.fpu.__fpu_xmm7.__xmm_reg, &value->value.uint8, 16); success = true; break; 791 } 792 break; 793 794 case e_regSetEXC: 795 if (reg < k_num_exc_registers) 796 { 797 (&m_state.context.exc.__trapno)[reg] = value->value.uint32; 798 success = true; 799 } 800 break; 801 } 802 } 803 804 if (success) 805 return SetRegisterState(set) == KERN_SUCCESS; 806 return false; 807} 808 809 810nub_size_t 811DNBArchImplI386::GetRegisterContext (void *buf, nub_size_t buf_len) 812{ 813 nub_size_t size = sizeof (m_state.context); 814 815 if (buf && buf_len) 816 { 817 if (size > buf_len) 818 size = buf_len; 819 820 bool force = false; 821 if (GetGPRState(force) | GetFPUState(force) | GetEXCState(force)) 822 return 0; 823 ::memcpy (buf, &m_state.context, size); 824 } 825 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); 826 // Return the size of the register context even if NULL was passed in 827 return size; 828} 829 830nub_size_t 831DNBArchImplI386::SetRegisterContext (const void *buf, nub_size_t buf_len) 832{ 833 nub_size_t size = sizeof (m_state.context); 834 if (buf == NULL || buf_len == 0) 835 size = 0; 836 837 if (size) 838 { 839 if (size > buf_len) 840 size = buf_len; 841 842 ::memcpy (&m_state.context, buf, size); 843 SetGPRState(); 844 SetFPUState(); 845 SetEXCState(); 846 } 847 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); 848 return size; 849} 850 851 852 853kern_return_t 854DNBArchImplI386::GetRegisterState(int set, bool force) 855{ 856 switch (set) 857 { 858 case e_regSetALL: return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); 859 case e_regSetGPR: return GetGPRState(force); 860 case e_regSetFPU: return GetFPUState(force); 861 case e_regSetEXC: return GetEXCState(force); 862 default: break; 863 } 864 return KERN_INVALID_ARGUMENT; 865} 866 867kern_return_t 868DNBArchImplI386::SetRegisterState(int set) 869{ 870 // Make sure we have a valid context to set. 871 if (RegisterSetStateIsValid(set)) 872 { 873 switch (set) 874 { 875 case e_regSetALL: return SetGPRState() | SetFPUState() | SetEXCState(); 876 case e_regSetGPR: return SetGPRState(); 877 case e_regSetFPU: return SetFPUState(); 878 case e_regSetEXC: return SetEXCState(); 879 default: break; 880 } 881 } 882 return KERN_INVALID_ARGUMENT; 883} 884 885bool 886DNBArchImplI386::RegisterSetStateIsValid (int set) const 887{ 888 return m_state.RegsAreValid(set); 889} 890 891 892 893#endif // #if defined (__i386__) 894