patch-2.3.10 linux/arch/sparc/kernel/ptrace.c
Next file: linux/arch/sparc/kernel/sparc-stub.c
Previous file: linux/arch/sparc/kernel/process.c
Back to the patch index
Back to the overall index
- Lines: 335
- Date:
Mon Jul 5 11:30:11 1999
- Orig file:
v2.3.9/linux/arch/sparc/kernel/ptrace.c
- Orig date:
Mon Jun 7 11:15:33 1999
diff -u --recursive --new-file v2.3.9/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c
@@ -24,202 +24,6 @@
#define MAGIC_CONSTANT 0x80000000
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- */
-static unsigned long get_long(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
-{
- pgd_t * pgdir;
- pmd_t * pgmiddle;
- pte_t * pgtable;
- unsigned long page, retval;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (pgd_none(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return 0;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return 0;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 0);
- goto repeat;
- }
- page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
- if (MAP_NR(page) >= max_mapnr)
- return 0;
- page += addr & ~PAGE_MASK;
- retval = *(unsigned long *) page;
- flush_page_to_ram(page);
- return retval;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it. -M.U-
- */
-static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long addr, unsigned long data)
-{
- pgd_t *pgdir;
- pmd_t *pgmiddle;
- pte_t *pgtable;
- unsigned long page;
-
-repeat:
- pgdir = pgd_offset(vma->vm_mm, addr);
- if (!pgd_present(*pgdir)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
- pgd_clear(pgdir);
- return;
- }
- pgmiddle = pmd_offset(pgdir, addr);
- if (pmd_none(*pgmiddle)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page middle %08lx\n", pmd_val(*pgmiddle));
- pmd_clear(pgmiddle);
- return;
- }
- pgtable = pte_offset(pgmiddle, addr);
- if (!pte_present(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
- page = pte_page(*pgtable);
- if (!pte_write(*pgtable)) {
- handle_mm_fault(tsk, vma, addr, 1);
- goto repeat;
- }
-/* this is a hack for non-kernel-mapped video buffers and similar */
- flush_cache_page(vma, addr);
- if (MAP_NR(page) < max_mapnr) {
- *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
- flush_page_to_ram(page);
- }
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
- set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- flush_tlb_page(vma, addr);
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
- unsigned long * result)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- *result = get_long(tsk, vma, addr);
- return 0;
-}
-
-static int read_byte(struct task_struct *tsk, unsigned long addr,
- unsigned char *result)
-{
- struct vm_area_struct *vma = find_extend_vma(tsk, addr&~3);
- unsigned long tmp;
-
- if(!vma)
- return -EIO;
- tmp = get_long(tsk, vma, (addr & ~3));
- switch(addr & 3) {
- case 0:
- *result = (tmp & 0xff000000)>>24;
- break;
- case 1:
- *result = (tmp & 0x00ff0000)>>16;
- break;
- case 2:
- *result = (tmp & 0x0000ff00)>>8;
- break;
- case 3:
- *result = (tmp & 0x000000ff);
- break;
- }
- return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
- unsigned long data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- put_long(tsk, vma, addr, data);
- return 0;
-}
-
-static int write_byte(struct task_struct * tsk, unsigned long addr,
- unsigned char data)
-{
- struct vm_area_struct * vma = find_extend_vma(tsk, (addr & ~3));
- unsigned long tmp;
-
- if (!vma)
- return -EIO;
- tmp = get_long(tsk, vma, (addr & ~3));
- switch(addr & 3) {
- case 0:
- tmp &= 0x00ffffff;
- tmp |= (data << 24);
- break;
- case 1:
- tmp &= 0xff00ffff;
- tmp |= ((data << 16) & 0x00ff0000);
- break;
- case 2:
- tmp &= 0xffff00ff;
- tmp |= ((data << 8) & 0x0000ff00);
- break;
- case 3:
- tmp &= 0xffffff00;
- tmp |= (data & 0x000000ff);
- break;
- }
- put_long(tsk, vma, (addr & ~3), tmp);
- return 0;
-}
/* Returning from ptrace is a bit tricky because the syscall return
* low level code assumes any value returned which is negative and
@@ -565,24 +369,12 @@
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
- int res;
-
- /* XXX Find out what is really going on. */
- flush_cache_all();
- /* Non-word alignment _not_ allowed on Sparc. */
- if(addr & (sizeof(unsigned long) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- res = read_long(child, addr, &tmp);
- up(&child->mm->mmap_sem);
- if (res < 0) {
- pt_error_return(regs, -res);
- goto out;
- }
- pt_os_succ_return(regs, tmp, (long *) data);
+ if (access_process_vm(child, addr,
+ &tmp, sizeof(tmp), 0) == sizeof(tmp))
+ pt_os_succ_return(regs, tmp, (long *)data);
+ else
+ pt_error_return(regs, EIO);
goto out;
}
@@ -596,22 +388,11 @@
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: {
- struct vm_area_struct *vma;
- int res;
-
- /* Non-word alignment _not_ allowed on Sparc. */
- if(addr & (sizeof(unsigned long) - 1)) {
- pt_error_return(regs, EINVAL);
- goto out;
- }
- down(&child->mm->mmap_sem);
- vma = find_extend_vma(child, addr);
- res = write_long(child, addr, data);
- up(&child->mm->mmap_sem);
- if(res < 0)
- pt_error_return(regs, -res);
+ if (access_process_vm(child, addr,
+ &data, sizeof(data), 1) == sizeof(data))
+ pt_succ_return(regs, 0);
else
- pt_succ_return(regs, res);
+ pt_error_return(regs, EIO);
goto out;
}
@@ -737,56 +518,31 @@
case PTRACE_READTEXT:
case PTRACE_READDATA: {
- unsigned char *dest = (unsigned char *) addr2;
- unsigned long src = addr;
- unsigned char tmp;
- int res, len = data;
-
- res = verify_area(VERIFY_WRITE, dest, len);
- if(res) {
- pt_error_return(regs, -res);
- goto out;
- }
- while(len) {
- down(&child->mm->mmap_sem);
- res = read_byte(child, src, &tmp);
- up(&child->mm->mmap_sem);
- if(res < 0) {
- pt_error_return(regs, -res);
- goto out;
- }
- __put_user(tmp, dest);
- src++; dest++; len--;
+ int res = ptrace_readdata(child, addr, (void *) addr2, data);
+
+ if (res == data) {
+ pt_succ_return(regs, 0);
+ goto out;
}
- pt_succ_return(regs, 0);
+ /* Partial read is an IO failure */
+ if (res >= 0)
+ res = -EIO;
+ pt_error_return(regs, -res);
goto out;
}
case PTRACE_WRITETEXT:
case PTRACE_WRITEDATA: {
- unsigned char *src = (unsigned char *) addr2;
- unsigned long dest = addr;
- int res, len = data;
-
- res = verify_area(VERIFY_READ, src, len);
- if(res) {
- pt_error_return(regs, -res);
- goto out;
- }
- while(len) {
- unsigned long tmp;
-
- __get_user(tmp, src);
- down(&child->mm->mmap_sem);
- res = write_byte(child, dest, tmp);
- up(&child->mm->mmap_sem);
- if(res < 0) {
- pt_error_return(regs, -res);
- goto out;
- }
- src++; dest++; len--;
+ int res = ptrace_writedata(child, (void *) addr2, addr, data);
+
+ if (res == data) {
+ pt_succ_return(regs, 0);
+ goto out;
}
- pt_succ_return(regs, 0);
+ /* Partial write is an IO failure */
+ if (res >= 0)
+ res = -EIO;
+ pt_error_return(regs, -res);
goto out;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)