diff options
Diffstat (limited to 'arch/um/kernel/ptrace.c')
| -rw-r--r-- | arch/um/kernel/ptrace.c | 79 |
1 files changed, 29 insertions, 50 deletions
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 3efa59a941a4..2b75d8d9ba73 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c | |||
| @@ -19,15 +19,30 @@ | |||
| 19 | #include "skas_ptrace.h" | 19 | #include "skas_ptrace.h" |
| 20 | #include "sysdep/ptrace.h" | 20 | #include "sysdep/ptrace.h" |
| 21 | 21 | ||
| 22 | static inline void set_singlestepping(struct task_struct *child, int on) | ||
| 23 | { | ||
| 24 | if (on) | ||
| 25 | child->ptrace |= PT_DTRACE; | ||
| 26 | else | ||
| 27 | child->ptrace &= ~PT_DTRACE; | ||
| 28 | child->thread.singlestep_syscall = 0; | ||
| 29 | |||
| 30 | #ifdef SUBARCH_SET_SINGLESTEPPING | ||
| 31 | SUBARCH_SET_SINGLESTEPPING(child, on) | ||
| 32 | #endif | ||
| 33 | } | ||
| 34 | |||
| 22 | /* | 35 | /* |
| 23 | * Called by kernel/ptrace.c when detaching.. | 36 | * Called by kernel/ptrace.c when detaching.. |
| 24 | */ | 37 | */ |
| 25 | void ptrace_disable(struct task_struct *child) | 38 | void ptrace_disable(struct task_struct *child) |
| 26 | { | 39 | { |
| 27 | child->ptrace &= ~PT_DTRACE; | 40 | set_singlestepping(child,0); |
| 28 | child->thread.singlestep_syscall = 0; | ||
| 29 | } | 41 | } |
| 30 | 42 | ||
| 43 | extern int peek_user(struct task_struct * child, long addr, long data); | ||
| 44 | extern int poke_user(struct task_struct * child, long addr, long data); | ||
| 45 | |||
| 31 | long sys_ptrace(long request, long pid, long addr, long data) | 46 | long sys_ptrace(long request, long pid, long addr, long data) |
| 32 | { | 47 | { |
| 33 | struct task_struct *child; | 48 | struct task_struct *child; |
| @@ -67,6 +82,10 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 67 | goto out_tsk; | 82 | goto out_tsk; |
| 68 | } | 83 | } |
| 69 | 84 | ||
| 85 | #ifdef SUBACH_PTRACE_SPECIAL | ||
| 86 | SUBARCH_PTRACE_SPECIAL(child,request,addr,data) | ||
| 87 | #endif | ||
| 88 | |||
| 70 | ret = ptrace_check_attach(child, request == PTRACE_KILL); | 89 | ret = ptrace_check_attach(child, request == PTRACE_KILL); |
| 71 | if (ret < 0) | 90 | if (ret < 0) |
| 72 | goto out_tsk; | 91 | goto out_tsk; |
| @@ -87,28 +106,9 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 87 | } | 106 | } |
| 88 | 107 | ||
| 89 | /* read the word at location addr in the USER area. */ | 108 | /* read the word at location addr in the USER area. */ |
| 90 | case PTRACE_PEEKUSR: { | 109 | case PTRACE_PEEKUSR: |
| 91 | unsigned long tmp; | 110 | ret = peek_user(child, addr, data); |
| 92 | 111 | break; | |
| 93 | ret = -EIO; | ||
| 94 | if ((addr & 3) || addr < 0) | ||
| 95 | break; | ||
| 96 | |||
| 97 | tmp = 0; /* Default return condition */ | ||
| 98 | if(addr < MAX_REG_OFFSET){ | ||
| 99 | tmp = getreg(child, addr); | ||
| 100 | } | ||
| 101 | #if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT) | ||
| 102 | else if((addr >= offsetof(struct user, u_debugreg[0])) && | ||
| 103 | (addr <= offsetof(struct user, u_debugreg[7]))){ | ||
| 104 | addr -= offsetof(struct user, u_debugreg[0]); | ||
| 105 | addr = addr >> 2; | ||
| 106 | tmp = child->thread.arch.debugregs[addr]; | ||
| 107 | } | ||
| 108 | #endif | ||
| 109 | ret = put_user(tmp, (unsigned long __user *) data); | ||
| 110 | break; | ||
| 111 | } | ||
| 112 | 112 | ||
| 113 | /* when I and D space are separate, this will have to be fixed. */ | 113 | /* when I and D space are separate, this will have to be fixed. */ |
| 114 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 114 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
| @@ -121,26 +121,8 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 121 | break; | 121 | break; |
| 122 | 122 | ||
| 123 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ | 123 | case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ |
| 124 | ret = -EIO; | 124 | ret = poke_user(child, addr, data); |
| 125 | if ((addr & 3) || addr < 0) | 125 | break; |
| 126 | break; | ||
| 127 | |||
| 128 | if (addr < MAX_REG_OFFSET) { | ||
| 129 | ret = putreg(child, addr, data); | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | #if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT) | ||
| 133 | else if((addr >= offsetof(struct user, u_debugreg[0])) && | ||
| 134 | (addr <= offsetof(struct user, u_debugreg[7]))){ | ||
| 135 | addr -= offsetof(struct user, u_debugreg[0]); | ||
| 136 | addr = addr >> 2; | ||
| 137 | if((addr == 4) || (addr == 5)) break; | ||
| 138 | child->thread.arch.debugregs[addr] = data; | ||
| 139 | ret = 0; | ||
| 140 | } | ||
| 141 | #endif | ||
| 142 | |||
| 143 | break; | ||
| 144 | 126 | ||
| 145 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | 127 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ |
| 146 | case PTRACE_CONT: { /* restart after signal. */ | 128 | case PTRACE_CONT: { /* restart after signal. */ |
| @@ -148,8 +130,7 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 148 | if (!valid_signal(data)) | 130 | if (!valid_signal(data)) |
| 149 | break; | 131 | break; |
| 150 | 132 | ||
| 151 | child->ptrace &= ~PT_DTRACE; | 133 | set_singlestepping(child, 0); |
| 152 | child->thread.singlestep_syscall = 0; | ||
| 153 | if (request == PTRACE_SYSCALL) { | 134 | if (request == PTRACE_SYSCALL) { |
| 154 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 135 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
| 155 | } | 136 | } |
| @@ -172,8 +153,7 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 172 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | 153 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ |
| 173 | break; | 154 | break; |
| 174 | 155 | ||
| 175 | child->ptrace &= ~PT_DTRACE; | 156 | set_singlestepping(child, 0); |
| 176 | child->thread.singlestep_syscall = 0; | ||
| 177 | child->exit_code = SIGKILL; | 157 | child->exit_code = SIGKILL; |
| 178 | wake_up_process(child); | 158 | wake_up_process(child); |
| 179 | break; | 159 | break; |
| @@ -184,8 +164,7 @@ long sys_ptrace(long request, long pid, long addr, long data) | |||
| 184 | if (!valid_signal(data)) | 164 | if (!valid_signal(data)) |
| 185 | break; | 165 | break; |
| 186 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | 166 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
| 187 | child->ptrace |= PT_DTRACE; | 167 | set_singlestepping(child, 1); |
| 188 | child->thread.singlestep_syscall = 0; | ||
| 189 | child->exit_code = data; | 168 | child->exit_code = data; |
| 190 | /* give it a chance to run. */ | 169 | /* give it a chance to run. */ |
| 191 | wake_up_process(child); | 170 | wake_up_process(child); |
