vserver 2.0 rc7
[linux-2.6.git] / arch / parisc / kernel / ptrace.c
1 /*
2  * Kernel support for the ptrace() and syscall tracing interfaces.
3  *
4  * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc.
5  * Copyright (C) 2000 Matthew Wilcox <matthew@wil.cx>
6  * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/sched.h>
11 #include <linux/mm.h>
12 #include <linux/smp.h>
13 #include <linux/smp_lock.h>
14 #include <linux/errno.h>
15 #include <linux/ptrace.h>
16 #include <linux/user.h>
17 #include <linux/personality.h>
18 #include <linux/security.h>
19 #include <linux/compat.h>
20 #include <linux/signal.h>
21
22 #include <asm/uaccess.h>
23 #include <asm/pgtable.h>
24 #include <asm/system.h>
25 #include <asm/processor.h>
26 #include <asm/offsets.h>
27
28 /* PSW bits we allow the debugger to modify */
29 #define USER_PSW_BITS   (PSW_N | PSW_V | PSW_CB)
30
31 #undef DEBUG_PTRACE
32
33 #ifdef DEBUG_PTRACE
34 #define DBG(x...)       printk(x)
35 #else
36 #define DBG(x...)
37 #endif
38
39 #ifdef __LP64__
40
41 /* This function is needed to translate 32 bit pt_regs offsets in to
42  * 64 bit pt_regs offsets.  For example, a 32 bit gdb under a 64 bit kernel
43  * will request offset 12 if it wants gr3, but the lower 32 bits of
44  * the 64 bit kernels view of gr3 will be at offset 28 (3*8 + 4).
45  * This code relies on a 32 bit pt_regs being comprised of 32 bit values
46  * except for the fp registers which (a) are 64 bits, and (b) follow
47  * the gr registers at the start of pt_regs.  The 32 bit pt_regs should
48  * be half the size of the 64 bit pt_regs, plus 32*4 to allow for fr[]
49  * being 64 bit in both cases.
50  */
51
52 static long translate_usr_offset(long offset)
53 {
54         if (offset < 0)
55                 return -1;
56         else if (offset <= 32*4)        /* gr[0..31] */
57                 return offset * 2 + 4;
58         else if (offset <= 32*4+32*8)   /* gr[0..31] + fr[0..31] */
59                 return offset + 32*4;
60         else if (offset < sizeof(struct pt_regs)/2 + 32*4)
61                 return offset * 2 + 4 - 32*8;
62         else
63                 return -1;
64 }
65 #endif
66
67 /*
68  * Called by kernel/ptrace.c when detaching..
69  *
70  * Make sure single step bits etc are not set.
71  */
72 void ptrace_disable(struct task_struct *child)
73 {
74         /* make sure the trap bits are not set */
75         pa_psw(child)->r = 0;
76         pa_psw(child)->t = 0;
77         pa_psw(child)->h = 0;
78         pa_psw(child)->l = 0;
79 }
80
81 long sys_ptrace(long request, pid_t pid, long addr, long data)
82 {
83         struct task_struct *child;
84         long ret;
85 #ifdef DEBUG_PTRACE
86         long oaddr=addr, odata=data;
87 #endif
88
89         lock_kernel();
90         ret = -EPERM;
91         if (request == PTRACE_TRACEME) {
92                 /* are we already being traced? */
93                 if (current->ptrace & PT_PTRACED)
94                         goto out;
95
96                 ret = security_ptrace(current->parent, current);
97                 if (ret) 
98                         goto out;
99
100                 /* set the ptrace bit in the process flags. */
101                 current->ptrace |= PT_PTRACED;
102                 ret = 0;
103                 goto out;
104         }
105
106         ret = -ESRCH;
107         read_lock(&tasklist_lock);
108         child = find_task_by_pid(pid);
109         if (child)
110                 get_task_struct(child);
111         read_unlock(&tasklist_lock);
112         if (!child)
113                 goto out;
114         if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
115                 goto out_tsk;
116
117         ret = -EPERM;
118         if (pid == 1)           /* no messing around with init! */
119                 goto out_tsk;
120
121         if (request == PTRACE_ATTACH) {
122                 ret = ptrace_attach(child);
123                 goto out_tsk;
124         }
125
126         ret = ptrace_check_attach(child, request == PTRACE_KILL);
127         if (ret < 0)
128                 goto out_tsk;
129
130         switch (request) {
131         case PTRACE_PEEKTEXT: /* read word at location addr. */ 
132         case PTRACE_PEEKDATA: {
133                 int copied;
134
135 #ifdef __LP64__
136                 if (is_compat_task(child)) {
137                         unsigned int tmp;
138
139                         addr &= 0xffffffffL;
140                         copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
141                         ret = -EIO;
142                         if (copied != sizeof(tmp))
143                                 goto out_tsk;
144                         ret = put_user(tmp,(unsigned int *) data);
145                         DBG("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n",
146                                 request == PTRACE_PEEKTEXT ? "TEXT" : "DATA",
147                                 pid, oaddr, odata, ret, tmp);
148                 }
149                 else
150 #endif
151                 {
152                         unsigned long tmp;
153
154                         copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
155                         ret = -EIO;
156                         if (copied != sizeof(tmp))
157                                 goto out_tsk;
158                         ret = put_user(tmp,(unsigned long *) data);
159                 }
160                 goto out_tsk;
161         }
162
163         /* when I and D space are separate, this will have to be fixed. */
164         case PTRACE_POKETEXT: /* write the word at location addr. */
165         case PTRACE_POKEDATA:
166                 ret = 0;
167 #ifdef __LP64__
168                 if (is_compat_task(child)) {
169                         unsigned int tmp = (unsigned int)data;
170                         DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
171                                 request == PTRACE_POKETEXT ? "TEXT" : "DATA",
172                                 pid, oaddr, odata);
173                         addr &= 0xffffffffL;
174                         if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp))
175                                 goto out_tsk;
176                 }
177                 else
178 #endif
179                 {
180                         if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
181                                 goto out_tsk;
182                 }
183                 ret = -EIO;
184                 goto out_tsk;
185
186         /* Read the word at location addr in the USER area.  For ptraced
187            processes, the kernel saves all regs on a syscall. */
188         case PTRACE_PEEKUSR: {
189                 ret = -EIO;
190 #ifdef __LP64__
191                 if (is_compat_task(child)) {
192                         unsigned int tmp;
193
194                         if (addr & (sizeof(int)-1))
195                                 goto out_tsk;
196                         if ((addr = translate_usr_offset(addr)) < 0)
197                                 goto out_tsk;
198
199                         tmp = *(unsigned int *) ((char *) task_regs(child) + addr);
200                         ret = put_user(tmp, (unsigned int *) data);
201                         DBG("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n",
202                                 pid, oaddr, odata, ret, addr, tmp);
203                 }
204                 else
205 #endif
206                 {
207                         unsigned long tmp;
208
209                         if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
210                                 goto out_tsk;
211                         tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
212                         ret = put_user(tmp, (unsigned long *) data);
213                 }
214                 goto out_tsk;
215         }
216
217         /* Write the word at location addr in the USER area.  This will need
218            to change when the kernel no longer saves all regs on a syscall.
219            FIXME.  There is a problem at the moment in that r3-r18 are only
220            saved if the process is ptraced on syscall entry, and even then
221            those values are overwritten by actual register values on syscall
222            exit. */
223         case PTRACE_POKEUSR:
224                 ret = -EIO;
225                 /* Some register values written here may be ignored in
226                  * entry.S:syscall_restore_rfi; e.g. iaoq is written with
227                  * r31/r31+4, and not with the values in pt_regs.
228                  */
229                  /* PT_PSW=0, so this is valid for 32 bit processes under 64
230                  * bit kernels.
231                  */
232                 if (addr == PT_PSW) {
233                         /* PT_PSW=0, so this is valid for 32 bit processes
234                          * under 64 bit kernels.
235                          *
236                          * Allow writing to Nullify, Divide-step-correction,
237                          * and carry/borrow bits.
238                          * BEWARE, if you set N, and then single step, it won't
239                          * stop on the nullified instruction.
240                          */
241                         DBG("sys_ptrace(POKEUSR, %d, %lx, %lx)\n",
242                                 pid, oaddr, odata);
243                         data &= USER_PSW_BITS;
244                         task_regs(child)->gr[0] &= ~USER_PSW_BITS;
245                         task_regs(child)->gr[0] |= data;
246                         ret = 0;
247                         goto out_tsk;
248                 }
249 #ifdef __LP64__
250                 if (is_compat_task(child)) {
251                         if (addr & (sizeof(int)-1))
252                                 goto out_tsk;
253                         if ((addr = translate_usr_offset(addr)) < 0)
254                                 goto out_tsk;
255                         DBG("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n",
256                                 pid, oaddr, odata, addr);
257                         if (addr >= PT_FR0 && addr <= PT_FR31 + 4) {
258                                 /* Special case, fp regs are 64 bits anyway */
259                                 *(unsigned int *) ((char *) task_regs(child) + addr) = data;
260                                 ret = 0;
261                         }
262                         else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) ||
263                                         addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 ||
264                                         addr == PT_SAR+4) {
265                                 /* Zero the top 32 bits */
266                                 *(unsigned int *) ((char *) task_regs(child) + addr - 4) = 0;
267                                 *(unsigned int *) ((char *) task_regs(child) + addr) = data;
268                                 ret = 0;
269                         }
270                         goto out_tsk;
271                 }
272                 else
273 #endif
274                 {
275                         if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
276                                 goto out_tsk;
277                         if ((addr >= PT_GR1 && addr <= PT_GR31) ||
278                                         addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
279                                         (addr >= PT_FR0 && addr <= PT_FR31 + 4) ||
280                                         addr == PT_SAR) {
281                                 *(unsigned long *) ((char *) task_regs(child) + addr) = data;
282                                 ret = 0;
283                         }
284                         goto out_tsk;
285                 }
286
287         case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
288         case PTRACE_CONT:
289                 ret = -EIO;
290                 DBG("sys_ptrace(%s)\n",
291                         request == PTRACE_SYSCALL ? "SYSCALL" : "CONT");
292                 if (!valid_signal(data))
293                         goto out_tsk;
294                 child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
295                 if (request == PTRACE_SYSCALL) {
296                         set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
297                 } else {
298                         clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
299                 }               
300                 child->exit_code = data;
301                 goto out_wake_notrap;
302
303         case PTRACE_KILL:
304                 /*
305                  * make the child exit.  Best I can do is send it a
306                  * sigkill.  perhaps it should be put in the status
307                  * that it wants to exit.
308                  */
309                 DBG("sys_ptrace(KILL)\n");
310                 if (child->exit_state == EXIT_ZOMBIE)   /* already dead */
311                         goto out_tsk;
312                 child->exit_code = SIGKILL;
313                 goto out_wake_notrap;
314
315         case PTRACE_SINGLEBLOCK:
316                 DBG("sys_ptrace(SINGLEBLOCK)\n");
317                 ret = -EIO;
318                 if (!valid_signal(data))
319                         goto out_tsk;
320                 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
321                 child->ptrace &= ~PT_SINGLESTEP;
322                 child->ptrace |= PT_BLOCKSTEP;
323                 child->exit_code = data;
324
325                 /* Enable taken branch trap. */
326                 pa_psw(child)->r = 0;
327                 pa_psw(child)->t = 1;
328                 pa_psw(child)->h = 0;
329                 pa_psw(child)->l = 0;
330                 goto out_wake;
331
332         case PTRACE_SINGLESTEP:
333                 DBG("sys_ptrace(SINGLESTEP)\n");
334                 ret = -EIO;
335                 if (!valid_signal(data))
336                         goto out_tsk;
337
338                 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
339                 child->ptrace &= ~PT_BLOCKSTEP;
340                 child->ptrace |= PT_SINGLESTEP;
341                 child->exit_code = data;
342
343                 if (pa_psw(child)->n) {
344                         struct siginfo si;
345
346                         /* Nullified, just crank over the queue. */
347                         task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1];
348                         task_regs(child)->iasq[0] = task_regs(child)->iasq[1];
349                         task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4;
350                         pa_psw(child)->n = 0;
351                         pa_psw(child)->x = 0;
352                         pa_psw(child)->y = 0;
353                         pa_psw(child)->z = 0;
354                         pa_psw(child)->b = 0;
355                         ptrace_disable(child);
356                         /* Don't wake up the child, but let the
357                            parent know something happened. */
358                         si.si_code = TRAP_TRACE;
359                         si.si_addr = (void __user *) (task_regs(child)->iaoq[0] & ~3);
360                         si.si_signo = SIGTRAP;
361                         si.si_errno = 0;
362                         force_sig_info(SIGTRAP, &si, child);
363                         //notify_parent(child, SIGCHLD);
364                         //ret = 0;
365                         goto out_wake;
366                 }
367
368                 /* Enable recovery counter traps.  The recovery counter
369                  * itself will be set to zero on a task switch.  If the
370                  * task is suspended on a syscall then the syscall return
371                  * path will overwrite the recovery counter with a suitable
372                  * value such that it traps once back in user space.  We
373                  * disable interrupts in the childs PSW here also, to avoid
374                  * interrupts while the recovery counter is decrementing.
375                  */
376                 pa_psw(child)->r = 1;
377                 pa_psw(child)->t = 0;
378                 pa_psw(child)->h = 0;
379                 pa_psw(child)->l = 0;
380                 /* give it a chance to run. */
381                 goto out_wake;
382
383         case PTRACE_DETACH:
384                 ret = ptrace_detach(child, data);
385                 goto out_tsk;
386
387         case PTRACE_GETEVENTMSG:
388                 ret = put_user(child->ptrace_message, (unsigned int __user *) data);
389                 goto out_tsk;
390
391         default:
392                 ret = ptrace_request(child, request, addr, data);
393                 goto out_tsk;
394         }
395
396 out_wake_notrap:
397         ptrace_disable(child);
398 out_wake:
399         wake_up_process(child);
400         ret = 0;
401 out_tsk:
402         put_task_struct(child);
403 out:
404         unlock_kernel();
405         DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
406                 request, pid, oaddr, odata, ret);
407         return ret;
408 }
409
410 void syscall_trace(void)
411 {
412         if (!test_thread_flag(TIF_SYSCALL_TRACE))
413                 return;
414         if (!(current->ptrace & PT_PTRACED))
415                 return;
416         ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
417                                  ? 0x80 : 0));
418         /*
419          * this isn't the same as continuing with a signal, but it will do
420          * for normal use.  strace only continues with a signal if the
421          * stopping signal is not SIGTRAP.  -brl
422          */
423         if (current->exit_code) {
424                 send_sig(current->exit_code, current, 1);
425                 current->exit_code = 0;
426         }
427 }