📄 ptrace.c
字号:
retval |= __copy_to_user(&ppr->gr[1], &pt->r1, sizeof(long) * 3); /* gr4-gr7 */ for (i = 4; i < 8; i++) { retval |= unw_access_gr(&info, i, &ppr->gr[i], &nat, 0); } /* gr8-gr11 */ retval |= __copy_to_user(&ppr->gr[8], &pt->r8, sizeof(long) * 4); /* gr12-gr15 */ retval |= __copy_to_user(&ppr->gr[12], &pt->r12, sizeof(long) * 4); /* gr16-gr31 */ retval |= __copy_to_user(&ppr->gr[16], &pt->r16, sizeof(long) * 16); /* b0 */ retval |= __put_user(pt->b0, &ppr->br[0]); /* b1-b5 */ for (i = 1; i < 6; i++) { retval |= unw_access_br(&info, i, &ppr->br[i], 0); } /* b6-b7 */ retval |= __put_user(pt->b6, &ppr->br[6]); retval |= __put_user(pt->b7, &ppr->br[7]); /* fr2-fr5 */ for (i = 2; i < 6; i++) { retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 0); retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 0); } /* fr6-fr9 */ retval |= __copy_to_user(&ppr->fr[6], &pt->f6, sizeof(struct ia64_fpreg) * 4); /* fp scratch regs(10-15) */ retval |= __copy_to_user(&ppr->fr[10], &sw->f10, sizeof(struct ia64_fpreg) * 6); /* fr16-fr31 */ for (i = 16; i < 32; i++) { retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 0); retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 0); } /* fph */ ia64_flush_fph(child); retval |= __copy_to_user(&ppr->fr[32], &child->thread.fph, sizeof(ppr->fr[32]) * 96); /* preds */ retval |= __put_user(pt->pr, &ppr->pr); /* nat bits */ retval |= access_uarea(child, PT_NAT_BITS, &ppr->nat, 0); ret = retval ? -EIO : 0; return ret;}static longptrace_setregs (struct task_struct *child, struct pt_all_user_regs *ppr){ struct switch_stack *sw; struct pt_regs *pt; long ret, retval; struct unw_frame_info info; char nat = 0; int i; retval = verify_area(VERIFY_READ, ppr, sizeof(struct pt_all_user_regs)); if (retval != 0) { return -EIO; } pt = ia64_task_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); unw_init_from_blocked_task(&info, child); if (unw_unwind_to_user(&info) < 0) { return -EIO; } if (((unsigned long) ppr & 0x7) != 0) { dprintk("ptrace:unaligned register address %p\n", ppr); return -EIO; } retval = 0; /* control regs */ retval |= __get_user(pt->cr_iip, &ppr->cr_iip); retval |= access_uarea(child, PT_CR_IPSR, &ppr->cr_ipsr, 1); /* app regs */ retval |= __get_user(pt->ar_pfs, &ppr->ar[PT_AUR_PFS]); retval |= __get_user(pt->ar_rsc, &ppr->ar[PT_AUR_RSC]); retval |= __get_user(pt->ar_bspstore, &ppr->ar[PT_AUR_BSPSTORE]); retval |= __get_user(pt->ar_unat, &ppr->ar[PT_AUR_UNAT]); retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]); retval |= __get_user(pt->ar_fpsr, &ppr->ar[PT_AUR_FPSR]); retval |= access_uarea(child, PT_AR_EC, &ppr->ar[PT_AUR_EC], 1); retval |= access_uarea(child, PT_AR_LC, &ppr->ar[PT_AUR_LC], 1); retval |= access_uarea(child, PT_AR_RNAT, &ppr->ar[PT_AUR_RNAT], 1); retval |= access_uarea(child, PT_AR_BSP, &ppr->ar[PT_AUR_BSP], 1); retval |= access_uarea(child, PT_CFM, &ppr->cfm, 1); /* gr1-gr3 */ retval |= __copy_from_user(&pt->r1, &ppr->gr[1], sizeof(long) * 3); /* gr4-gr7 */ for (i = 4; i < 8; i++) { long ret = unw_get_gr(&info, i, &ppr->gr[i], &nat); if (ret < 0) { return ret; } retval |= unw_access_gr(&info, i, &ppr->gr[i], &nat, 1); } /* gr8-gr11 */ retval |= __copy_from_user(&pt->r8, &ppr->gr[8], sizeof(long) * 4); /* gr12-gr15 */ retval |= __copy_from_user(&pt->r12, &ppr->gr[12], sizeof(long) * 4); /* gr16-gr31 */ retval |= __copy_from_user(&pt->r16, &ppr->gr[16], sizeof(long) * 16); /* b0 */ retval |= __get_user(pt->b0, &ppr->br[0]); /* b1-b5 */ for (i = 1; i < 6; i++) { retval |= unw_access_br(&info, i, &ppr->br[i], 1); } /* b6-b7 */ retval |= __get_user(pt->b6, &ppr->br[6]); retval |= __get_user(pt->b7, &ppr->br[7]); /* fr2-fr5 */ for (i = 2; i < 6; i++) { retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 1); retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 1); } /* fr6-fr9 */ retval |= __copy_from_user(&pt->f6, &ppr->fr[6], sizeof(ppr->fr[6]) * 4); /* fp scratch regs(10-15) */ retval |= __copy_from_user(&sw->f10, &ppr->fr[10], sizeof(ppr->fr[10]) * 6); /* fr16-fr31 */ for (i = 16; i < 32; i++) { retval |= access_fr(&info, i, 0, (unsigned long *) &ppr->fr[i], 1); retval |= access_fr(&info, i, 1, (unsigned long *) &ppr->fr[i] + 1, 1); } /* fph */ ia64_sync_fph(child); retval |= __copy_from_user(&child->thread.fph, &ppr->fr[32], sizeof(ppr->fr[32]) * 96); /* preds */ retval |= __get_user(pt->pr, &ppr->pr); /* nat bits */ retval |= access_uarea(child, PT_NAT_BITS, &ppr->nat, 1); ret = retval ? -EIO : 0; return ret;}/* * Called by kernel/ptrace.c when detaching.. * * Make sure the single step bit is not set. */voidptrace_disable (struct task_struct *child){ struct ia64_psr *child_psr = ia64_psr(ia64_task_regs(child)); /* make sure the single step/take-branch tra bits are not set: */ child_psr->ss = 0; child_psr->tb = 0; /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED;}asmlinkage longsys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, long arg4, long arg5, long arg6, long arg7, long stack){ struct pt_regs *pt, *regs = (struct pt_regs *) &stack; unsigned long urbs_end; struct task_struct *child; struct switch_stack *sw; long ret; lock_kernel(); ret = -EPERM; if (request == PTRACE_TRACEME) { /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; current->ptrace |= PT_PTRACED; ret = 0; goto out; } ret = -ESRCH; read_lock(&tasklist_lock); { child = find_task_by_pid(pid); if (child) get_task_struct(child); } read_unlock(&tasklist_lock); if (!child) goto out; ret = -EPERM; if (pid == 1) /* no messing around with init! */ goto out_tsk; if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); goto out_tsk; } ret = ptrace_check_attach(child, request == PTRACE_KILL); if (ret < 0) goto out_tsk; pt = ia64_task_regs(child); sw = (struct switch_stack *) (child->thread.ksp + 16); switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: /* read word at location addr */ urbs_end = ia64_get_user_rbs_end(child, pt, NULL); if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED)) threads_sync_user_rbs(child, urbs_end, 0); ret = ia64_peek(child, sw, urbs_end, addr, &data); if (ret == 0) { ret = data; regs->r8 = 0; /* ensure "ret" is not mistaken as an error code */ } goto out_tsk; case PTRACE_POKETEXT: case PTRACE_POKEDATA: /* write the word at location addr */ urbs_end = ia64_get_user_rbs_end(child, pt, NULL); if (!(child->thread.flags & IA64_THREAD_KRBS_SYNCED)) threads_sync_user_rbs(child, urbs_end, 1); ret = ia64_poke(child, sw, urbs_end, addr, data); goto out_tsk; case PTRACE_PEEKUSR: /* read the word at addr in the USER area */ if (access_uarea(child, addr, &data, 0) < 0) { ret = -EIO; goto out_tsk; } ret = data; regs->r8 = 0; /* ensure "ret" is not mistaken as an error code */ goto out_tsk; case PTRACE_POKEUSR: /* write the word at addr in the USER area */ if (access_uarea(child, addr, &data, 1) < 0) { ret = -EIO; goto out_tsk; } ret = 0; goto out_tsk; case PTRACE_GETSIGINFO: ret = -EIO; if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t)) || !child->thread.siginfo) goto out_tsk; ret = copy_siginfo_to_user((siginfo_t *) data, child->thread.siginfo); goto out_tsk; case PTRACE_SETSIGINFO: ret = -EIO; if (!access_ok(VERIFY_READ, data, sizeof (siginfo_t)) || child->thread.siginfo == 0) goto out_tsk; ret = copy_siginfo_from_user(child->thread.siginfo, (siginfo_t *) data); goto out_tsk; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: /* restart after signal. */ ret = -EIO; if (data > _NSIG) goto out_tsk; if (request == PTRACE_SYSCALL) child->ptrace |= PT_TRACESYS; else child->ptrace &= ~PT_TRACESYS; child->exit_code = data; /* make sure the single step/taken-branch trap bits are not set: */ ia64_psr(pt)->ss = 0; ia64_psr(pt)->tb = 0; /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; wake_up_process(child); ret = 0; goto out_tsk; case PTRACE_KILL: /* * Make the child exit. Best I can do is send it a * sigkill. Perhaps it should be put in the status * that it wants to exit. */ if (child->state == TASK_ZOMBIE) /* already dead */ goto out_tsk; child->exit_code = SIGKILL; /* make sure the single step/take-branch tra bits are not set: */ ia64_psr(pt)->ss = 0; ia64_psr(pt)->tb = 0; /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; wake_up_process(child); ret = 0; goto out_tsk; case PTRACE_SINGLESTEP: /* let child execute for one instruction */ case PTRACE_SINGLEBLOCK: ret = -EIO; if (data > _NSIG) goto out_tsk; child->ptrace &= ~PT_TRACESYS; if (request == PTRACE_SINGLESTEP) { ia64_psr(pt)->ss = 1; } else { ia64_psr(pt)->tb = 1; } child->exit_code = data; /* Turn off flag indicating that the KRBS is sync'd with child's VM: */ child->thread.flags &= ~IA64_THREAD_KRBS_SYNCED; /* give it a chance to run. */ wake_up_process(child); ret = 0; goto out_tsk; case PTRACE_DETACH: /* detach a process that was attached. */ ret = ptrace_detach(child, data); goto out_tsk; case PTRACE_GETREGS: ret = ptrace_getregs(child, (struct pt_all_user_regs*) data); goto out_tsk; case PTRACE_SETREGS: ret = ptrace_setregs(child, (struct pt_all_user_regs*) data); goto out_tsk; default: ret = -EIO; goto out_tsk; } out_tsk: free_task_struct(child); out: unlock_kernel(); return ret;}voidsyscall_trace (void){ if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; current->exit_code = SIGTRAP; set_current_state(TASK_STOPPED); notify_parent(current, SIGCHLD); schedule(); /* * This isn't the same as continuing with a signal, but it * will do for normal use. strace only continues with a * signal if the stopping signal is not SIGTRAP. -brl */ if (current->exit_code) { send_sig(current->exit_code, current, 1); current->exit_code = 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -