1 /* 2 * Copyright 2003 PathScale, Inc. 3 * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 * 5 * Licensed under the GPL 6 */ 7 8 #include <linux/mm.h> 9 #include <linux/sched.h> 10 #include <linux/errno.h> 11 #define __FRAME_OFFSETS 12 #include <asm/ptrace.h> 13 #include <asm/uaccess.h> 14 #include <asm/ptrace-abi.h> 15 16 /* 17 * determines which flags the user has access to. 18 * 1 = access 0 = no access 19 */ 20 #define FLAG_MASK 0x44dd5UL 21 22 static const int reg_offsets[] = 23 { 24 [R8 >> 3] = HOST_R8, 25 [R9 >> 3] = HOST_R9, 26 [R10 >> 3] = HOST_R10, 27 [R11 >> 3] = HOST_R11, 28 [R12 >> 3] = HOST_R12, 29 [R13 >> 3] = HOST_R13, 30 [R14 >> 3] = HOST_R14, 31 [R15 >> 3] = HOST_R15, 32 [RIP >> 3] = HOST_IP, 33 [RSP >> 3] = HOST_SP, 34 [RAX >> 3] = HOST_AX, 35 [RBX >> 3] = HOST_BX, 36 [RCX >> 3] = HOST_CX, 37 [RDX >> 3] = HOST_DX, 38 [RSI >> 3] = HOST_SI, 39 [RDI >> 3] = HOST_DI, 40 [RBP >> 3] = HOST_BP, 41 [CS >> 3] = HOST_CS, 42 [SS >> 3] = HOST_SS, 43 [FS_BASE >> 3] = HOST_FS_BASE, 44 [GS_BASE >> 3] = HOST_GS_BASE, 45 [DS >> 3] = HOST_DS, 46 [ES >> 3] = HOST_ES, 47 [FS >> 3] = HOST_FS, 48 [GS >> 3] = HOST_GS, 49 [EFLAGS >> 3] = HOST_EFLAGS, 50 [ORIG_RAX >> 3] = HOST_ORIG_AX, 51 }; 52 53 int putreg(struct task_struct *child, int regno, unsigned long value) 54 { 55 #ifdef TIF_IA32 56 /* 57 * Some code in the 64bit emulation may not be 64bit clean. 58 * Don't take any chances. 59 */ 60 if (test_tsk_thread_flag(child, TIF_IA32)) 61 value &= 0xffffffff; 62 #endif 63 switch (regno) { 64 case R8: 65 case R9: 66 case R10: 67 case R11: 68 case R12: 69 case R13: 70 case R14: 71 case R15: 72 case RIP: 73 case RSP: 74 case RAX: 75 case RBX: 76 case RCX: 77 case RDX: 78 case RSI: 79 case RDI: 80 case RBP: 81 case ORIG_RAX: 82 break; 83 84 case FS: 85 case GS: 86 case DS: 87 case ES: 88 case SS: 89 case CS: 90 if (value && (value & 3) != 3) 91 return -EIO; 92 value &= 0xffff; 93 break; 94 95 case FS_BASE: 96 case GS_BASE: 97 if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) 98 return -EIO; 99 break; 100 101 case EFLAGS: 102 value &= FLAG_MASK; 103 child->thread.regs.regs.gp[HOST_EFLAGS] |= value; 104 return 0; 105 106 default: 107 panic("Bad register in putreg(): %d\n", regno); 108 } 109 110 child->thread.regs.regs.gp[reg_offsets[regno >> 3]] = value; 111 return 0; 112 } 113 114 int poke_user(struct task_struct *child, long addr, long data) 115 { 116 if ((addr & 3) || addr < 0) 117 return -EIO; 118 119 if (addr < MAX_REG_OFFSET) 120 return putreg(child, addr, data); 121 else if ((addr >= offsetof(struct user, u_debugreg[0])) && 122 (addr <= offsetof(struct user, u_debugreg[7]))) { 123 addr -= offsetof(struct user, u_debugreg[0]); 124 addr = addr >> 2; 125 if ((addr == 4) || (addr == 5)) 126 return -EIO; 127 child->thread.arch.debugregs[addr] = data; 128 return 0; 129 } 130 return -EIO; 131 } 132 133 unsigned long getreg(struct task_struct *child, int regno) 134 { 135 unsigned long mask = ~0UL; 136 #ifdef TIF_IA32 137 if (test_tsk_thread_flag(child, TIF_IA32)) 138 mask = 0xffffffff; 139 #endif 140 switch (regno) { 141 case R8: 142 case R9: 143 case R10: 144 case R11: 145 case R12: 146 case R13: 147 case R14: 148 case R15: 149 case RIP: 150 case RSP: 151 case RAX: 152 case RBX: 153 case RCX: 154 case RDX: 155 case RSI: 156 case RDI: 157 case RBP: 158 case ORIG_RAX: 159 case EFLAGS: 160 case FS_BASE: 161 case GS_BASE: 162 break; 163 case FS: 164 case GS: 165 case DS: 166 case ES: 167 case SS: 168 case CS: 169 mask = 0xffff; 170 break; 171 default: 172 panic("Bad register in getreg: %d\n", regno); 173 } 174 return mask & child->thread.regs.regs.gp[reg_offsets[regno >> 3]]; 175 } 176 177 int peek_user(struct task_struct *child, long addr, long data) 178 { 179 /* read the word at location addr in the USER area. */ 180 unsigned long tmp; 181 182 if ((addr & 3) || addr < 0) 183 return -EIO; 184 185 tmp = 0; /* Default return condition */ 186 if (addr < MAX_REG_OFFSET) 187 tmp = getreg(child, addr); 188 else if ((addr >= offsetof(struct user, u_debugreg[0])) && 189 (addr <= offsetof(struct user, u_debugreg[7]))) { 190 addr -= offsetof(struct user, u_debugreg[0]); 191 addr = addr >> 2; 192 tmp = child->thread.arch.debugregs[addr]; 193 } 194 return put_user(tmp, (unsigned long *) data); 195 } 196 197 /* XXX Mostly copied from sys-i386 */ 198 int is_syscall(unsigned long addr) 199 { 200 unsigned short instr; 201 int n; 202 203 n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); 204 if (n) { 205 /* 206 * access_process_vm() grants access to vsyscall and stub, 207 * while copy_from_user doesn't. Maybe access_process_vm is 208 * slow, but that doesn't matter, since it will be called only 209 * in case of singlestepping, if copy_from_user failed. 210 */ 211 n = access_process_vm(current, addr, &instr, sizeof(instr), 0); 212 if (n != sizeof(instr)) { 213 printk("is_syscall : failed to read instruction from " 214 "0x%lx\n", addr); 215 return 1; 216 } 217 } 218 /* sysenter */ 219 return instr == 0x050f; 220 } 221 222 static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 223 { 224 int err, n, cpu = ((struct thread_info *) child->stack)->cpu; 225 long fpregs[HOST_FP_SIZE]; 226 227 BUG_ON(sizeof(*buf) != sizeof(fpregs)); 228 err = save_fp_registers(userspace_pid[cpu], fpregs); 229 if (err) 230 return err; 231 232 n = copy_to_user(buf, fpregs, sizeof(fpregs)); 233 if (n > 0) 234 return -EFAULT; 235 236 return n; 237 } 238 239 static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) 240 { 241 int n, cpu = ((struct thread_info *) child->stack)->cpu; 242 long fpregs[HOST_FP_SIZE]; 243 244 BUG_ON(sizeof(*buf) != sizeof(fpregs)); 245 n = copy_from_user(fpregs, buf, sizeof(fpregs)); 246 if (n > 0) 247 return -EFAULT; 248 249 return restore_fp_registers(userspace_pid[cpu], fpregs); 250 } 251 252 long subarch_ptrace(struct task_struct *child, long request, 253 unsigned long addr, unsigned long data) 254 { 255 int ret = -EIO; 256 void __user *datap = (void __user *) data; 257 258 switch (request) { 259 case PTRACE_GETFPREGS: /* Get the child FPU state. */ 260 ret = get_fpregs(datap, child); 261 break; 262 case PTRACE_SETFPREGS: /* Set the child FPU state. */ 263 ret = set_fpregs(datap, child); 264 break; 265 case PTRACE_ARCH_PRCTL: 266 /* XXX Calls ptrace on the host - needs some SMP thinking */ 267 ret = arch_prctl(child, data, (void __user *) addr); 268 break; 269 } 270 271 return ret; 272 } 273