long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { int ret; unsigned int regno = addr >> 2; unsigned long __user *datap = (unsigned long __user *)data; switch (request) { /* Read word at location address. */ case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: { unsigned long tmp; int copied; ret = -EIO; /* The signal trampoline page is outside the normal user-addressable * space but still accessible. This is hack to make it possible to * access the signal handler code in GDB. */ if ((addr & PAGE_MASK) == cris_signal_return_page) { /* The trampoline page is globally mapped, no page table to traverse.*/ tmp = *(unsigned long*)addr; } else { copied = ptrace_access_vm(child, addr, &tmp, sizeof(tmp), FOLL_FORCE); if (copied != sizeof(tmp)) break; } ret = put_user(tmp,datap); break; } /* Read the word at location address in the USER area. */ case PTRACE_PEEKUSR: { unsigned long tmp; ret = -EIO; if ((addr & 3) || regno > PT_MAX) break; tmp = get_reg(child, regno); ret = put_user(tmp, datap); break; } /* Write the word at location address. */ case PTRACE_POKETEXT: case PTRACE_POKEDATA: ret = generic_ptrace_pokedata(child, addr, data); break; /* Write the word at location address in the USER area. */ case PTRACE_POKEUSR: ret = -EIO; if ((addr & 3) || regno > PT_MAX) break; if (regno == PT_CCS) { /* don't allow the tracing process to change stuff like * interrupt enable, kernel/user bit, dma enables etc. */ data &= CCS_MASK; data |= get_reg(child, PT_CCS) & ~CCS_MASK; } if (put_reg(child, regno, data)) break; ret = 0; break; /* Get all GP registers from the child. */ case PTRACE_GETREGS: { int i; unsigned long tmp; for (i = 0; i <= PT_MAX; i++) { tmp = get_reg(child, i); if (put_user(tmp, datap)) { ret = -EFAULT; goto out_tsk; } datap++; } ret = 0; break; } /* Set all GP registers in the child. */ case PTRACE_SETREGS: { int i; unsigned long tmp; for (i = 0; i <= PT_MAX; i++) { if (get_user(tmp, datap)) { ret = -EFAULT; goto out_tsk; } if (i == PT_CCS) { tmp &= CCS_MASK; tmp |= get_reg(child, PT_CCS) & ~CCS_MASK; } put_reg(child, i, tmp); datap++; } ret = 0; break; } default: ret = ptrace_request(child, request, addr, data); break; } out_tsk: return ret; }
long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { int ret; unsigned long __user *datap = (unsigned long __user *)data; void *paddr = (void *)addr; switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKDATA: pr_debug("ptrace: PEEKDATA\n"); /* fall through */ case PTRACE_PEEKTEXT: /* read word at location addr. */ { unsigned long tmp = 0; int copied = 0, to_copy = sizeof(tmp); ret = -EIO; pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %i\n", addr, to_copy); if (is_user_addr_valid(child, addr, to_copy) < 0) break; pr_debug("ptrace: user address is valid\n"); switch (bfin_mem_access_type(addr, to_copy)) { case BFIN_MEM_ACCESS_CORE: case BFIN_MEM_ACCESS_CORE_ONLY: copied = ptrace_access_vm(child, addr, &tmp, to_copy, FOLL_FORCE); if (copied) break; /* hrm, why didn't that work ... maybe no mapping */ if (addr >= FIXED_CODE_START && addr + to_copy <= FIXED_CODE_END) { copy_from_user_page(0, 0, 0, &tmp, paddr, to_copy); copied = to_copy; } else if (addr >= BOOT_ROM_START) { memcpy(&tmp, paddr, to_copy); copied = to_copy; } break; case BFIN_MEM_ACCESS_DMA: if (safe_dma_memcpy(&tmp, paddr, to_copy)) copied = to_copy; break; case BFIN_MEM_ACCESS_ITEST: if (isram_memcpy(&tmp, paddr, to_copy)) copied = to_copy; break; default: copied = 0; break; } pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); if (copied == to_copy) ret = put_user(tmp, datap); break; } /* when I and D space are separate, this will have to be fixed. */ case PTRACE_POKEDATA: pr_debug("ptrace: PTRACE_PEEKDATA\n"); /* fall through */ case PTRACE_POKETEXT: /* write the word at location addr. */ { int copied = 0, to_copy = sizeof(data); ret = -EIO; pr_debug("ptrace: POKETEXT at addr 0x%08lx + %i bytes %lx\n", addr, to_copy, data); if (is_user_addr_valid(child, addr, to_copy) < 0) break; pr_debug("ptrace: user address is valid\n"); switch (bfin_mem_access_type(addr, to_copy)) { case BFIN_MEM_ACCESS_CORE: case BFIN_MEM_ACCESS_CORE_ONLY: copied = ptrace_access_vm(child, addr, &data, to_copy, FOLL_FORCE | FOLL_WRITE); break; case BFIN_MEM_ACCESS_DMA: if (safe_dma_memcpy(paddr, &data, to_copy)) copied = to_copy; break; case BFIN_MEM_ACCESS_ITEST: if (isram_memcpy(paddr, &data, to_copy)) copied = to_copy; break; default: copied = 0; break; } pr_debug("ptrace: copied size %d\n", copied); if (copied == to_copy) ret = 0; break; } case PTRACE_PEEKUSR: switch (addr) { #ifdef CONFIG_BINFMT_ELF_FDPIC /* backwards compat */ case PT_FDPIC_EXEC: request = PTRACE_GETFDPIC; addr = PTRACE_GETFDPIC_EXEC; goto case_default; case PT_FDPIC_INTERP: request = PTRACE_GETFDPIC; addr = PTRACE_GETFDPIC_INTERP; goto case_default; #endif default: ret = get_reg(child, addr, datap); } pr_debug("ptrace: PEEKUSR reg %li with %#lx = %i\n", addr, data, ret); break; case PTRACE_POKEUSR: ret = put_reg(child, addr, data); pr_debug("ptrace: POKEUSR reg %li with %li = %i\n", addr, data, ret); break; case PTRACE_GETREGS: pr_debug("ptrace: PTRACE_GETREGS\n"); return copy_regset_to_user(child, &user_bfin_native_view, REGSET_GENERAL, 0, sizeof(struct pt_regs), datap); case PTRACE_SETREGS: pr_debug("ptrace: PTRACE_SETREGS\n"); return copy_regset_from_user(child, &user_bfin_native_view, REGSET_GENERAL, 0, sizeof(struct pt_regs), datap); case_default: default: ret = ptrace_request(child, request, addr, data); break; } return ret; }