aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/ptrace_32.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2008-07-30 06:09:31 -0400
committerPaul Mundt <lethal@linux-sh.org>2008-08-01 15:39:33 -0400
commitc459dbf294b4a3d70490a468a7ca3907fb2c2f57 (patch)
treec78866944d8e03247b6d5072987cd7f7c558caef /arch/sh/kernel/ptrace_32.c
parentc4637d475170ca0d99973efd07df727012db6cd1 (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_32.c')
-rw-r--r--arch/sh/kernel/ptrace_32.c93
1 files changed, 18 insertions, 75 deletions
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index e9bd4b2aa9c..ff66f97c564 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -58,7 +58,23 @@ static inline int put_stack_long(struct task_struct *task, int offset,
58 return 0; 58 return 0;
59} 59}
60 60
61static void ptrace_disable_singlestep(struct task_struct *child) 61void user_enable_single_step(struct task_struct *child)
62{
63 struct pt_regs *regs = task_pt_regs(child);
64 long pc;
65
66 pc = get_stack_long(child, (long)&regs->pc);
67
68 /* Next scheduling will set up UBC */
69 if (child->thread.ubc_pc == 0)
70 ubc_usercnt += 1;
71
72 child->thread.ubc_pc = pc;
73
74 set_tsk_thread_flag(child, TIF_SINGLESTEP);
75}
76
77void user_disable_single_step(struct task_struct *child)
62{ 78{
63 clear_tsk_thread_flag(child, TIF_SINGLESTEP); 79 clear_tsk_thread_flag(child, TIF_SINGLESTEP);
64 80
@@ -82,7 +98,7 @@ static void ptrace_disable_singlestep(struct task_struct *child)
82 */ 98 */
83void ptrace_disable(struct task_struct *child) 99void ptrace_disable(struct task_struct *child)
84{ 100{
85 ptrace_disable_singlestep(child); 101 user_disable_single_step(child);
86} 102}
87 103
88long arch_ptrace(struct task_struct *child, long request, long addr, long data) 104long arch_ptrace(struct task_struct *child, long request, long addr, long data)
@@ -91,12 +107,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
91 int ret; 107 int ret;
92 108
93 switch (request) { 109 switch (request) {
94 /* when I and D space are separate, these will need to be fixed. */
95 case PTRACE_PEEKTEXT: /* read word at location addr. */
96 case PTRACE_PEEKDATA:
97 ret = generic_ptrace_peekdata(child, addr, data);
98 break;
99
100 /* read the word at location addr in the USER area. */ 110 /* read the word at location addr in the USER area. */
101 case PTRACE_PEEKUSR: { 111 case PTRACE_PEEKUSR: {
102 unsigned long tmp; 112 unsigned long tmp;
@@ -126,12 +136,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
126 break; 136 break;
127 } 137 }
128 138
129 /* when I and D space are separate, this will have to be fixed. */
130 case PTRACE_POKETEXT: /* write the word at location addr. */
131 case PTRACE_POKEDATA:
132 ret = generic_ptrace_pokedata(child, addr, data);
133 break;
134
135 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ 139 case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
136 ret = -EIO; 140 ret = -EIO;
137 if ((addr & 3) || addr < 0 || 141 if ((addr & 3) || addr < 0 ||
@@ -152,67 +156,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
152 } 156 }
153 break; 157 break;
154 158
155 case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
156 case PTRACE_CONT: { /* restart after signal. */
157 ret = -EIO;
158 if (!valid_signal(data))
159 break;
160 if (request == PTRACE_SYSCALL)
161 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
162 else
163 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
164
165 ptrace_disable_singlestep(child);
166
167 child->exit_code = data;
168 wake_up_process(child);
169 ret = 0;
170 break;
171 }
172
173/*
174 * make the child exit. Best I can do is send it a sigkill.
175 * perhaps it should be put in the status that it wants to
176 * exit.
177 */
178 case PTRACE_KILL: {
179 ret = 0;
180 if (child->exit_state == EXIT_ZOMBIE) /* already dead */
181 break;
182 ptrace_disable_singlestep(child);
183 child->exit_code = SIGKILL;
184 wake_up_process(child);
185 break;
186 }
187
188 case PTRACE_SINGLESTEP: { /* set the trap flag. */
189 long pc;
190 struct pt_regs *regs = NULL;
191
192 ret = -EIO;
193 if (!valid_signal(data))
194 break;
195 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
196 if ((child->ptrace & PT_DTRACE) == 0) {
197 /* Spurious delayed TF traps may occur */
198 child->ptrace |= PT_DTRACE;
199 }
200
201 pc = get_stack_long(child, (long)&regs->pc);
202
203 /* Next scheduling will set up UBC */
204 if (child->thread.ubc_pc == 0)
205 ubc_usercnt += 1;
206 child->thread.ubc_pc = pc;
207
208 set_tsk_thread_flag(child, TIF_SINGLESTEP);
209 child->exit_code = data;
210 /* give it a chance to run. */
211 wake_up_process(child);
212 ret = 0;
213 break;
214 }
215
216#ifdef CONFIG_SH_DSP 159#ifdef CONFIG_SH_DSP
217 case PTRACE_GETDSPREGS: { 160 case PTRACE_GETDSPREGS: {
218 unsigned long dp; 161 unsigned long dp;