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