patch-2.3.10 linux/arch/alpha/kernel/ptrace.c
Next file: linux/arch/alpha/kernel/signal.c
Previous file: linux/arch/alpha/config.in
Back to the patch index
Back to the overall index
- Lines: 293
- Date:
Sun Jul 4 13:41:08 1999
- Orig file:
v2.3.9/linux/arch/alpha/kernel/ptrace.c
- Orig date:
Mon Jun 7 11:15:33 1999
diff -u --recursive --new-file v2.3.9/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
@@ -135,242 +135,18 @@
return 0;
}
-/*
- * 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;
-
- DBG(DBG_MEM_ALL, ("getting long at 0x%lx\n", addr));
- 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;
- return *(unsigned long *) page;
-}
-
-/*
- * 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)
+static inline int
+read_int(struct task_struct *task, unsigned long addr, int * 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. */
- if (MAP_NR(page) < max_mapnr)
- *(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
-
- /* 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();
-}
-
-/*
- * 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);
-
- DBG(DBG_MEM_ALL, ("in read_long\n"));
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) {
- struct vm_area_struct * vma_high = vma;
- unsigned long low, align;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- align = addr & (sizeof(long) - 1);
- addr -= align;
- low = get_long(tsk, vma, addr);
- if (align) {
- unsigned long high;
-
- high = get_long(tsk, vma_high, addr + sizeof(long));
- low >>= align * 8;
- low |= high << (64 - align * 8);
- }
- *result = low;
- } else {
- long l = get_long(tsk, vma, addr);
-
- DBG(DBG_MEM_ALL, ("value is 0x%lx\n", l));
- *result = l;
- }
- return 0;
+ int copied = access_process_vm(task, addr, data, sizeof(int), 0);
+ return (copied == sizeof(int)) ? 0 : -EIO;
}
-/*
- * 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)
+static inline int
+write_int(struct task_struct *task, unsigned long addr, int data)
{
- struct vm_area_struct * vma = find_extend_vma(tsk, addr);
-
- if (!vma)
- return -EIO;
- if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
- unsigned long low, high, align;
- struct vm_area_struct * vma_high = vma;
-
- if (addr + sizeof(long) >= vma->vm_end) {
- vma_high = vma->vm_next;
- if (!vma_high || vma_high->vm_start != vma->vm_end)
- return -EIO;
- }
- align = addr & (sizeof(long) - 1);
- addr -= align;
- low = get_long(tsk, vma, addr);
- high = get_long(tsk, vma_high, addr + sizeof(long));
- low &= ~0UL >> (64 - align * 8);
- high &= ~0UL << (align * 8);
- low |= data << (align * 8);
- high |= data >> (64 - align * 8);
- put_long(tsk, vma, addr, low);
- put_long(tsk, vma_high, addr + sizeof(long), high);
- } else
- put_long(tsk, vma, addr, data);
- return 0;
-}
-
-/*
- * Read a 32bit int from address space TSK.
- */
-static int
-read_int(struct task_struct * tsk, unsigned long addr, unsigned int *data)
-{
- unsigned long l, align;
- int res;
-
- align = addr & 0x7;
- addr &= ~0x7;
-
- res = read_long(tsk, addr, &l);
- if (res < 0)
- return res;
-
- if (align == 0) {
- *data = l;
- } else {
- *data = l >> 32;
- }
- return 0;
-}
-
-/*
- * Write a 32bit word to address space TSK.
- *
- * For simplicity, do a read-modify-write of the 64bit word that
- * contains the 32bit word that we are about to write.
- */
-static int
-write_int(struct task_struct * tsk, unsigned long addr, unsigned int data)
-{
- unsigned long l, align;
- int res;
-
- align = addr & 0x7;
- addr &= ~0x7;
-
- res = read_long(tsk, addr, &l);
- if (res < 0)
- return res;
-
- if (align == 0) {
- l = (l & 0xffffffff00000000UL) | ((unsigned long) data << 0);
- } else {
- l = (l & 0x00000000ffffffffUL) | ((unsigned long) data << 32);
- }
- return write_long(tsk, addr, l);
+ int copied = access_process_vm(task, addr, &data, sizeof(int), 1);
+ return (copied == sizeof(int)) ? 0 : -EIO;
}
/*
@@ -521,16 +297,17 @@
switch (request) {
/* When I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA:
- down(&child->mm->mmap_sem);
- ret = read_long(child, addr, &tmp);
- up(&child->mm->mmap_sem);
- DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
- if (ret < 0)
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+ int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
goto out;
+
regs.r0 = 0; /* special return: no errors */
ret = tmp;
goto out;
+ }
/* Read register number ADDR. */
case PTRACE_PEEKUSR:
@@ -541,12 +318,12 @@
/* When I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
- case PTRACE_POKEDATA:
- DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
- down(&child->mm->mmap_sem);
- ret = write_long(child, addr, data);
- up(&child->mm->mmap_sem);
+ case PTRACE_POKEDATA: {
+ unsigned long tmp = data;
+ int copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 1);
+ ret = (copied == sizeof(tmp)) ? 0 : -EIO;
goto out;
+ }
case PTRACE_POKEUSR: /* write the specified register */
DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)