Commit 290ba3aef58ff21c977585ff6b687e457f80bf54
Committed by
Linus Torvalds
1 parent
8313809ef3
Exists in
master
and in
7 other branches
cris arch-v32: use generic ptrace_resume code
Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT, PTRACE_KILL and PTRACE_SINGLESTEP. This implies defining arch_has_single_step in <asm/ptrace.h> and implementing the user_enable_single_step and user_disable_single_step functions, which also causes the breakpoint information to be cleared on fork, which could be considered a bug fix. Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL which it previously wasn't which is consistent with all architectures using the modern ptrace code. The way breakpoints are disabled is entirely inconsistent currently, I tried to make some sense of it, but I suspect all of the content of ptrace_disable should be moved into user_disable_single_step, this defintively needs some revisting as the current patch changes behaviour in not quite designed ways. Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Roland McGrath <roland@redhat.com> Cc: Mikael Starvik <starvik@axis.com> Cc: Jesper Nilsson <jesper.nilsson@axis.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 31 additions and 79 deletions Side-by-side Diff
arch/cris/arch-v32/kernel/ptrace.c
... | ... | @@ -78,6 +78,35 @@ |
78 | 78 | return 0; |
79 | 79 | } |
80 | 80 | |
81 | +void user_enable_single_step(struct task_struct *child) | |
82 | +{ | |
83 | + unsigned long tmp; | |
84 | + | |
85 | + /* | |
86 | + * Set up SPC if not set already (in which case we have no other | |
87 | + * choice but to trust it). | |
88 | + */ | |
89 | + if (!get_reg(child, PT_SPC)) { | |
90 | + /* In case we're stopped in a delay slot. */ | |
91 | + tmp = get_reg(child, PT_ERP) & ~1; | |
92 | + put_reg(child, PT_SPC, tmp); | |
93 | + } | |
94 | + tmp = get_reg(child, PT_CCS) | SBIT_USER; | |
95 | + put_reg(child, PT_CCS, tmp); | |
96 | +} | |
97 | + | |
98 | +void user_disable_single_step(struct task_struct *child) | |
99 | +{ | |
100 | + put_reg(child, PT_SPC, 0); | |
101 | + | |
102 | + if (!get_debugreg(child->pid, PT_BP_CTRL)) { | |
103 | + unsigned long tmp; | |
104 | + /* If no h/w bp configured, disable S bit. */ | |
105 | + tmp = get_reg(child, PT_CCS) & ~SBIT_USER; | |
106 | + put_reg(child, PT_CCS, tmp); | |
107 | + } | |
108 | +} | |
109 | + | |
81 | 110 | /* |
82 | 111 | * Called by kernel/ptrace.c when detaching. |
83 | 112 | * |
... | ... | @@ -89,8 +118,7 @@ |
89 | 118 | unsigned long tmp; |
90 | 119 | |
91 | 120 | /* Deconfigure SPC and S-bit. */ |
92 | - tmp = get_reg(child, PT_CCS) & ~SBIT_USER; | |
93 | - put_reg(child, PT_CCS, tmp); | |
121 | + user_disable_single_step(child); | |
94 | 122 | put_reg(child, PT_SPC, 0); |
95 | 123 | |
96 | 124 | /* Deconfigure any watchpoints associated with the child. */ |
... | ... | @@ -168,83 +196,6 @@ |
168 | 196 | break; |
169 | 197 | ret = 0; |
170 | 198 | break; |
171 | - | |
172 | - case PTRACE_SYSCALL: | |
173 | - case PTRACE_CONT: | |
174 | - ret = -EIO; | |
175 | - | |
176 | - if (!valid_signal(data)) | |
177 | - break; | |
178 | - | |
179 | - /* Continue means no single-step. */ | |
180 | - put_reg(child, PT_SPC, 0); | |
181 | - | |
182 | - if (!get_debugreg(child->pid, PT_BP_CTRL)) { | |
183 | - unsigned long tmp; | |
184 | - /* If no h/w bp configured, disable S bit. */ | |
185 | - tmp = get_reg(child, PT_CCS) & ~SBIT_USER; | |
186 | - put_reg(child, PT_CCS, tmp); | |
187 | - } | |
188 | - | |
189 | - if (request == PTRACE_SYSCALL) { | |
190 | - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | |
191 | - } | |
192 | - else { | |
193 | - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | |
194 | - } | |
195 | - | |
196 | - child->exit_code = data; | |
197 | - | |
198 | - /* TODO: make sure any pending breakpoint is killed */ | |
199 | - wake_up_process(child); | |
200 | - ret = 0; | |
201 | - | |
202 | - break; | |
203 | - | |
204 | - /* Make the child exit by sending it a sigkill. */ | |
205 | - case PTRACE_KILL: | |
206 | - ret = 0; | |
207 | - | |
208 | - if (child->exit_state == EXIT_ZOMBIE) | |
209 | - break; | |
210 | - | |
211 | - child->exit_code = SIGKILL; | |
212 | - | |
213 | - /* Deconfigure single-step and h/w bp. */ | |
214 | - ptrace_disable(child); | |
215 | - | |
216 | - /* TODO: make sure any pending breakpoint is killed */ | |
217 | - wake_up_process(child); | |
218 | - break; | |
219 | - | |
220 | - /* Set the trap flag. */ | |
221 | - case PTRACE_SINGLESTEP: { | |
222 | - unsigned long tmp; | |
223 | - ret = -EIO; | |
224 | - | |
225 | - /* Set up SPC if not set already (in which case we have | |
226 | - no other choice but to trust it). */ | |
227 | - if (!get_reg(child, PT_SPC)) { | |
228 | - /* In case we're stopped in a delay slot. */ | |
229 | - tmp = get_reg(child, PT_ERP) & ~1; | |
230 | - put_reg(child, PT_SPC, tmp); | |
231 | - } | |
232 | - tmp = get_reg(child, PT_CCS) | SBIT_USER; | |
233 | - put_reg(child, PT_CCS, tmp); | |
234 | - | |
235 | - if (!valid_signal(data)) | |
236 | - break; | |
237 | - | |
238 | - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | |
239 | - | |
240 | - /* TODO: set some clever breakpoint mechanism... */ | |
241 | - | |
242 | - child->exit_code = data; | |
243 | - wake_up_process(child); | |
244 | - ret = 0; | |
245 | - break; | |
246 | - | |
247 | - } | |
248 | 199 | |
249 | 200 | /* Get all GP registers from the child. */ |
250 | 201 | case PTRACE_GETREGS: { |
arch/cris/include/arch-v32/arch/ptrace.h
... | ... | @@ -108,6 +108,7 @@ |
108 | 108 | |
109 | 109 | #ifdef __KERNEL__ |
110 | 110 | |
111 | +#define arch_has_single_step() (1) | |
111 | 112 | #define user_mode(regs) (((regs)->ccs & (1 << (U_CCS_BITNR + CCS_SHIFT))) != 0) |
112 | 113 | #define instruction_pointer(regs) ((regs)->erp) |
113 | 114 | extern void show_regs(struct pt_regs *); |