DNBArchImplI386.cpp revision c71899ef308e6134d1b0ca5f30cbc64414855e1a
13d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman//===-- DNBArchImplI386.cpp -------------------------------------*- C++ -*-===// 23d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman// 33d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman// The LLVM Compiler Infrastructure 43d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman// 53d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman// This file is distributed under the University of Illinois Open Source 63d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman// License. See LICENSE.TXT for details. 73d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman// 83d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman//===----------------------------------------------------------------------===// 93d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman// 103d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman// Created by Greg Clayton on 6/25/07. 113d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman// 123d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman//===----------------------------------------------------------------------===// 133d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman 143d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman#if defined (__i386__) || defined (__x86_64__) 153d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman 163d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman#include <sys/cdefs.h> 173d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman 183d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman#include "MacOSX/i386/DNBArchImplI386.h" 193d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman#include "DNBLog.h" 203d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman#include "MachThread.h" 213d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman#include "MachProcess.h" 223d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman 233d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohmanenum 243d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman{ 253d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_eax = 0, 263d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_ebx = 1, 273d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_ecx = 2, 283d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_edx = 3, 293d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_edi = 4, 303d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_esi = 5, 313d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_ebp = 6, 323d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_esp = 7, 333d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_ss = 8, 343d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_eflags = 9, 353d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_eip = 10, 363d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_cs = 11, 373d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_ds = 12, 383d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_es = 13, 393d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_fs = 14, 403d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman gpr_gs = 15, 413d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman k_num_gpr_regs 423d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman}; 433d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman 443d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohmanenum { 453d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_fcw, 463d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_fsw, 473d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_ftw, 483d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_fop, 493d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_ip, 503d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_cs, 513d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_dp, 523d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_ds, 533d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_mxcsr, 543d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_mxcsrmask, 553d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_stmm0, 563d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_stmm1, 573d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_stmm2, 583d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_stmm3, 593d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_stmm4, 603d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_stmm5, 613d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_stmm6, 623d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_stmm7, 633d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_xmm0, 643d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_xmm1, 653d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_xmm2, 663d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman fpu_xmm3, 673d5aff5d3036b0ff09d114857cd2276134b3d8c9Dan Gohman 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 return true; 433 } 434 } 435 break; 436 case EXC_SYSCALL: 437 break; 438 case EXC_MACH_SYSCALL: 439 break; 440 case EXC_RPC_ALERT: 441 break; 442 } 443 return false; 444} 445 446 447// Set the single step bit in the processor status register. 448kern_return_t 449DNBArchImplI386::EnableHardwareSingleStep (bool enable) 450{ 451 if (GetGPRState(false) == KERN_SUCCESS) 452 { 453 const uint32_t trace_bit = 0x100u; 454 if (enable) 455 m_state.context.gpr.__eflags |= trace_bit; 456 else 457 m_state.context.gpr.__eflags &= ~trace_bit; 458 return SetGPRState(); 459 } 460 return m_state.GetError(e_regSetGPR, Read); 461} 462 463 464//---------------------------------------------------------------------- 465// Register information defintions 466//---------------------------------------------------------------------- 467 468 469#define GPR_OFFSET(reg) (offsetof (DNBArchImplI386::GPR, __##reg)) 470#define FPU_OFFSET(reg) (offsetof (DNBArchImplI386::FPU, __fpu_##reg) + offsetof (DNBArchImplI386::Context, fpu)) 471#define EXC_OFFSET(reg) (offsetof (DNBArchImplI386::EXC, __##reg) + offsetof (DNBArchImplI386::Context, exc)) 472 473#define GPR_SIZE(reg) (sizeof(((DNBArchImplI386::GPR *)NULL)->__##reg)) 474#define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg)) 475#define FPU_SIZE_MMST(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__mmst_reg)) 476#define FPU_SIZE_XMM(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__xmm_reg)) 477#define EXC_SIZE(reg) (sizeof(((DNBArchImplI386::EXC *)NULL)->__##reg)) 478 479// These macros will auto define the register name, alt name, register size, 480// register offset, encoding, format and native register. This ensures that 481// the register state structures are defined correctly and have the correct 482// sizes and offsets. 483 484// General purpose registers for 64 bit 485const DNBRegisterInfo 486DNBArchImplI386::g_gpr_registers[] = 487{ 488{ e_regSetGPR, gpr_eax, "eax" , NULL , Uint, Hex, GPR_SIZE(eax), GPR_OFFSET(eax) , gcc_eax , dwarf_eax , -1 , gdb_eax }, 489{ e_regSetGPR, gpr_ebx, "ebx" , NULL , Uint, Hex, GPR_SIZE(ebx), GPR_OFFSET(ebx) , gcc_ebx , dwarf_ebx , -1 , gdb_ebx }, 490{ e_regSetGPR, gpr_ecx, "ecx" , NULL , Uint, Hex, GPR_SIZE(ecx), GPR_OFFSET(ecx) , gcc_ecx , dwarf_ecx , -1 , gdb_ecx }, 491{ e_regSetGPR, gpr_edx, "edx" , NULL , Uint, Hex, GPR_SIZE(edx), GPR_OFFSET(edx) , gcc_edx , dwarf_edx , -1 , gdb_edx }, 492{ e_regSetGPR, gpr_edi, "edi" , NULL , Uint, Hex, GPR_SIZE(edi), GPR_OFFSET(edi) , gcc_edi , dwarf_edi , -1 , gdb_edi }, 493{ e_regSetGPR, gpr_esi, "esi" , NULL , Uint, Hex, GPR_SIZE(esi), GPR_OFFSET(esi) , gcc_esi , dwarf_esi , -1 , gdb_esi }, 494{ e_regSetGPR, gpr_ebp, "ebp" , "fp" , Uint, Hex, GPR_SIZE(ebp), GPR_OFFSET(ebp) , gcc_ebp , dwarf_ebp , GENERIC_REGNUM_FP , gdb_ebp }, 495{ e_regSetGPR, gpr_esp, "esp" , "sp" , Uint, Hex, GPR_SIZE(esp), GPR_OFFSET(esp) , gcc_esp , dwarf_esp , GENERIC_REGNUM_SP , gdb_esp }, 496{ e_regSetGPR, gpr_ss, "ss" , NULL , Uint, Hex, GPR_SIZE(ss), GPR_OFFSET(ss) , -1 , -1 , -1 , gdb_ss }, 497{ e_regSetGPR, gpr_eflags, "eflags", "flags" , Uint, Hex, GPR_SIZE(eflags), GPR_OFFSET(eflags) , gcc_eflags, dwarf_eflags , GENERIC_REGNUM_FLAGS , gdb_eflags}, 498{ e_regSetGPR, gpr_eip, "eip" , "pc" , Uint, Hex, GPR_SIZE(eip), GPR_OFFSET(eip) , gcc_eip , dwarf_eip , GENERIC_REGNUM_PC , gdb_eip }, 499{ e_regSetGPR, gpr_cs, "cs" , NULL , Uint, Hex, GPR_SIZE(cs), GPR_OFFSET(cs) , -1 , -1 , -1 , gdb_cs }, 500{ e_regSetGPR, gpr_ds, "ds" , NULL , Uint, Hex, GPR_SIZE(ds), GPR_OFFSET(ds) , -1 , -1 , -1 , gdb_ds }, 501{ e_regSetGPR, gpr_es, "es" , NULL , Uint, Hex, GPR_SIZE(es), GPR_OFFSET(es) , -1 , -1 , -1 , gdb_es }, 502{ e_regSetGPR, gpr_fs, "fs" , NULL , Uint, Hex, GPR_SIZE(fs), GPR_OFFSET(fs) , -1 , -1 , -1 , gdb_fs }, 503{ e_regSetGPR, gpr_gs, "gs" , NULL , Uint, Hex, GPR_SIZE(gs), GPR_OFFSET(gs) , -1 , -1 , -1 , gdb_gs } 504}; 505 506 507const DNBRegisterInfo 508DNBArchImplI386::g_fpu_registers[] = 509{ 510{ e_regSetFPU, fpu_fcw , "fctrl" , NULL, Uint, Hex, FPU_SIZE_UINT(fcw) , FPU_OFFSET(fcw) , -1, -1, -1, -1 }, 511{ e_regSetFPU, fpu_fsw , "fstat" , NULL, Uint, Hex, FPU_SIZE_UINT(fsw) , FPU_OFFSET(fsw) , -1, -1, -1, -1 }, 512{ e_regSetFPU, fpu_ftw , "ftag" , NULL, Uint, Hex, FPU_SIZE_UINT(ftw) , FPU_OFFSET(ftw) , -1, -1, -1, -1 }, 513{ e_regSetFPU, fpu_fop , "fop" , NULL, Uint, Hex, FPU_SIZE_UINT(fop) , FPU_OFFSET(fop) , -1, -1, -1, -1 }, 514{ e_regSetFPU, fpu_ip , "fioff" , NULL, Uint, Hex, FPU_SIZE_UINT(ip) , FPU_OFFSET(ip) , -1, -1, -1, -1 }, 515{ e_regSetFPU, fpu_cs , "fiseg" , NULL, Uint, Hex, FPU_SIZE_UINT(cs) , FPU_OFFSET(cs) , -1, -1, -1, -1 }, 516{ e_regSetFPU, fpu_dp , "fooff" , NULL, Uint, Hex, FPU_SIZE_UINT(dp) , FPU_OFFSET(dp) , -1, -1, -1, -1 }, 517{ e_regSetFPU, fpu_ds , "foseg" , NULL, Uint, Hex, FPU_SIZE_UINT(ds) , FPU_OFFSET(ds) , -1, -1, -1, -1 }, 518{ e_regSetFPU, fpu_mxcsr , "mxcsr" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr) , FPU_OFFSET(mxcsr) , -1, -1, -1, -1 }, 519{ e_regSetFPU, fpu_mxcsrmask, "mxcsrmask" , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , -1, -1, -1, -1 }, 520 521{ e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), -1, dwarf_stmm0, -1, gdb_stmm0 }, 522{ e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), -1, dwarf_stmm1, -1, gdb_stmm1 }, 523{ e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), -1, dwarf_stmm2, -1, gdb_stmm2 }, 524{ e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), -1, dwarf_stmm3, -1, gdb_stmm3 }, 525{ e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), -1, dwarf_stmm4, -1, gdb_stmm4 }, 526{ e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), -1, dwarf_stmm5, -1, gdb_stmm5 }, 527{ e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), -1, dwarf_stmm6, -1, gdb_stmm6 }, 528{ e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), -1, dwarf_stmm7, -1, gdb_stmm7 }, 529 530{ e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), -1, dwarf_xmm0, -1, gdb_xmm0 }, 531{ e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), -1, dwarf_xmm1, -1, gdb_xmm1 }, 532{ e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), -1, dwarf_xmm2, -1, gdb_xmm2 }, 533{ e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), -1, dwarf_xmm3, -1, gdb_xmm3 }, 534{ e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), -1, dwarf_xmm4, -1, gdb_xmm4 }, 535{ e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), -1, dwarf_xmm5, -1, gdb_xmm5 }, 536{ e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), -1, dwarf_xmm6, -1, gdb_xmm6 }, 537{ e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), -1, dwarf_xmm7, -1, gdb_xmm7 } 538}; 539 540 541 542const DNBRegisterInfo 543DNBArchImplI386::g_exc_registers[] = 544{ 545{ e_regSetEXC, exc_trapno, "trapno" , NULL, Uint, Hex, EXC_SIZE (trapno) , EXC_OFFSET (trapno) , -1, -1, -1, -1 }, 546{ e_regSetEXC, exc_err, "err" , NULL, Uint, Hex, EXC_SIZE (err) , EXC_OFFSET (err) , -1, -1, -1, -1 }, 547{ e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr) , -1, -1, -1, -1 } 548}; 549 550// Number of registers in each register set 551const size_t DNBArchImplI386::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); 552const size_t DNBArchImplI386::k_num_fpu_registers = sizeof(g_fpu_registers)/sizeof(DNBRegisterInfo); 553const size_t DNBArchImplI386::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); 554const size_t DNBArchImplI386::k_num_all_registers = k_num_gpr_registers + k_num_fpu_registers + k_num_exc_registers; 555 556//---------------------------------------------------------------------- 557// Register set definitions. The first definitions at register set index 558// of zero is for all registers, followed by other registers sets. The 559// register information for the all register set need not be filled in. 560//---------------------------------------------------------------------- 561const DNBRegisterSetInfo 562DNBArchImplI386::g_reg_sets[] = 563{ 564 { "i386 Registers", NULL, k_num_all_registers }, 565 { "General Purpose Registers", g_gpr_registers, k_num_gpr_registers }, 566 { "Floating Point Registers", g_fpu_registers, k_num_fpu_registers }, 567 { "Exception State Registers", g_exc_registers, k_num_exc_registers } 568}; 569// Total number of register sets for this architecture 570const size_t DNBArchImplI386::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); 571 572 573DNBArchProtocol * 574DNBArchImplI386::Create (MachThread *thread) 575{ 576 return new DNBArchImplI386 (thread); 577} 578 579const uint8_t * const 580DNBArchImplI386::SoftwareBreakpointOpcode (nub_size_t byte_size) 581{ 582 static const uint8_t g_breakpoint_opcode[] = { 0xCC }; 583 if (byte_size == 1) 584 return g_breakpoint_opcode; 585 return NULL; 586} 587 588const DNBRegisterSetInfo * 589DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) 590{ 591 *num_reg_sets = k_num_register_sets; 592 return g_reg_sets; 593} 594 595 596void 597DNBArchImplI386::Initialize() 598{ 599 DNBArchPluginInfo arch_plugin_info = 600 { 601 CPU_TYPE_I386, 602 DNBArchImplI386::Create, 603 DNBArchImplI386::GetRegisterSetInfo, 604 DNBArchImplI386::SoftwareBreakpointOpcode 605 }; 606 607 // Register this arch plug-in with the main protocol class 608 DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); 609} 610 611bool 612DNBArchImplI386::GetRegisterValue(int set, int reg, DNBRegisterValue *value) 613{ 614 if (set == REGISTER_SET_GENERIC) 615 { 616 switch (reg) 617 { 618 case GENERIC_REGNUM_PC: // Program Counter 619 set = e_regSetGPR; 620 reg = gpr_eip; 621 break; 622 623 case GENERIC_REGNUM_SP: // Stack Pointer 624 set = e_regSetGPR; 625 reg = gpr_esp; 626 break; 627 628 case GENERIC_REGNUM_FP: // Frame Pointer 629 set = e_regSetGPR; 630 reg = gpr_ebp; 631 break; 632 633 case GENERIC_REGNUM_FLAGS: // Processor flags register 634 set = e_regSetGPR; 635 reg = gpr_eflags; 636 break; 637 638 case GENERIC_REGNUM_RA: // Return Address 639 default: 640 return false; 641 } 642 } 643 644 if (GetRegisterState(set, false) != KERN_SUCCESS) 645 return false; 646 647 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 648 if (regInfo) 649 { 650 value->info = *regInfo; 651 switch (set) 652 { 653 case e_regSetGPR: 654 if (reg < k_num_gpr_registers) 655 { 656 value->value.uint32 = ((uint32_t*)(&m_state.context.gpr))[reg]; 657 return true; 658 } 659 break; 660 661 case e_regSetFPU: 662 switch (reg) 663 { 664 case fpu_fcw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.__fpu_fcw)); return true; 665 case fpu_fsw: value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.__fpu_fsw)); return true; 666 case fpu_ftw: value->value.uint8 = m_state.context.fpu.__fpu_ftw; return true; 667 case fpu_fop: value->value.uint16 = m_state.context.fpu.__fpu_fop; return true; 668 case fpu_ip: value->value.uint32 = m_state.context.fpu.__fpu_ip; return true; 669 case fpu_cs: value->value.uint16 = m_state.context.fpu.__fpu_cs; return true; 670 case fpu_dp: value->value.uint32 = m_state.context.fpu.__fpu_dp; return true; 671 case fpu_ds: value->value.uint16 = m_state.context.fpu.__fpu_ds; return true; 672 case fpu_mxcsr: value->value.uint32 = m_state.context.fpu.__fpu_mxcsr; return true; 673 case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.__fpu_mxcsrmask; return true; 674 675 case fpu_stmm0: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm0.__mmst_reg, 10); return true; 676 case fpu_stmm1: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm1.__mmst_reg, 10); return true; 677 case fpu_stmm2: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm2.__mmst_reg, 10); return true; 678 case fpu_stmm3: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm3.__mmst_reg, 10); return true; 679 case fpu_stmm4: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm4.__mmst_reg, 10); return true; 680 case fpu_stmm5: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm5.__mmst_reg, 10); return true; 681 case fpu_stmm6: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm6.__mmst_reg, 10); return true; 682 case fpu_stmm7: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_stmm7.__mmst_reg, 10); return true; 683 684 case fpu_xmm0: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm0.__xmm_reg, 16); return true; 685 case fpu_xmm1: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm1.__xmm_reg, 16); return true; 686 case fpu_xmm2: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm2.__xmm_reg, 16); return true; 687 case fpu_xmm3: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm3.__xmm_reg, 16); return true; 688 case fpu_xmm4: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm4.__xmm_reg, 16); return true; 689 case fpu_xmm5: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm5.__xmm_reg, 16); return true; 690 case fpu_xmm6: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm6.__xmm_reg, 16); return true; 691 case fpu_xmm7: memcpy(&value->value.uint8, m_state.context.fpu.__fpu_xmm7.__xmm_reg, 16); return true; 692 } 693 break; 694 695 case e_regSetEXC: 696 if (reg < k_num_exc_registers) 697 { 698 value->value.uint32 = (&m_state.context.exc.__trapno)[reg]; 699 return true; 700 } 701 break; 702 } 703 } 704 return false; 705} 706 707 708bool 709DNBArchImplI386::SetRegisterValue(int set, int reg, const DNBRegisterValue *value) 710{ 711 if (set == REGISTER_SET_GENERIC) 712 { 713 switch (reg) 714 { 715 case GENERIC_REGNUM_PC: // Program Counter 716 set = e_regSetGPR; 717 reg = gpr_eip; 718 break; 719 720 case GENERIC_REGNUM_SP: // Stack Pointer 721 set = e_regSetGPR; 722 reg = gpr_esp; 723 break; 724 725 case GENERIC_REGNUM_FP: // Frame Pointer 726 set = e_regSetGPR; 727 reg = gpr_ebp; 728 break; 729 730 case GENERIC_REGNUM_FLAGS: // Processor flags register 731 set = e_regSetGPR; 732 reg = gpr_eflags; 733 break; 734 735 case GENERIC_REGNUM_RA: // Return Address 736 default: 737 return false; 738 } 739 } 740 741 if (GetRegisterState(set, false) != KERN_SUCCESS) 742 return false; 743 744 bool success = false; 745 const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); 746 if (regInfo) 747 { 748 switch (set) 749 { 750 case e_regSetGPR: 751 if (reg < k_num_gpr_registers) 752 { 753 ((uint32_t*)(&m_state.context.gpr))[reg] = value->value.uint32; 754 success = true; 755 } 756 break; 757 758 case e_regSetFPU: 759 switch (reg) 760 { 761 case fpu_fcw: *((uint16_t *)(&m_state.context.fpu.__fpu_fcw)) = value->value.uint16; success = true; break; 762 case fpu_fsw: *((uint16_t *)(&m_state.context.fpu.__fpu_fsw)) = value->value.uint16; success = true; break; 763 case fpu_ftw: m_state.context.fpu.__fpu_ftw = value->value.uint8; success = true; break; 764 case fpu_fop: m_state.context.fpu.__fpu_fop = value->value.uint16; success = true; break; 765 case fpu_ip: m_state.context.fpu.__fpu_ip = value->value.uint32; success = true; break; 766 case fpu_cs: m_state.context.fpu.__fpu_cs = value->value.uint16; success = true; break; 767 case fpu_dp: m_state.context.fpu.__fpu_dp = value->value.uint32; success = true; break; 768 case fpu_ds: m_state.context.fpu.__fpu_ds = value->value.uint16; success = true; break; 769 case fpu_mxcsr: m_state.context.fpu.__fpu_mxcsr = value->value.uint32; success = true; break; 770 case fpu_mxcsrmask: m_state.context.fpu.__fpu_mxcsrmask = value->value.uint32; success = true; break; 771 772 case fpu_stmm0: memcpy (m_state.context.fpu.__fpu_stmm0.__mmst_reg, &value->value.uint8, 10); success = true; break; 773 case fpu_stmm1: memcpy (m_state.context.fpu.__fpu_stmm1.__mmst_reg, &value->value.uint8, 10); success = true; break; 774 case fpu_stmm2: memcpy (m_state.context.fpu.__fpu_stmm2.__mmst_reg, &value->value.uint8, 10); success = true; break; 775 case fpu_stmm3: memcpy (m_state.context.fpu.__fpu_stmm3.__mmst_reg, &value->value.uint8, 10); success = true; break; 776 case fpu_stmm4: memcpy (m_state.context.fpu.__fpu_stmm4.__mmst_reg, &value->value.uint8, 10); success = true; break; 777 case fpu_stmm5: memcpy (m_state.context.fpu.__fpu_stmm5.__mmst_reg, &value->value.uint8, 10); success = true; break; 778 case fpu_stmm6: memcpy (m_state.context.fpu.__fpu_stmm6.__mmst_reg, &value->value.uint8, 10); success = true; break; 779 case fpu_stmm7: memcpy (m_state.context.fpu.__fpu_stmm7.__mmst_reg, &value->value.uint8, 10); success = true; break; 780 781 case fpu_xmm0: memcpy(m_state.context.fpu.__fpu_xmm0.__xmm_reg, &value->value.uint8, 16); success = true; break; 782 case fpu_xmm1: memcpy(m_state.context.fpu.__fpu_xmm1.__xmm_reg, &value->value.uint8, 16); success = true; break; 783 case fpu_xmm2: memcpy(m_state.context.fpu.__fpu_xmm2.__xmm_reg, &value->value.uint8, 16); success = true; break; 784 case fpu_xmm3: memcpy(m_state.context.fpu.__fpu_xmm3.__xmm_reg, &value->value.uint8, 16); success = true; break; 785 case fpu_xmm4: memcpy(m_state.context.fpu.__fpu_xmm4.__xmm_reg, &value->value.uint8, 16); success = true; break; 786 case fpu_xmm5: memcpy(m_state.context.fpu.__fpu_xmm5.__xmm_reg, &value->value.uint8, 16); success = true; break; 787 case fpu_xmm6: memcpy(m_state.context.fpu.__fpu_xmm6.__xmm_reg, &value->value.uint8, 16); success = true; break; 788 case fpu_xmm7: memcpy(m_state.context.fpu.__fpu_xmm7.__xmm_reg, &value->value.uint8, 16); success = true; break; 789 } 790 break; 791 792 case e_regSetEXC: 793 if (reg < k_num_exc_registers) 794 { 795 (&m_state.context.exc.__trapno)[reg] = value->value.uint32; 796 success = true; 797 } 798 break; 799 } 800 } 801 802 if (success) 803 return SetRegisterState(set) == KERN_SUCCESS; 804 return false; 805} 806 807 808nub_size_t 809DNBArchImplI386::GetRegisterContext (void *buf, nub_size_t buf_len) 810{ 811 nub_size_t size = sizeof (m_state.context); 812 813 if (buf && buf_len) 814 { 815 if (size > buf_len) 816 size = buf_len; 817 818 bool force = false; 819 if (GetGPRState(force) | GetFPUState(force) | GetEXCState(force)) 820 return 0; 821 ::memcpy (buf, &m_state.context, size); 822 } 823 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); 824 // Return the size of the register context even if NULL was passed in 825 return size; 826} 827 828nub_size_t 829DNBArchImplI386::SetRegisterContext (const void *buf, nub_size_t buf_len) 830{ 831 nub_size_t size = sizeof (m_state.context); 832 if (buf == NULL || buf_len == 0) 833 size = 0; 834 835 if (size) 836 { 837 if (size > buf_len) 838 size = buf_len; 839 840 ::memcpy (&m_state.context, buf, size); 841 SetGPRState(); 842 SetFPUState(); 843 SetEXCState(); 844 } 845 DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size); 846 return size; 847} 848 849 850 851kern_return_t 852DNBArchImplI386::GetRegisterState(int set, bool force) 853{ 854 switch (set) 855 { 856 case e_regSetALL: return GetGPRState(force) | GetFPUState(force) | GetEXCState(force); 857 case e_regSetGPR: return GetGPRState(force); 858 case e_regSetFPU: return GetFPUState(force); 859 case e_regSetEXC: return GetEXCState(force); 860 default: break; 861 } 862 return KERN_INVALID_ARGUMENT; 863} 864 865kern_return_t 866DNBArchImplI386::SetRegisterState(int set) 867{ 868 // Make sure we have a valid context to set. 869 if (RegisterSetStateIsValid(set)) 870 { 871 switch (set) 872 { 873 case e_regSetALL: return SetGPRState() | SetFPUState() | SetEXCState(); 874 case e_regSetGPR: return SetGPRState(); 875 case e_regSetFPU: return SetFPUState(); 876 case e_regSetEXC: return SetEXCState(); 877 default: break; 878 } 879 } 880 return KERN_INVALID_ARGUMENT; 881} 882 883bool 884DNBArchImplI386::RegisterSetStateIsValid (int set) const 885{ 886 return m_state.RegsAreValid(set); 887} 888 889 890 891#endif // #if defined (__i386__) 892