1 /* 2 * Copyright (C) 2004 PathScale, Inc 3 * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 * Licensed under the GPL 5 */ 6 7 #include <errno.h> 8 #include <sys/ptrace.h> 9 #ifdef __i386__ 10 #include <sys/user.h> 11 #endif 12 #include <longjmp.h> 13 #include <sysdep/ptrace_user.h> 14 #include <sys/uio.h> 15 #include <asm/sigcontext.h> 16 #include <linux/elf.h> 17 18 int have_xstate_support; 19 20 int save_i387_registers(int pid, unsigned long *fp_regs) 21 { 22 if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) 23 return -errno; 24 return 0; 25 } 26 27 int save_fp_registers(int pid, unsigned long *fp_regs) 28 { 29 struct iovec iov; 30 31 if (have_xstate_support) { 32 iov.iov_base = fp_regs; 33 iov.iov_len = sizeof(struct _xstate); 34 if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 35 return -errno; 36 return 0; 37 } else { 38 return save_i387_registers(pid, fp_regs); 39 } 40 } 41 42 int restore_i387_registers(int pid, unsigned long *fp_regs) 43 { 44 if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) 45 return -errno; 46 return 0; 47 } 48 49 int restore_fp_registers(int pid, unsigned long *fp_regs) 50 { 51 struct iovec iov; 52 53 if (have_xstate_support) { 54 iov.iov_base = fp_regs; 55 iov.iov_len = sizeof(struct _xstate); 56 if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) 57 return -errno; 58 return 0; 59 } else { 60 return restore_i387_registers(pid, fp_regs); 61 } 62 } 63 64 #ifdef __i386__ 65 int have_fpx_regs = 1; 66 int save_fpx_registers(int pid, unsigned long *fp_regs) 67 { 68 if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) 69 return -errno; 70 return 0; 71 } 72 73 int restore_fpx_registers(int pid, unsigned long *fp_regs) 74 { 75 if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) 76 return -errno; 77 return 0; 78 } 79 80 int get_fp_registers(int pid, unsigned long *regs) 81 { 82 if (have_fpx_regs) 83 return save_fpx_registers(pid, regs); 84 else 85 return save_fp_registers(pid, regs); 86 } 87 88 int put_fp_registers(int pid, unsigned long *regs) 89 { 90 if (have_fpx_regs) 91 return restore_fpx_registers(pid, regs); 92 else 93 return restore_fp_registers(pid, regs); 94 } 95 96 void arch_init_registers(int pid) 97 { 98 struct user_fpxregs_struct fpx_regs; 99 int err; 100 101 err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); 102 if (!err) 103 return; 104 105 if (errno != EIO) 106 panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", 107 errno); 108 109 have_fpx_regs = 0; 110 } 111 #else 112 113 int get_fp_registers(int pid, unsigned long *regs) 114 { 115 return save_fp_registers(pid, regs); 116 } 117 118 int put_fp_registers(int pid, unsigned long *regs) 119 { 120 return restore_fp_registers(pid, regs); 121 } 122 123 void arch_init_registers(int pid) 124 { 125 struct _xstate fp_regs; 126 struct iovec iov; 127 128 iov.iov_base = &fp_regs; 129 iov.iov_len = sizeof(struct _xstate); 130 if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) 131 have_xstate_support = 1; 132 } 133 #endif 134 135 unsigned long get_thread_reg(int reg, jmp_buf *buf) 136 { 137 switch (reg) { 138 #ifdef __i386__ 139 case HOST_IP: 140 return buf[0]->__eip; 141 case HOST_SP: 142 return buf[0]->__esp; 143 case HOST_BP: 144 return buf[0]->__ebp; 145 #else 146 case HOST_IP: 147 return buf[0]->__rip; 148 case HOST_SP: 149 return buf[0]->__rsp; 150 case HOST_BP: 151 return buf[0]->__rbp; 152 #endif 153 default: 154 printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", 155 reg); 156 return 0; 157 } 158 } 159