2 * linux/kernel/ptrace.c
4 * (C) Copyright 1999 Linus Torvalds
6 * Common interfaces for "ptrace()" which we do not want
7 * to continually duplicate across every architecture.
10 #include <linux/sched.h>
11 #include <linux/errno.h>
13 #include <linux/highmem.h>
14 #include <linux/smp_lock.h>
16 #include <asm/pgtable.h>
17 #include <asm/uaccess.h>
20 * Access another process' address space, one page at a time.
22 static int access_one_page(struct mm_struct
* mm
, struct vm_area_struct
* vma
, unsigned long addr
, void *buf
, int len
, int write
)
31 pgdir
= pgd_offset(vma
->vm_mm
, addr
);
36 pgmiddle
= pmd_offset(pgdir
, addr
);
37 if (pmd_none(*pgmiddle
))
39 if (pmd_bad(*pgmiddle
))
41 pgtable
= pte_offset(pgmiddle
, addr
);
42 if (!pte_present(*pgtable
))
44 if (write
&& (!pte_write(*pgtable
) || !pte_dirty(*pgtable
)))
46 page
= pte_page(*pgtable
);
48 /* ZERO_PAGE is special: reads from it are ok even though it's marked reserved */
49 if (page
!= ZERO_PAGE(addr
) || write
) {
50 if ((!VALID_PAGE(page
)) || PageReserved(page
))
53 flush_cache_page(vma
, addr
);
57 memcpy(maddr
+ (addr
& ~PAGE_MASK
), buf
, len
);
58 flush_page_to_ram(page
);
59 flush_icache_page(vma
, page
);
63 memcpy(buf
, maddr
+ (addr
& ~PAGE_MASK
), len
);
64 flush_page_to_ram(page
);
70 /* -1: out of memory. 0 - unmapped page */
71 if (handle_mm_fault(mm
, vma
, addr
, write
) > 0)
84 static int access_mm(struct mm_struct
*mm
, struct vm_area_struct
* vma
, unsigned long addr
, void *buf
, int len
, int write
)
89 unsigned long offset
= addr
& ~PAGE_MASK
;
90 int this_len
= PAGE_SIZE
- offset
;
95 retval
= access_one_page(mm
, vma
, addr
, buf
, this_len
, write
);
97 if (retval
!= this_len
)
107 if (addr
< vma
->vm_end
)
111 if (vma
->vm_next
->vm_start
!= vma
->vm_end
)
119 int access_process_vm(struct task_struct
*tsk
, unsigned long addr
, void *buf
, int len
, int write
)
122 struct mm_struct
*mm
;
123 struct vm_area_struct
* vma
;
125 /* Worry about races with exit() */
129 atomic_inc(&mm
->mm_users
);
135 vma
= find_extend_vma(mm
, addr
);
138 copied
= access_mm(mm
, vma
, addr
, buf
, len
, write
);
145 int ptrace_readdata(struct task_struct
*tsk
, unsigned long src
, char *dst
, int len
)
151 int this_len
, retval
;
153 this_len
= (len
> sizeof(buf
)) ? sizeof(buf
) : len
;
154 retval
= access_process_vm(tsk
, src
, buf
, this_len
, 0);
160 if (copy_to_user(dst
, buf
, retval
))
170 int ptrace_writedata(struct task_struct
*tsk
, char * src
, unsigned long dst
, int len
)
176 int this_len
, retval
;
178 this_len
= (len
> sizeof(buf
)) ? sizeof(buf
) : len
;
179 if (copy_from_user(buf
, src
, this_len
))
181 retval
= access_process_vm(tsk
, dst
, buf
, this_len
, 1);