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
)
32 pgdir
= pgd_offset(vma
->vm_mm
, addr
);
37 pgmiddle
= pmd_offset(pgdir
, addr
);
38 if (pmd_none(*pgmiddle
))
40 if (pmd_bad(*pgmiddle
))
42 pgtable
= pte_offset(pgmiddle
, addr
);
43 if (!pte_present(*pgtable
))
45 mapnr
= pte_pagenr(*pgtable
);
46 if (write
&& (!pte_write(*pgtable
) || !pte_dirty(*pgtable
)))
48 page
= mem_map
+ mapnr
;
49 if ((mapnr
>= max_mapnr
) || PageReserved(page
))
51 flush_cache_page(vma
, addr
);
55 memcpy((char *)maddr
+ (addr
& ~PAGE_MASK
), buf
, len
);
56 flush_page_to_ram(page
);
57 flush_icache_page(vma
, page
);
61 memcpy(buf
, (char *)maddr
+ (addr
& ~PAGE_MASK
), len
);
62 flush_page_to_ram(page
);
68 /* -1: out of memory. 0 - unmapped page */
69 if (handle_mm_fault(mm
, vma
, addr
, write
) > 0)
82 static int access_mm(struct mm_struct
*mm
, struct vm_area_struct
* vma
, unsigned long addr
, void *buf
, int len
, int write
)
87 unsigned long offset
= addr
& ~PAGE_MASK
;
88 int this_len
= PAGE_SIZE
- offset
;
93 retval
= access_one_page(mm
, vma
, addr
, buf
, this_len
, write
);
95 if (retval
!= this_len
)
105 if (addr
< vma
->vm_end
)
109 if (vma
->vm_next
->vm_start
!= vma
->vm_end
)
117 int access_process_vm(struct task_struct
*tsk
, unsigned long addr
, void *buf
, int len
, int write
)
120 struct mm_struct
*mm
;
121 struct vm_area_struct
* vma
;
123 /* Worry about races with exit() */
127 atomic_inc(&mm
->mm_users
);
133 vma
= find_extend_vma(mm
, addr
);
136 copied
= access_mm(mm
, vma
, addr
, buf
, len
, write
);
143 int ptrace_readdata(struct task_struct
*tsk
, unsigned long src
, char *dst
, int len
)
149 int this_len
, retval
;
151 this_len
= (len
> sizeof(buf
)) ? sizeof(buf
) : len
;
152 retval
= access_process_vm(tsk
, src
, buf
, this_len
, 0);
158 if (copy_to_user(dst
, buf
, retval
))
168 int ptrace_writedata(struct task_struct
*tsk
, char * src
, unsigned long dst
, int len
)
174 int this_len
, retval
;
176 this_len
= (len
> sizeof(buf
)) ? sizeof(buf
) : len
;
177 if (copy_from_user(buf
, src
, this_len
))
179 retval
= access_process_vm(tsk
, dst
, buf
, this_len
, 1);