Ok. I didn't make 2.4.0 in 2000. Tough. I tried, but we had some
[davej-history.git] / arch / arm / kernel / ptrace.c
blob2d20c927111380b55c893499994bcd92f7735368
1 /*
2 * linux/arch/arm/kernel/ptrace.c
4 * By Ross Biro 1/23/92
5 * edited by Linus Torvalds
6 * ARM modifications Copyright (C) 2000 Russell King
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/mm.h>
15 #include <linux/smp.h>
16 #include <linux/smp_lock.h>
17 #include <linux/ptrace.h>
18 #include <linux/user.h>
20 #include <asm/uaccess.h>
21 #include <asm/pgtable.h>
22 #include <asm/system.h>
24 #include "ptrace.h"
26 #define REG_PC 15
27 #define REG_PSR 16
29 * does not yet catch signals sent when the child dies.
30 * in exit.c or in signal.c.
34 * Breakpoint SWI instruction: SWI &9F0001
36 #define BREAKINST 0xef9f0001
39 * Get the address of the live pt_regs for the specified task.
40 * These are saved onto the top kernel stack when the process
41 * is not running.
43 static inline struct pt_regs *
44 get_user_regs(struct task_struct *task)
46 return (struct pt_regs *)
47 ((unsigned long)task + 8192 - sizeof(struct pt_regs));
51 * this routine will get a word off of the processes privileged stack.
52 * the offset is how far from the base addr as stored in the THREAD.
53 * this routine assumes that all the privileged stacks are in our
54 * data space.
56 static inline long get_stack_long(struct task_struct *task, int offset)
58 return get_user_regs(task)->uregs[offset];
62 * this routine will put a word on the processes privileged stack.
63 * the offset is how far from the base addr as stored in the THREAD.
64 * this routine assumes that all the privileged stacks are in our
65 * data space.
67 static inline int
68 put_stack_long(struct task_struct *task, int offset, long data)
70 struct pt_regs newregs, *regs = get_user_regs(task);
71 int ret = -EINVAL;
73 newregs = *regs;
74 newregs.uregs[offset] = data;
76 if (valid_user_regs(&newregs)) {
77 regs->uregs[offset] = data;
78 ret = 0;
81 return ret;
84 static inline int
85 read_tsk_long(struct task_struct *child, unsigned long addr, unsigned long *res)
87 int copied;
89 copied = access_process_vm(child, addr, res, sizeof(*res), 0);
91 return copied != sizeof(*res) ? -EIO : 0;
94 static inline int
95 write_tsk_long(struct task_struct *child, unsigned long addr, unsigned long val)
97 int copied;
99 copied = access_process_vm(child, addr, &val, sizeof(val), 1);
101 return copied != sizeof(val) ? -EIO : 0;
105 * Get value of register `rn' (in the instruction)
107 static unsigned long
108 ptrace_getrn(struct task_struct *child, unsigned long insn)
110 unsigned int reg = (insn >> 16) & 15;
111 unsigned long val;
113 val = get_stack_long(child, reg);
114 if (reg == 15)
115 val = pc_pointer(val);
117 return val;
121 * Get value of operand 2 (in an ALU instruction)
123 static unsigned long
124 ptrace_getaluop2(struct task_struct *child, unsigned long insn)
126 unsigned long val;
127 int shift;
128 int type;
130 if (insn & 1 << 25) {
131 val = insn & 255;
132 shift = (insn >> 8) & 15;
133 type = 3;
134 } else {
135 val = get_stack_long (child, insn & 15);
137 if (insn & (1 << 4))
138 shift = (int)get_stack_long (child, (insn >> 8) & 15);
139 else
140 shift = (insn >> 7) & 31;
142 type = (insn >> 5) & 3;
145 switch (type) {
146 case 0: val <<= shift; break;
147 case 1: val >>= shift; break;
148 case 2:
149 val = (((signed long)val) >> shift);
150 break;
151 case 3:
152 val = (val >> shift) | (val << (32 - shift));
153 break;
155 return val;
159 * Get value of operand 2 (in a LDR instruction)
161 static unsigned long
162 ptrace_getldrop2(struct task_struct *child, unsigned long insn)
164 unsigned long val;
165 int shift;
166 int type;
168 val = get_stack_long(child, insn & 15);
169 shift = (insn >> 7) & 31;
170 type = (insn >> 5) & 3;
172 switch (type) {
173 case 0: val <<= shift; break;
174 case 1: val >>= shift; break;
175 case 2:
176 val = (((signed long)val) >> shift);
177 break;
178 case 3:
179 val = (val >> shift) | (val << (32 - shift));
180 break;
182 return val;
185 static unsigned long
186 get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn)
188 unsigned long alt = 0;
190 switch (insn & 0x0e000000) {
191 case 0x00000000:
192 case 0x02000000: {
194 * data processing
196 long aluop1, aluop2, ccbit;
198 if ((insn & 0xf000) != 0xf000)
199 break;
201 aluop1 = ptrace_getrn(child, insn);
202 aluop2 = ptrace_getaluop2(child, insn);
203 ccbit = get_stack_long(child, REG_PSR) & CC_C_BIT ? 1 : 0;
205 switch (insn & 0x01e00000) {
206 case 0x00000000: alt = aluop1 & aluop2; break;
207 case 0x00200000: alt = aluop1 ^ aluop2; break;
208 case 0x00400000: alt = aluop1 - aluop2; break;
209 case 0x00600000: alt = aluop2 - aluop1; break;
210 case 0x00800000: alt = aluop1 + aluop2; break;
211 case 0x00a00000: alt = aluop1 + aluop2 + ccbit; break;
212 case 0x00c00000: alt = aluop1 - aluop2 + ccbit; break;
213 case 0x00e00000: alt = aluop2 - aluop1 + ccbit; break;
214 case 0x01800000: alt = aluop1 | aluop2; break;
215 case 0x01a00000: alt = aluop2; break;
216 case 0x01c00000: alt = aluop1 & ~aluop2; break;
217 case 0x01e00000: alt = ~aluop2; break;
219 break;
222 case 0x04000000:
223 case 0x06000000:
225 * ldr
227 if ((insn & 0x0010f000) == 0x0010f000) {
228 unsigned long base;
230 base = ptrace_getrn(child, insn);
231 if (insn & 1 << 24) {
232 long aluop2;
234 if (insn & 0x02000000)
235 aluop2 = ptrace_getldrop2(child, insn);
236 else
237 aluop2 = insn & 0xfff;
239 if (insn & 1 << 23)
240 base += aluop2;
241 else
242 base -= aluop2;
244 if (read_tsk_long(child, base, &alt) == 0)
245 alt = pc_pointer(alt);
247 break;
249 case 0x08000000:
251 * ldm
253 if ((insn & 0x00108000) == 0x00108000) {
254 unsigned long base;
255 unsigned int nr_regs;
257 if (insn & (1 << 23)) {
258 nr_regs = insn & 65535;
260 nr_regs = (nr_regs & 0x5555) + ((nr_regs & 0xaaaa) >> 1);
261 nr_regs = (nr_regs & 0x3333) + ((nr_regs & 0xcccc) >> 2);
262 nr_regs = (nr_regs & 0x0707) + ((nr_regs & 0x7070) >> 4);
263 nr_regs = (nr_regs & 0x000f) + ((nr_regs & 0x0f00) >> 8);
264 nr_regs <<= 2;
266 if (!(insn & (1 << 24)))
267 nr_regs -= 4;
268 } else {
269 if (insn & (1 << 24))
270 nr_regs = -4;
271 else
272 nr_regs = 0;
275 base = ptrace_getrn(child, insn);
277 if (read_tsk_long(child, base + nr_regs, &alt) == 0)
278 alt = pc_pointer (alt);
279 break;
281 break;
283 case 0x0a000000: {
285 * bl or b
287 signed long displ;
288 /* It's a branch/branch link: instead of trying to
289 * figure out whether the branch will be taken or not,
290 * we'll put a breakpoint at both locations. This is
291 * simpler, more reliable, and probably not a whole lot
292 * slower than the alternative approach of emulating the
293 * branch.
295 displ = (insn & 0x00ffffff) << 8;
296 displ = (displ >> 6) + 8;
297 if (displ != 0 && displ != 4)
298 alt = pc + displ;
300 break;
303 return alt;
306 static int
307 add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long addr)
309 int nr = dbg->nsaved;
310 int res = -EINVAL;
312 if (nr < 2) {
313 res = read_tsk_long(child, addr, &dbg->bp[nr].insn);
314 if (res == 0)
315 res = write_tsk_long(child, addr, BREAKINST);
317 if (res == 0) {
318 dbg->bp[nr].address = addr;
319 dbg->nsaved += 1;
321 } else
322 printk(KERN_DEBUG "add_breakpoint: too many breakpoints\n");
324 return res;
327 int ptrace_set_bpt(struct task_struct *child)
329 unsigned long insn, pc;
330 int res;
332 pc = pc_pointer(get_stack_long(child, REG_PC));
334 res = read_tsk_long(child, pc, &insn);
335 if (!res) {
336 struct debug_info *dbg = &child->thread.debug;
337 unsigned long alt;
339 dbg->nsaved = 0;
341 alt = get_branch_address(child, pc, insn);
342 if (alt)
343 res = add_breakpoint(child, dbg, alt);
345 if (!res && (!alt || predicate(insn) != PREDICATE_ALWAYS))
346 res = add_breakpoint(child, dbg, pc + 4);
349 return res;
353 * Ensure no single-step breakpoint is pending. Returns non-zero
354 * value if child was being single-stepped.
356 void __ptrace_cancel_bpt(struct task_struct *child)
358 struct debug_info *dbg = &child->thread.debug;
359 int i, nsaved = dbg->nsaved;
361 dbg->nsaved = 0;
363 if (nsaved > 2) {
364 printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
365 nsaved = 2;
368 for (i = 0; i < nsaved; i++) {
369 unsigned long tmp;
371 read_tsk_long(child, dbg->bp[i].address, &tmp);
372 if (tmp != BREAKINST)
373 printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n");
374 write_tsk_long(child, dbg->bp[i].address, dbg->bp[i].insn);
378 static int do_ptrace(int request, struct task_struct *child, long addr, long data)
380 unsigned long tmp;
381 int ret;
383 switch (request) {
385 * read word at location "addr" in the child process.
387 case PTRACE_PEEKTEXT:
388 case PTRACE_PEEKDATA:
389 ret = read_tsk_long(child, addr, &tmp);
390 if (!ret)
391 ret = put_user(tmp, (unsigned long *) data);
392 break;
395 * read the word at location "addr" in the user registers.
397 case PTRACE_PEEKUSR:
398 ret = -EIO;
399 if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
400 break;
402 tmp = 0; /* Default return condition */
403 if (addr < sizeof(struct pt_regs))
404 tmp = get_stack_long(child, (int)addr >> 2);
405 ret = put_user(tmp, (unsigned long *)data);
406 break;
409 * write the word at location addr.
411 case PTRACE_POKETEXT:
412 case PTRACE_POKEDATA:
413 ret = write_tsk_long(child, addr, data);
414 break;
417 * write the word at location addr in the user registers.
419 case PTRACE_POKEUSR:
420 ret = -EIO;
421 if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
422 break;
424 if (addr < sizeof(struct pt_regs))
425 ret = put_stack_long(child, (int)addr >> 2, data);
426 break;
429 * continue/restart and stop at next (return from) syscall
431 case PTRACE_SYSCALL:
432 case PTRACE_CONT:
433 ret = -EIO;
434 if ((unsigned long) data > _NSIG)
435 break;
436 if (request == PTRACE_SYSCALL)
437 child->ptrace |= PT_TRACESYS;
438 else
439 child->ptrace &= ~PT_TRACESYS;
440 child->exit_code = data;
441 /* make sure single-step breakpoint is gone. */
442 __ptrace_cancel_bpt(child);
443 wake_up_process(child);
444 ret = 0;
445 break;
448 * make the child exit. Best I can do is send it a sigkill.
449 * perhaps it should be put in the status that it wants to
450 * exit.
452 case PTRACE_KILL:
453 /* already dead */
454 ret = 0;
455 if (child->state == TASK_ZOMBIE)
456 break;
457 child->exit_code = SIGKILL;
458 /* make sure single-step breakpoint is gone. */
459 __ptrace_cancel_bpt(child);
460 wake_up_process(child);
461 ret = 0;
462 break;
465 * execute single instruction.
467 case PTRACE_SINGLESTEP:
468 ret = -EIO;
469 if ((unsigned long) data > _NSIG)
470 break;
471 child->thread.debug.nsaved = -1;
472 child->ptrace &= ~PT_TRACESYS;
473 child->exit_code = data;
474 /* give it a chance to run. */
475 wake_up_process(child);
476 ret = 0;
477 break;
480 * detach a process that was attached.
482 case PTRACE_DETACH:
483 ret = -EIO;
484 if ((unsigned long) data > _NSIG)
485 break;
486 child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
487 child->exit_code = data;
488 write_lock_irq(&tasklist_lock);
489 REMOVE_LINKS(child);
490 child->p_pptr = child->p_opptr;
491 SET_LINKS(child);
492 write_unlock_irq(&tasklist_lock);
493 /* make sure single-step breakpoint is gone. */
494 __ptrace_cancel_bpt(child);
495 wake_up_process (child);
496 ret = 0;
497 break;
500 * Get all gp regs from the child.
502 case PTRACE_GETREGS: {
503 struct pt_regs *regs = get_user_regs(child);
505 ret = 0;
506 if (copy_to_user((void *)data, regs,
507 sizeof(struct pt_regs)))
508 ret = -EFAULT;
510 break;
514 * Set all gp regs in the child.
516 case PTRACE_SETREGS: {
517 struct pt_regs newregs;
519 ret = -EFAULT;
520 if (copy_from_user(&newregs, (void *)data,
521 sizeof(struct pt_regs)) == 0) {
522 struct pt_regs *regs = get_user_regs(child);
524 ret = -EINVAL;
525 if (valid_user_regs(&newregs)) {
526 *regs = newregs;
527 ret = 0;
530 break;
534 * Get the child FPU state.
536 case PTRACE_GETFPREGS:
537 ret = -EIO;
538 if (!access_ok(VERIFY_WRITE, (void *)data, sizeof(struct user_fp)))
539 break;
541 /* we should check child->used_math here */
542 ret = __copy_to_user((void *)data, &child->thread.fpstate,
543 sizeof(struct user_fp)) ? -EFAULT : 0;
544 break;
547 * Set the child FPU state.
549 case PTRACE_SETFPREGS:
550 ret = -EIO;
551 if (!access_ok(VERIFY_READ, (void *)data, sizeof(struct user_fp)))
552 break;
554 child->used_math = 1;
555 ret = __copy_from_user(&child->thread.fpstate, (void *)data,
556 sizeof(struct user_fp)) ? -EFAULT : 0;
557 break;
559 default:
560 ret = -EIO;
561 break;
564 return ret;
567 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
569 struct task_struct *child;
570 int ret;
572 lock_kernel();
573 ret = -EPERM;
574 if (request == PTRACE_TRACEME) {
575 /* are we already being traced? */
576 if (current->ptrace & PT_PTRACED)
577 goto out;
578 /* set the ptrace bit in the process flags. */
579 current->ptrace |= PT_PTRACED;
580 ret = 0;
581 goto out;
583 ret = -ESRCH;
584 read_lock(&tasklist_lock);
585 child = find_task_by_pid(pid);
586 if (child)
587 get_task_struct(child);
588 read_unlock(&tasklist_lock);
589 if (!child)
590 goto out;
592 ret = -EPERM;
593 if (pid == 1) /* you may not mess with init */
594 goto out_tsk;
596 if (request == PTRACE_ATTACH) {
597 if (child == current)
598 goto out_tsk;
599 if ((!child->dumpable ||
600 (current->uid != child->euid) ||
601 (current->uid != child->suid) ||
602 (current->uid != child->uid) ||
603 (current->gid != child->egid) ||
604 (current->gid != child->sgid) ||
605 (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
606 (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
607 goto out_tsk;
608 /* the same process cannot be attached many times */
609 if (child->ptrace & PT_PTRACED)
610 goto out_tsk;
611 child->ptrace |= PT_PTRACED;
613 write_lock_irq(&tasklist_lock);
614 if (child->p_pptr != current) {
615 REMOVE_LINKS(child);
616 child->p_pptr = current;
617 SET_LINKS(child);
619 write_unlock_irq(&tasklist_lock);
621 send_sig(SIGSTOP, child, 1);
622 ret = 0;
623 goto out_tsk;
625 ret = -ESRCH;
626 if (!(child->ptrace & PT_PTRACED))
627 goto out_tsk;
628 if (child->state != TASK_STOPPED && request != PTRACE_KILL)
629 goto out_tsk;
630 if (child->p_pptr != current)
631 goto out_tsk;
633 ret = do_ptrace(request, child, addr, data);
635 out_tsk:
636 free_task_struct(child);
637 out:
638 unlock_kernel();
639 return ret;
642 asmlinkage void syscall_trace(void)
644 if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
645 != (PT_PTRACED|PT_TRACESYS))
646 return;
647 current->exit_code = SIGTRAP;
648 current->state = TASK_STOPPED;
649 notify_parent(current, SIGCHLD);
650 schedule();
652 * this isn't the same as continuing with a signal, but it will do
653 * for normal use. strace only continues with a signal if the
654 * stopping signal is not SIGTRAP. -brl
656 if (current->exit_code) {
657 send_sig(current->exit_code, current, 1);
658 current->exit_code = 0;