diff options
Diffstat (limited to 'arch/um/kernel/ptrace.c')
| -rw-r--r-- | arch/um/kernel/ptrace.c | 70 |
1 files changed, 16 insertions, 54 deletions
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 8e3d69e4fcb5..484509948ee9 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
| @@ -12,16 +12,25 @@ | |||
| 12 | #endif | 12 | #endif |
| 13 | #include "skas_ptrace.h" | 13 | #include "skas_ptrace.h" |
| 14 | 14 | ||
| 15 | static inline void set_singlestepping(struct task_struct *child, int on) | 15 | |
| 16 | |||
| 17 | void user_enable_single_step(struct task_struct *child) | ||
| 16 | { | 18 | { |
| 17 | if (on) | 19 | child->ptrace |= PT_DTRACE; |
| 18 | child->ptrace |= PT_DTRACE; | ||
| 19 | else | ||
| 20 | child->ptrace &= ~PT_DTRACE; | ||
| 21 | child->thread.singlestep_syscall = 0; | 20 | child->thread.singlestep_syscall = 0; |
| 22 | 21 | ||
| 23 | #ifdef SUBARCH_SET_SINGLESTEPPING | 22 | #ifdef SUBARCH_SET_SINGLESTEPPING |
| 24 | SUBARCH_SET_SINGLESTEPPING(child, on); | 23 | SUBARCH_SET_SINGLESTEPPING(child, 1); |
| 24 | #endif | ||
| 25 | } | ||
| 26 | |||
| 27 | void user_disable_single_step(struct task_struct *child) | ||
| 28 | { | ||
| 29 | child->ptrace &= ~PT_DTRACE; | ||
| 30 | child->thread.singlestep_syscall = 0; | ||
| 31 | |||
| 32 | #ifdef SUBARCH_SET_SINGLESTEPPING | ||
| 33 | SUBARCH_SET_SINGLESTEPPING(child, 0); | ||
| 25 | #endif | 34 | #endif |
| 26 | } | 35 | } |
| 27 | 36 | ||
| @@ -30,7 +39,7 @@ static inline void set_singlestepping(struct task_struct *child, int on) | |||
| 30 | */ | 39 | */ |
| 31 | void ptrace_disable(struct task_struct *child) | 40 | void ptrace_disable(struct task_struct *child) |
| 32 | { | 41 | { |
| 33 | set_singlestepping(child,0); | 42 | user_disable_single_step(child); |
| 34 | } | 43 | } |
| 35 | 44 | ||
| 36 | extern int peek_user(struct task_struct * child, long addr, long data); | 45 | extern int peek_user(struct task_struct * child, long addr, long data); |
| @@ -69,53 +78,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 69 | ret = -EIO; | 78 | ret = -EIO; |
| 70 | break; | 79 | break; |
| 71 | 80 | ||
| 72 | /* continue and stop at next (return from) syscall */ | ||
| 73 | case PTRACE_SYSCALL: | ||
| 74 | /* restart after signal. */ | ||
| 75 | case PTRACE_CONT: { | ||
| 76 | ret = -EIO; | ||
| 77 | if (!valid_signal(data)) | ||
| 78 | break; | ||
| 79 | |||
| 80 | set_singlestepping(child, 0); | ||
| 81 | if (request == PTRACE_SYSCALL) | ||
| 82 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 83 | else clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 84 | child->exit_code = data; | ||
| 85 | wake_up_process(child); | ||
| 86 | ret = 0; | ||
| 87 | break; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* | ||
| 91 | * make the child exit. Best I can do is send it a sigkill. | ||
| 92 | * perhaps it should be put in the status that it wants to | ||
| 93 | * exit. | ||
| 94 | */ | ||
| 95 | case PTRACE_KILL: { | ||
| 96 | ret = 0; | ||
| 97 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
| 98 | break; | ||
| 99 | |||
| 100 | set_singlestepping(child, 0); | ||
| 101 | child->exit_code = SIGKILL; | ||
| 102 | wake_up_process(child); | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | |||
| 106 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | ||
| 107 | ret = -EIO; | ||
| 108 | if (!valid_signal(data)) | ||
| 109 | break; | ||
| 110 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
| 111 | set_singlestepping(child, 1); | ||
| 112 | child->exit_code = data; | ||
| 113 | /* give it a chance to run. */ | ||
| 114 | wake_up_process(child); | ||
| 115 | ret = 0; | ||
| 116 | break; | ||
| 117 | } | ||
| 118 | |||
| 119 | #ifdef PTRACE_GETREGS | 81 | #ifdef PTRACE_GETREGS |
| 120 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ | 82 | case PTRACE_GETREGS: { /* Get all gp regs from the child. */ |
| 121 | if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { | 83 | if (!access_ok(VERIFY_WRITE, p, MAX_REG_OFFSET)) { |
