diff options
author | Paul Mundt <lethal@linux-sh.org> | 2008-07-30 06:09:31 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2008-08-01 15:39:33 -0400 |
commit | c459dbf294b4a3d70490a468a7ca3907fb2c2f57 (patch) | |
tree | c78866944d8e03247b6d5072987cd7f7c558caef /arch/sh/kernel/ptrace_64.c | |
parent | c4637d475170ca0d99973efd07df727012db6cd1 (diff) |
sh: ptrace single stepping cleanups.
This converts the single stepping done by sh/sh64 ptrace implementations
to use the generic user_enable/disable_single_step(), and subsequently
rips out a lot of ptrace request cases that are now handled generically.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/ptrace_64.c')
-rw-r--r-- | arch/sh/kernel/ptrace_64.c | 77 |
1 files changed, 12 insertions, 65 deletions
diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 7d8776260953..108f3962e39a 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c | |||
@@ -121,18 +121,23 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) | |||
121 | return 0; | 121 | return 0; |
122 | } | 122 | } |
123 | 123 | ||
124 | void user_enable_single_step(struct task_struct *child) | ||
125 | { | ||
126 | struct pt_regs *regs = child->thread.uregs; | ||
127 | |||
128 | regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ | ||
129 | } | ||
130 | |||
131 | void user_disable_single_step(struct task_struct *child) | ||
132 | { | ||
133 | regs->sr &= ~SR_SSTEP; | ||
134 | } | ||
124 | 135 | ||
125 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 136 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
126 | { | 137 | { |
127 | int ret; | 138 | int ret; |
128 | 139 | ||
129 | switch (request) { | 140 | switch (request) { |
130 | /* when I and D space are separate, these will need to be fixed. */ | ||
131 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | ||
132 | case PTRACE_PEEKDATA: | ||
133 | ret = generic_ptrace_peekdata(child, addr, data); | ||
134 | break; | ||
135 | |||
136 | /* read the word at location addr in the USER area. */ | 141 | /* read the word at location addr in the USER area. */ |
137 | case PTRACE_PEEKUSR: { | 142 | case PTRACE_PEEKUSR: { |
138 | unsigned long tmp; | 143 | unsigned long tmp; |
@@ -155,12 +160,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
155 | break; | 160 | break; |
156 | } | 161 | } |
157 | 162 | ||
158 | /* when I and D space are separate, this will have to be fixed. */ | ||
159 | case PTRACE_POKETEXT: /* write the word at location addr. */ | ||
160 | case PTRACE_POKEDATA: | ||
161 | ret = generic_ptrace_pokedata(child, addr, data); | ||
162 | break; | ||
163 | |||
164 | case PTRACE_POKEUSR: | 163 | case PTRACE_POKEUSR: |
165 | /* write the word at location addr in the USER area. We must | 164 | /* write the word at location addr in the USER area. We must |
166 | disallow any changes to certain SR bits or u_fpvalid, since | 165 | disallow any changes to certain SR bits or u_fpvalid, since |
@@ -192,58 +191,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
192 | } | 191 | } |
193 | break; | 192 | break; |
194 | 193 | ||
195 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | ||
196 | case PTRACE_CONT: { /* restart after signal. */ | ||
197 | ret = -EIO; | ||
198 | if (!valid_signal(data)) | ||
199 | break; | ||
200 | if (request == PTRACE_SYSCALL) | ||
201 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
202 | else | ||
203 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
204 | child->exit_code = data; | ||
205 | wake_up_process(child); | ||
206 | ret = 0; | ||
207 | break; | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * make the child exit. Best I can do is send it a sigkill. | ||
212 | * perhaps it should be put in the status that it wants to | ||
213 | * exit. | ||
214 | */ | ||
215 | case PTRACE_KILL: { | ||
216 | ret = 0; | ||
217 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
218 | break; | ||
219 | child->exit_code = SIGKILL; | ||
220 | wake_up_process(child); | ||
221 | break; | ||
222 | } | ||
223 | |||
224 | case PTRACE_SINGLESTEP: { /* set the trap flag. */ | ||
225 | struct pt_regs *regs; | ||
226 | |||
227 | ret = -EIO; | ||
228 | if (!valid_signal(data)) | ||
229 | break; | ||
230 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
231 | if ((child->ptrace & PT_DTRACE) == 0) { | ||
232 | /* Spurious delayed TF traps may occur */ | ||
233 | child->ptrace |= PT_DTRACE; | ||
234 | } | ||
235 | |||
236 | regs = child->thread.uregs; | ||
237 | |||
238 | regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ | ||
239 | |||
240 | child->exit_code = data; | ||
241 | /* give it a chance to run. */ | ||
242 | wake_up_process(child); | ||
243 | ret = 0; | ||
244 | break; | ||
245 | } | ||
246 | |||
247 | default: | 194 | default: |
248 | ret = ptrace_request(child, request, addr, data); | 195 | ret = ptrace_request(child, request, addr, data); |
249 | break; | 196 | break; |
@@ -341,5 +288,5 @@ asmlinkage void do_software_break_point(unsigned long long vec, | |||
341 | */ | 288 | */ |
342 | void ptrace_disable(struct task_struct *child) | 289 | void ptrace_disable(struct task_struct *child) |
343 | { | 290 | { |
344 | /* nothing to do.. */ | 291 | user_disable_single_step(child); |
345 | } | 292 | } |