Consolidate multiple switch statements in do_ptrace_resume(). No functional changes, except in PTRACE_EVENT_SYSCALL_EXIT case ptrace(SINGLESTEP, signr)->ptrace_resume() first does send_sigtrap() then send_sig_info(signr). Hopefully this is OK, and we should move this sigtrap logic into the tracee's context anyway.
To simplify the review: 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); switch (get_stop_event(context)) { case PTRACE_EVENT_VFORK: if (context->options & PTRACE_O_TRACEVFORKDONE) { set_stop_code(context, PTRACE_EVENT_VFORK_DONE); utrace_control(tracee, engine, UTRACE_REPORT); return; } break; case PTRACE_EVENT_EXEC: case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: if (request == PTRACE_SYSCALL) { set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); do_ptrace_notify_stop(context, tracee); return; } /* fallthrough, but suppress send_sig_info() below */ data = 0; case PTRACE_EVENT_SYSCALL_EXIT: if (action != UTRACE_RESUME) { read_lock(&tasklist_lock); if (tracee->sighand) send_sigtrap(tracee, task_pt_regs(tracee), 0, TRAP_BRKPT); read_unlock(&tasklist_lock); action = UTRACE_RESUME; } /* fallthrough */ case PTRACE_EVENT_SYSCALL_ENTRY: if (data) send_sig_info(data, SEND_SIG_PRIV, tracee); break; case PTRACE_EVENT_SIGNAL: context->signr = data; break; case 0: // XXX: JCTL stop break; } context->resume = action; ptrace_wake_up(tracee, engine, action, true); } --- kernel/ptrace.c | 53 +++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 30 deletions(-) --- PU/kernel/ptrace.c~100_RESUME_CONSOLIDATE_SWITCH 2009-10-17 19:50:54.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-18 16:51:38.000000000 +0200 @@ -972,10 +972,6 @@ static void do_ptrace_resume(struct utra struct ptrace_context *context = ptrace_context(engine); switch (get_stop_event(context)) { - case 0: - // XXX: JCTL stop - break; - case PTRACE_EVENT_VFORK: if (context->options & PTRACE_O_TRACEVFORKDONE) { set_stop_code(context, PTRACE_EVENT_VFORK_DONE); @@ -984,45 +980,41 @@ static void do_ptrace_resume(struct utra } break; - case PTRACE_EVENT_SYSCALL_ENTRY: - case PTRACE_EVENT_SYSCALL_EXIT: - if (data) - send_sig_info(data, SEND_SIG_PRIV, tracee); - break; - - case PTRACE_EVENT_SIGNAL: - context->signr = data; - break; - } - - if (request == PTRACE_SYSCALL) { - switch (get_stop_event(context)) { - case PTRACE_EVENT_EXEC: - case PTRACE_EVENT_FORK: - case PTRACE_EVENT_CLONE: - case PTRACE_EVENT_VFORK_DONE: + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: + if (request == PTRACE_SYSCALL) { set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); do_ptrace_notify_stop(context, tracee); return; } - } + /* fallthrough, but suppress send_sig_info() below */ + data = 0; - if (action != UTRACE_RESUME) { - switch (get_stop_event(context)) { - case PTRACE_EVENT_EXEC: - case PTRACE_EVENT_FORK: - case PTRACE_EVENT_CLONE: - case PTRACE_EVENT_VFORK_DONE: - case PTRACE_EVENT_SYSCALL_EXIT: + case PTRACE_EVENT_SYSCALL_EXIT: + if (action != UTRACE_RESUME) { read_lock(&tasklist_lock); if (tracee->sighand) send_sigtrap(tracee, task_pt_regs(tracee), 0, TRAP_BRKPT); read_unlock(&tasklist_lock); - action = UTRACE_RESUME; - break; } + /* fallthrough */ + + case PTRACE_EVENT_SYSCALL_ENTRY: + if (data) + send_sig_info(data, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + context->signr = data; + break; + + case 0: + // XXX: JCTL stop + break; } context->resume = action;