Import 2.3.16
[davej-history.git] / arch / arm / kernel / ptrace.c
blob6104b4dbe8b53919b4757ed136b0cb11fdc0ceec
1 /* ptrace.c */
2 /* By Ross Biro 1/23/92 */
3 /* edited by Linus Torvalds */
4 /* edited for ARM by Russell King */
6 #include <linux/kernel.h>
7 #include <linux/sched.h>
8 #include <linux/mm.h>
9 #include <linux/smp.h>
10 #include <linux/smp_lock.h>
11 #include <linux/errno.h>
12 #include <linux/ptrace.h>
13 #include <linux/user.h>
15 #include <asm/uaccess.h>
16 #include <asm/pgtable.h>
17 #include <asm/system.h>
20 * does not yet catch signals sent when the child dies.
21 * in exit.c or in signal.c.
25 * Breakpoint SWI instruction: SWI &9F0001
27 #define BREAKINST 0xef9f0001
30 * this routine will get a word off of the processes privileged stack.
31 * the offset is how far from the base addr as stored in the THREAD.
32 * this routine assumes that all the privileged stacks are in our
33 * data space.
35 static inline long get_stack_long(struct task_struct *task, int offset)
37 struct pt_regs *regs;
39 regs = (struct pt_regs *)((unsigned long)task + 8192 - sizeof(struct pt_regs));
41 return regs->uregs[offset];
45 * this routine will put a word on the processes privileged stack.
46 * the offset is how far from the base addr as stored in the THREAD.
47 * this routine assumes that all the privileged stacks are in our
48 * data space.
50 static inline long put_stack_long(struct task_struct *task, int offset,
51 unsigned long data)
53 struct pt_regs *regs;
55 regs = (struct pt_regs *)((unsigned long)task + 8192 - sizeof(struct pt_regs));
57 regs->uregs[offset] = data;
59 return 0;
62 static int
63 read_long(struct task_struct *child, unsigned long addr, unsigned long *res)
65 int copied;
67 copied = access_process_vm(child, addr, res, sizeof(*res), 0);
69 return copied != sizeof(*res) ? -EIO : 0;
72 static int
73 write_long(struct task_struct *child, unsigned long addr, unsigned long val)
75 int copied;
77 copied = access_process_vm(child, addr, &val, sizeof(val), 1);
79 return copied != sizeof(val) ? -EIO : 0;
83 * Get value of register `rn' (in the instruction)
85 static unsigned long ptrace_getrn (struct task_struct *child, unsigned long insn)
87 unsigned int reg = (insn >> 16) & 15;
88 unsigned long val;
90 if (reg == 15)
91 val = pc_pointer (get_stack_long (child, reg));
92 else
93 val = get_stack_long (child, reg);
95 printk ("r%02d=%08lX ", reg, val);
96 return val;
100 * Get value of operand 2 (in an ALU instruction)
102 static unsigned long ptrace_getaluop2 (struct task_struct *child, unsigned long insn)
104 unsigned long val;
105 int shift;
106 int type;
108 printk ("op2=");
109 if (insn & 1 << 25) {
110 val = insn & 255;
111 shift = (insn >> 8) & 15;
112 type = 3;
113 printk ("(imm)");
114 } else {
115 val = get_stack_long (child, insn & 15);
117 if (insn & (1 << 4))
118 shift = (int)get_stack_long (child, (insn >> 8) & 15);
119 else
120 shift = (insn >> 7) & 31;
122 type = (insn >> 5) & 3;
123 printk ("(r%02ld)", insn & 15);
125 printk ("sh%dx%d", type, shift);
126 switch (type) {
127 case 0: val <<= shift; break;
128 case 1: val >>= shift; break;
129 case 2:
130 val = (((signed long)val) >> shift);
131 break;
132 case 3:
133 val = (val >> shift) | (val << (32 - shift));
134 break;
136 printk ("=%08lX ", val);
137 return val;
141 * Get value of operand 2 (in a LDR instruction)
143 static unsigned long ptrace_getldrop2 (struct task_struct *child, unsigned long insn)
145 unsigned long val;
146 int shift;
147 int type;
149 val = get_stack_long (child, insn & 15);
150 shift = (insn >> 7) & 31;
151 type = (insn >> 5) & 3;
153 printk ("op2=r%02ldsh%dx%d", insn & 15, shift, type);
154 switch (type) {
155 case 0: val <<= shift; break;
156 case 1: val >>= shift; break;
157 case 2:
158 val = (((signed long)val) >> shift);
159 break;
160 case 3:
161 val = (val >> shift) | (val << (32 - shift));
162 break;
164 printk ("=%08lX ", val);
165 return val;
168 static unsigned long
169 get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn)
171 unsigned long alt = 0;
173 printk(KERN_DEBUG "ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc);
174 switch (insn & 0x0e100000) {
175 case 0x00000000:
176 case 0x00100000:
177 case 0x02000000:
178 case 0x02100000: /* data processing */
179 printk ("data ");
180 switch (insn & 0x01e0f000) {
181 case 0x0000f000:
182 alt = ptrace_getrn(child, insn) & ptrace_getaluop2(child, insn);
183 break;
184 case 0x0020f000:
185 alt = ptrace_getrn(child, insn) ^ ptrace_getaluop2(child, insn);
186 break;
187 case 0x0040f000:
188 alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn);
189 break;
190 case 0x0060f000:
191 alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn);
192 break;
193 case 0x0080f000:
194 alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn);
195 break;
196 case 0x00a0f000:
197 alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn) +
198 (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0);
199 break;
200 case 0x00c0f000:
201 alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn) +
202 (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0);
203 break;
204 case 0x00e0f000:
205 alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn) +
206 (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0);
207 break;
208 case 0x0180f000:
209 alt = ptrace_getrn(child, insn) | ptrace_getaluop2(child, insn);
210 break;
211 case 0x01a0f000:
212 alt = ptrace_getaluop2(child, insn);
213 break;
214 case 0x01c0f000:
215 alt = ptrace_getrn(child, insn) & ~ptrace_getaluop2(child, insn);
216 break;
217 case 0x01e0f000:
218 alt = ~ptrace_getaluop2(child, insn);
219 break;
221 break;
223 case 0x04100000: /* ldr */
224 if ((insn & 0xf000) == 0xf000) {
225 printk ("ldr ");
226 alt = ptrace_getrn(child, insn);
227 if (insn & 1 << 24) {
228 if (insn & 1 << 23)
229 alt += ptrace_getldrop2 (child, insn);
230 else
231 alt -= ptrace_getldrop2 (child, insn);
233 if (read_long (child, alt, &alt) < 0)
234 alt = 0; /* not valid */
235 else
236 alt = pc_pointer (alt);
238 break;
240 case 0x06100000: /* ldr imm */
241 if ((insn & 0xf000) == 0xf000) {
242 printk ("ldrimm ");
243 alt = ptrace_getrn(child, insn);
244 if (insn & 1 << 24) {
245 if (insn & 1 << 23)
246 alt += insn & 0xfff;
247 else
248 alt -= insn & 0xfff;
250 if (read_long (child, alt, &alt) < 0)
251 alt = 0; /* not valid */
252 else
253 alt = pc_pointer (alt);
255 break;
257 case 0x08100000: /* ldm */
258 if (insn & (1 << 15)) {
259 unsigned long base;
260 int nr_regs;
261 printk ("ldm ");
263 if (insn & (1 << 23)) {
264 nr_regs = insn & 65535;
266 nr_regs = (nr_regs & 0x5555) + ((nr_regs & 0xaaaa) >> 1);
267 nr_regs = (nr_regs & 0x3333) + ((nr_regs & 0xcccc) >> 2);
268 nr_regs = (nr_regs & 0x0707) + ((nr_regs & 0x7070) >> 4);
269 nr_regs = (nr_regs & 0x000f) + ((nr_regs & 0x0f00) >> 8);
270 nr_regs <<= 2;
272 if (!(insn & (1 << 24)))
273 nr_regs -= 4;
274 } else {
275 if (insn & (1 << 24))
276 nr_regs = -4;
277 else
278 nr_regs = 0;
281 base = ptrace_getrn (child, insn);
283 if (read_long (child, base + nr_regs, &alt) < 0)
284 alt = 0; /* not valid */
285 else
286 alt = pc_pointer (alt);
287 break;
289 break;
291 case 0x0a000000:
292 case 0x0a100000: { /* bl or b */
293 signed long displ;
294 printk ("b/bl ");
295 /* It's a branch/branch link: instead of trying to
296 * figure out whether the branch will be taken or not,
297 * we'll put a breakpoint at either location. This is
298 * simpler, more reliable, and probably not a whole lot
299 * slower than the alternative approach of emulating the
300 * branch.
302 displ = (insn & 0x00ffffff) << 8;
303 displ = (displ >> 6) + 8;
304 if (displ != 0 && displ != 4)
305 alt = pc + displ;
307 break;
309 printk ("=%08lX\n", alt);
311 return alt;
314 static int
315 add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long addr)
317 int nr = dbg->nsaved;
318 int res = -EINVAL;
320 if (nr < 2) {
321 res = read_long(child, addr, &dbg->bp[nr].insn);
322 if (res == 0)
323 res = write_long(child, addr, BREAKINST);
325 if (res == 0) {
326 dbg->bp[nr].address = addr;
327 dbg->nsaved += 1;
329 } else
330 printk(KERN_DEBUG "add_breakpoint: too many breakpoints\n");
332 return res;
335 int ptrace_set_bpt (struct task_struct *child)
337 struct debug_info *dbg = &child->thread.debug;
338 unsigned long insn, pc, alt;
339 int res;
341 pc = pc_pointer (get_stack_long (child, 15/*REG_PC*/));
343 res = read_long(child, pc, &insn);
344 if (res >= 0) {
345 res = 0;
347 dbg->nsaved = 0;
349 res = add_breakpoint(child, dbg, pc + 4);
351 if (res == 0) {
352 alt = get_branch_address(child, pc, insn);
353 if (alt)
354 res = add_breakpoint(child, dbg, alt);
358 return res;
361 /* Ensure no single-step breakpoint is pending. Returns non-zero
362 * value if child was being single-stepped.
364 int ptrace_cancel_bpt (struct task_struct *child)
366 struct debug_info *dbg = &child->thread.debug;
367 unsigned long tmp;
368 int i, nsaved = dbg->nsaved;
370 dbg->nsaved = 0;
372 if (nsaved > 2) {
373 printk ("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
374 nsaved = 2;
377 for (i = 0; i < nsaved; i++) {
378 read_long(child, dbg->bp[i].address, &tmp);
379 if (tmp != BREAKINST)
380 printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n");
381 write_long(child, dbg->bp[i].address, dbg->bp[i].insn);
384 return nsaved != 0;
387 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
389 struct task_struct *child;
390 int ret;
392 lock_kernel();
393 ret = -EPERM;
394 if (request == PTRACE_TRACEME) {
395 /* are we already being traced? */
396 if (current->flags & PF_PTRACED)
397 goto out;
398 /* set the ptrace bit in the process flags. */
399 current->flags |= PF_PTRACED;
400 ret = 0;
401 goto out;
403 if (pid == 1) /* you may not mess with init */
404 goto out;
405 ret = -ESRCH;
406 if (!(child = find_task_by_pid(pid)))
407 goto out;
408 ret = -EPERM;
409 if (request == PTRACE_ATTACH) {
410 if (child == current)
411 goto out;
412 if ((!child->dumpable ||
413 (current->uid != child->euid) ||
414 (current->uid != child->suid) ||
415 (current->uid != child->uid) ||
416 (current->gid != child->egid) ||
417 (current->gid != child->sgid) ||
418 (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
419 (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
420 goto out;
421 /* the same process cannot be attached many times */
422 if (child->flags & PF_PTRACED)
423 goto out;
424 child->flags |= PF_PTRACED;
425 if (child->p_pptr != current) {
426 REMOVE_LINKS(child);
427 child->p_pptr = current;
428 SET_LINKS(child);
430 send_sig(SIGSTOP, child, 1);
431 ret = 0;
432 goto out;
434 ret = -ESRCH;
435 if (!(child->flags & PF_PTRACED))
436 goto out;
437 if (child->state != TASK_STOPPED) {
438 if (request != PTRACE_KILL)
439 goto out;
441 if (child->p_pptr != current)
442 goto out;
444 switch (request) {
445 case PTRACE_PEEKTEXT: /* read word at location addr. */
446 case PTRACE_PEEKDATA: {
447 unsigned long tmp;
449 ret = read_long(child, addr, &tmp);
450 if (ret)
451 put_user(tmp, (unsigned long *) data);
452 goto out;
455 case PTRACE_PEEKUSR: { /* read the word at location addr in the USER area. */
456 unsigned long tmp;
458 ret = -EIO;
459 if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
460 goto out;
462 tmp = 0; /* Default return condition */
463 if (addr < sizeof (struct pt_regs))
464 tmp = get_stack_long(child, (int)addr >> 2);
465 ret = put_user(tmp, (unsigned long *)data);
466 goto out;
469 case PTRACE_POKETEXT: /* write the word at location addr. */
470 case PTRACE_POKEDATA:
471 ret = write_long(child, addr, data);
472 goto out;
474 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
475 ret = -EIO;
476 if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
477 goto out;
479 if (addr < sizeof (struct pt_regs))
480 ret = put_stack_long(child, (int)addr >> 2, data);
481 goto out;
483 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
484 case PTRACE_CONT: /* restart after signal. */
485 ret = -EIO;
486 if ((unsigned long) data > _NSIG)
487 goto out;
488 if (request == PTRACE_SYSCALL)
489 child->flags |= PF_TRACESYS;
490 else
491 child->flags &= ~PF_TRACESYS;
492 child->exit_code = data;
493 wake_up_process (child);
494 /* make sure single-step breakpoint is gone. */
495 ptrace_cancel_bpt (child);
496 ret = 0;
497 goto out;
499 /* make the child exit. Best I can do is send it a sigkill.
500 * perhaps it should be put in the status that it wants to
501 * exit.
503 case PTRACE_KILL:
504 if (child->state == TASK_ZOMBIE) /* already dead */
505 return 0;
506 wake_up_process (child);
507 child->exit_code = SIGKILL;
508 /* make sure single-step breakpoint is gone. */
509 ptrace_cancel_bpt (child);
510 ret = 0;
511 goto out;
513 case PTRACE_SINGLESTEP: /* execute single instruction. */
514 ret = -EIO;
515 if ((unsigned long) data > _NSIG)
516 goto out;
517 child->thread.debug.nsaved = -1;
518 child->flags &= ~PF_TRACESYS;
519 wake_up_process(child);
520 child->exit_code = data;
521 /* give it a chance to run. */
522 ret = 0;
523 goto out;
525 case PTRACE_DETACH: /* detach a process that was attached. */
526 ret = -EIO;
527 if ((unsigned long) data > _NSIG)
528 goto out;
529 child->flags &= ~(PF_PTRACED|PF_TRACESYS);
530 wake_up_process (child);
531 child->exit_code = data;
532 REMOVE_LINKS(child);
533 child->p_pptr = child->p_opptr;
534 SET_LINKS(child);
535 /* make sure single-step breakpoint is gone. */
536 ptrace_cancel_bpt (child);
537 ret = 0;
538 goto out;
540 default:
541 ret = -EIO;
542 goto out;
544 out:
545 unlock_kernel();
546 return ret;
549 asmlinkage void syscall_trace(void)
551 if ((current->flags & (PF_PTRACED|PF_TRACESYS))
552 != (PF_PTRACED|PF_TRACESYS))
553 return;
554 current->exit_code = SIGTRAP;
555 current->state = TASK_STOPPED;
556 notify_parent(current, SIGCHLD);
557 schedule();
559 * this isn't the same as continuing with a signal, but it will do
560 * for normal use. strace only continues with a signal if the
561 * stopping signal is not SIGTRAP. -brl
563 if (current->exit_code) {
564 send_sig(current->exit_code, current, 1);
565 current->exit_code = 0;