Commit 290ba3aef58ff21c977585ff6b687e457f80bf54

Authored by Christoph Hellwig
Committed by Linus Torvalds
1 parent 8313809ef3

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 *);