Change ptrace_resume() path to pass the correct "action" argument to utrace_control(), the current code always uses UTRACE_RESUME while PTRACE_SINGLEXXX needs UTRACE_XXXSTEP.
Introduce ptrace_context->resume to remember this action, we have to re-assert it from report_quiesce/report_signal callbacks. The next patch changes ptrace_report_signal(UTRACE_SIGNAL_HANDLER). --- kernel/ptrace.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) --- PU/kernel/ptrace.c~51_STEP_SIMPLE 2009-09-17 21:03:11.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-23 00:50:28.000000000 +0200 @@ -25,7 +25,7 @@ #include <linux/uaccess.h> typedef void (*resume_func_t)(struct utrace_engine *, - struct task_struct*, long); + struct task_struct*, long); struct ptrace_event { int ev_code; @@ -42,6 +42,8 @@ struct ptrace_context { struct ptrace_event ev_array[2]; unsigned int ev_first, ev_last; + + enum utrace_resume_action resume; }; static inline bool ev_empty(struct ptrace_context *context) @@ -348,6 +350,7 @@ static u32 ptrace_report_signal(u32 acti struct k_sigaction *return_ka) { struct ptrace_context *context = ptrace_context(engine); + enum utrace_resume_action resume = context->resume; struct ptrace_event *ev; if (!ev_empty(context)) { @@ -362,27 +365,27 @@ static u32 ptrace_report_signal(u32 acti WARN_ON(1); case UTRACE_SIGNAL_REPORT: if (!context->siginfo) - return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + return resume | UTRACE_SIGNAL_IGN; if (WARN_ON(context->siginfo != info)) - return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + return resume | UTRACE_SIGNAL_IGN; context->siginfo = NULL; if (!info->si_signo) // debugger cancelled sig - return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + return resume | UTRACE_SIGNAL_IGN; /* * If the (new) signal is now blocked, requeue it. */ if (sigismember(&task->blocked, info->si_signo)) { send_sig_info(info->si_signo, info, task); - return UTRACE_RESUME | UTRACE_SIGNAL_IGN; + return resume | UTRACE_SIGNAL_IGN; } spin_lock_irq(&task->sighand->siglock); *return_ka = task->sighand->action[info->si_signo - 1]; spin_unlock_irq(&task->sighand->siglock); - return UTRACE_RESUME | UTRACE_SIGNAL_DELIVER; + return resume | UTRACE_SIGNAL_DELIVER; default: WARN_ON(context->siginfo); @@ -411,7 +414,7 @@ static u32 ptrace_report_quiesce(u32 act return UTRACE_STOP; } - return UTRACE_RESUME; + return event ? UTRACE_RESUME : context->resume; } static void ptrace_release(void *data) @@ -463,6 +466,8 @@ static int ptrace_attach_task(struct tas if (unlikely(!context)) return -ENOMEM; + context->resume = UTRACE_RESUME; + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, @@ -924,6 +929,7 @@ static void ptrace_wake_up(struct utrace static void do_ptrace_resume(struct utrace_engine *engine, struct task_struct *tracee, + enum utrace_resume_action action, long request, long data) { struct ptrace_context *context = ptrace_context(engine); @@ -950,7 +956,8 @@ static void do_ptrace_resume(struct utra } } - ptrace_wake_up(engine, tracee, UTRACE_RESUME); + context->resume = action; + ptrace_wake_up(engine, tracee, action); } static int ptrace_resume(struct utrace_engine *engine, @@ -992,7 +999,7 @@ static int ptrace_resume(struct utrace_e } if (!ret) - do_ptrace_resume(engine, child, request, data); + do_ptrace_resume(engine, child, action, request, data); return ret; }