2 * linux/arch/ppc/kernel/ptrace.c
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
7 * Derived from "arch/m68k/kernel/ptrace.c"
8 * Copyright (C) 1994 by Hamish Macdonald
9 * Taken from linux/kernel/ptrace.c and modified for M680x0.
10 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
12 * Modified by Cort Dougan (cort@cs.nmt.edu)
14 * This file is subject to the terms and conditions of the GNU General
15 * Public License. See the file README.legal in the main directory of
16 * this archive for more details.
20 #include <linux/kernel.h>
21 #include <linux/sched.h>
23 #include <linux/smp.h>
24 #include <linux/smp_lock.h>
25 #include <linux/errno.h>
26 #include <linux/ptrace.h>
27 #include <linux/user.h>
29 #include <asm/segment.h>
31 #include <asm/pgtable.h>
32 #include <asm/system.h>
35 * Set of msr bits that gdb can change on behalf of a process.
37 #define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
40 * does not yet catch signals sent when the child dies.
41 * in exit.c or in signal.c.
45 * Get contents of register REGNO in task TASK.
47 static inline long get_reg(struct task_struct
*task
, int regno
)
49 if (regno
< sizeof(struct pt_regs
) / sizeof(unsigned long))
50 return ((unsigned long *)task
->tss
.regs
)[regno
];
55 * Write contents of register REGNO in task TASK.
57 static inline int put_reg(struct task_struct
*task
, int regno
,
62 data
= (data
& MSR_DEBUGCHANGE
)
63 | (task
->tss
.regs
->msr
& ~MSR_DEBUGCHANGE
);
64 ((unsigned long *)task
->tss
.regs
)[regno
] = data
;
71 set_single_step(struct task_struct
*task
)
73 struct pt_regs
*regs
= task
->tss
.regs
;
78 clear_single_step(struct task_struct
*task
)
80 struct pt_regs
*regs
= task
->tss
.regs
;
85 * This routine gets a long from any process space by following the page
86 * tables. NOTE! You should check that the long isn't on a page boundary,
87 * and that it is in the task area before calling this: this routine does
91 static unsigned long get_long(struct task_struct
* tsk
,
92 struct vm_area_struct
* vma
, unsigned long addr
)
100 pgdir
= pgd_offset(vma
->vm_mm
, addr
);
101 if (pgd_none(*pgdir
)) {
102 handle_mm_fault(tsk
, vma
, addr
, 0);
105 if (pgd_bad(*pgdir
)) {
106 printk("ptrace[1]: bad page directory %lx\n", pgd_val(*pgdir
));
110 pgmiddle
= pmd_offset(pgdir
,addr
);
111 if (pmd_none(*pgmiddle
)) {
112 handle_mm_fault(tsk
, vma
, addr
, 0);
115 if (pmd_bad(*pgmiddle
)) {
116 printk("ptrace[3]: bad pmd %lx\n", pmd_val(*pgmiddle
));
120 pgtable
= pte_offset(pgmiddle
, addr
);
121 if (!pte_present(*pgtable
)) {
122 handle_mm_fault(tsk
, vma
, addr
, 0);
125 page
= pte_page(*pgtable
);
126 /* this is a hack for non-kernel-mapped video buffers and similar */
127 if (MAP_NR(page
) >= max_mapnr
)
129 page
+= addr
& ~PAGE_MASK
;
130 return *(unsigned long *) page
;
134 * This routine puts a long into any process space by following the page
135 * tables. NOTE! You should check that the long isn't on a page boundary,
136 * and that it is in the task area before calling this: this routine does
139 * Now keeps R/W state of page so that a text page stays readonly
140 * even if a debugger scribbles breakpoints into it. -M.U-
142 static void put_long(struct task_struct
* tsk
, struct vm_area_struct
* vma
,
143 unsigned long addr
, unsigned long data
)
151 pgdir
= pgd_offset(vma
->vm_mm
, addr
);
152 if (!pgd_present(*pgdir
)) {
153 handle_mm_fault(tsk
, vma
, addr
, 1);
156 if (pgd_bad(*pgdir
)) {
157 printk("ptrace[2]: bad page directory %lx\n", pgd_val(*pgdir
));
161 pgmiddle
= pmd_offset(pgdir
,addr
);
162 if (pmd_none(*pgmiddle
)) {
163 handle_mm_fault(tsk
, vma
, addr
, 1);
166 if (pmd_bad(*pgmiddle
)) {
167 printk("ptrace[4]: bad pmd %lx\n", pmd_val(*pgmiddle
));
171 pgtable
= pte_offset(pgmiddle
, addr
);
172 if (!pte_present(*pgtable
)) {
173 handle_mm_fault(tsk
, vma
, addr
, 1);
176 page
= pte_page(*pgtable
);
177 if (!pte_write(*pgtable
)) {
178 handle_mm_fault(tsk
, vma
, addr
, 1);
181 /* this is a hack for non-kernel-mapped video buffers and similar */
182 if (MAP_NR(page
) < max_mapnr
) {
183 unsigned long phys_addr
= page
+ (addr
& ~PAGE_MASK
);
184 *(unsigned long *) phys_addr
= data
;
185 flush_icache_range(phys_addr
, phys_addr
+4);
187 /* we're bypassing pagetables, so we have to set the dirty bit ourselves */
188 /* this should also re-instate whatever read-only mode there was before */
189 set_pte(pgtable
, pte_mkdirty(mk_pte(page
, vma
->vm_page_prot
)));
193 static struct vm_area_struct
* find_extend_vma(struct task_struct
* tsk
, unsigned long addr
)
195 struct vm_area_struct
* vma
;
198 vma
= find_vma(tsk
->mm
,addr
);
201 if (vma
->vm_start
<= addr
)
203 if (!(vma
->vm_flags
& VM_GROWSDOWN
))
205 if (vma
->vm_end
- addr
> tsk
->rlim
[RLIMIT_STACK
].rlim_cur
)
207 vma
->vm_offset
-= vma
->vm_start
- addr
;
208 vma
->vm_start
= addr
;
213 * This routine checks the page boundaries, and that the offset is
214 * within the task area. It then calls get_long() to read a long.
216 static int read_long(struct task_struct
* tsk
, unsigned long addr
,
217 unsigned long * result
)
219 struct vm_area_struct
* vma
= find_extend_vma(tsk
, addr
);
223 if ((addr
& ~PAGE_MASK
) > PAGE_SIZE
-sizeof(long)) {
224 unsigned long low
,high
;
225 struct vm_area_struct
* vma_low
= vma
;
227 if (addr
+ sizeof(long) >= vma
->vm_end
) {
228 vma_low
= vma
->vm_next
;
229 if (!vma_low
|| vma_low
->vm_start
!= vma
->vm_end
)
232 high
= get_long(tsk
, vma
,addr
& ~(sizeof(long)-1));
233 low
= get_long(tsk
, vma_low
,(addr
+sizeof(long)) & ~(sizeof(long)-1));
234 switch (addr
& (sizeof(long)-1)) {
250 *result
= get_long(tsk
, vma
,addr
);
255 * This routine checks the page boundaries, and that the offset is
256 * within the task area. It then calls put_long() to write a long.
258 static int write_long(struct task_struct
* tsk
, unsigned long addr
,
261 struct vm_area_struct
* vma
= find_extend_vma(tsk
, addr
);
265 if ((addr
& ~PAGE_MASK
) > PAGE_SIZE
-sizeof(long)) {
266 unsigned long low
,high
;
267 struct vm_area_struct
* vma_low
= vma
;
269 if (addr
+ sizeof(long) >= vma
->vm_end
) {
270 vma_low
= vma
->vm_next
;
271 if (!vma_low
|| vma_low
->vm_start
!= vma
->vm_end
)
274 high
= get_long(tsk
, vma
,addr
& ~(sizeof(long)-1));
275 low
= get_long(tsk
, vma_low
,(addr
+sizeof(long)) & ~(sizeof(long)-1));
276 switch (addr
& (sizeof(long)-1)) {
277 case 0: /* shouldn't happen, but safety first */
299 put_long(tsk
, vma
,addr
& ~(sizeof(long)-1),high
);
300 put_long(tsk
, vma_low
,(addr
+sizeof(long)) & ~(sizeof(long)-1),low
);
302 put_long(tsk
, vma
,addr
,data
);
306 asmlinkage
int sys_ptrace(long request
, long pid
, long addr
, long data
)
308 struct task_struct
*child
;
312 if (request
== PTRACE_TRACEME
) {
313 /* are we already being traced? */
314 if (current
->flags
& PF_PTRACED
)
316 /* set the ptrace bit in the process flags. */
317 current
->flags
|= PF_PTRACED
;
321 if (pid
== 1) /* you may not mess with init */
324 if (!(child
= find_task_by_pid(pid
)))
327 if (request
== PTRACE_ATTACH
) {
328 if (child
== current
)
330 if ((!child
->dumpable
||
331 (current
->uid
!= child
->euid
) ||
332 (current
->uid
!= child
->uid
) ||
333 (current
->uid
!= child
->suid
) ||
334 (current
->gid
!= child
->egid
) ||
335 (current
->gid
!= child
->gid
) ||
336 (current
->gid
!= child
->sgid
) ||
337 (!cap_issubset(child
->cap_permitted
, current
->cap_permitted
)))
338 && !capable(CAP_SYS_PTRACE
))
340 /* the same process cannot be attached many times */
341 if (child
->flags
& PF_PTRACED
)
343 child
->flags
|= PF_PTRACED
;
344 if (child
->p_pptr
!= current
) {
346 child
->p_pptr
= current
;
349 send_sig(SIGSTOP
, child
, 1);
354 if (!(child
->flags
& PF_PTRACED
))
356 if (child
->state
!= TASK_STOPPED
) {
357 if (request
!= PTRACE_KILL
)
360 if (child
->p_pptr
!= current
)
364 /* If I and D space are separate, these will need to be fixed. */
365 case PTRACE_PEEKTEXT
: /* read word at location addr. */
366 case PTRACE_PEEKDATA
: {
369 down(&child
->mm
->mmap_sem
);
370 ret
= read_long(child
, addr
, &tmp
);
371 up(&child
->mm
->mmap_sem
);
374 ret
= verify_area(VERIFY_WRITE
, (void *) data
, sizeof(long));
376 put_user(tmp
, (unsigned long *) data
);
380 /* read the word at location addr in the USER area. */
381 case PTRACE_PEEKUSR
: {
384 if ((addr
& 3) || addr
< 0 || addr
> (PT_FPSCR
<< 2)) {
389 ret
= verify_area(VERIFY_WRITE
, (void *) data
,
393 tmp
= 0; /* Default return condition */
394 addr
= addr
>> 2; /* temporary hack. */
395 if (addr
< PT_FPR0
) {
396 tmp
= get_reg(child
, addr
);
398 else if (addr
>= PT_FPR0
&& addr
<= PT_FPSCR
) {
399 if (child
->tss
.regs
->msr
& MSR_FP
)
401 tmp
= ((long *)child
->tss
.fpr
)[addr
- PT_FPR0
];
406 put_user(tmp
,(unsigned long *) data
);
410 /* If I and D space are separate, this will have to be fixed. */
411 case PTRACE_POKETEXT
: /* write the word at location addr. */
412 case PTRACE_POKEDATA
:
413 down(&child
->mm
->mmap_sem
);
414 ret
= write_long(child
,addr
,data
);
415 up(&child
->mm
->mmap_sem
);
418 case PTRACE_POKEUSR
: /* write the word at location addr in the USER area */
420 if ((addr
& 3) || addr
< 0 || addr
>= ((PT_FPR0
+ 64) << 2))
423 addr
= addr
>> 2; /* temporary hack. */
425 if (addr
== PT_ORIG_R3
)
427 if (addr
< PT_FPR0
) {
428 if (put_reg(child
, addr
, data
))
433 if (addr
>= PT_FPR0
&& addr
< PT_FPR0
+ 64) {
434 if (child
->tss
.regs
->msr
& MSR_FP
)
436 ((long *)child
->tss
.fpr
)[addr
- PT_FPR0
] = data
;
442 case PTRACE_SYSCALL
: /* continue and stop at next (return from) syscall */
443 case PTRACE_CONT
: { /* restart after signal. */
445 if ((unsigned long) data
>= _NSIG
)
447 if (request
== PTRACE_SYSCALL
)
448 child
->flags
|= PF_TRACESYS
;
450 child
->flags
&= ~PF_TRACESYS
;
451 child
->exit_code
= data
;
452 wake_up_process(child
);
453 /* make sure the single step bit is not set. */
454 clear_single_step(child
);
460 * make the child exit. Best I can do is send it a sigkill.
461 * perhaps it should be put in the status that it wants to
466 if (child
->state
== TASK_ZOMBIE
) /* already dead */
468 wake_up_process(child
);
469 child
->exit_code
= SIGKILL
;
470 /* make sure the single step bit is not set. */
471 clear_single_step(child
);
475 case PTRACE_SINGLESTEP
: { /* set the trap flag. */
477 if ((unsigned long) data
>= _NSIG
)
479 child
->flags
&= ~PF_TRACESYS
;
480 set_single_step(child
);
481 wake_up_process(child
);
482 child
->exit_code
= data
;
483 /* give it a chance to run. */
488 case PTRACE_DETACH
: { /* detach a process that was attached. */
490 if ((unsigned long) data
>= _NSIG
)
492 child
->flags
&= ~(PF_PTRACED
|PF_TRACESYS
);
493 wake_up_process(child
);
494 child
->exit_code
= data
;
496 child
->p_pptr
= child
->p_opptr
;
498 /* make sure the single step bit is not set. */
499 clear_single_step(child
);
513 asmlinkage
void syscall_trace(void)
516 if ((current
->flags
& (PF_PTRACED
|PF_TRACESYS
))
517 != (PF_PTRACED
|PF_TRACESYS
))
519 current
->exit_code
= SIGTRAP
;
520 current
->state
= TASK_STOPPED
;
521 notify_parent(current
, SIGCHLD
);
524 * this isn't the same as continuing with a signal, but it will do
525 * for normal use. strace only continues with a signal if the
526 * stopping signal is not SIGTRAP. -brl
528 if (current
->exit_code
) {
529 send_sig(current
->exit_code
, current
, 1);
530 current
->exit_code
= 0;