Something like this? This patch:
- adds ptrace_context->sysemu boolean. (it will die) - changes ptrace_resume() so that SYSEMU/SYSEMU_SINGLESTEP set context ->sysemu, and require only SYSCALL_ENTRY event, not UTRACE_EVENT_SYSCALL which includes SYSCALL_EXIT as well. Afaics, this should handle PTRACE_SYSEMU correctly. But PTRACE_SYSEMU_SINGLESTEP case is not exactly right, it always sets action = UTRACE_SINGLESTEP. Looks like, it should be UTRACE_RESUME if the tracee has stopped somewhere after SYSCALL_ENTRY was reported. Will continue tomorrow. --- kernel/ptrace.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) --- PU/kernel/ptrace.c~104_PTRACE_SYSEMU 2009-10-18 19:56:28.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-19 18:46:50.000000000 +0200 @@ -25,7 +25,9 @@ #include <linux/uaccess.h> struct ptrace_context { - int options; + int options; + + bool sysemu; // XXX: will die soon int signr; siginfo_t *siginfo; @@ -250,6 +252,8 @@ static u32 ptrace_report_syscall_entry(u set_syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); + if (unlikely(context->sysemu)) + return UTRACE_SYSCALL_ABORT | UTRACE_STOP; return UTRACE_SYSCALL_RUN | UTRACE_STOP; } @@ -1012,16 +1016,16 @@ static void do_ptrace_resume(struct utra static int ptrace_resume(struct utrace_engine *engine, struct task_struct *tracee, long request, long data) { + struct ptrace_context *context = ptrace_context(engine); enum utrace_resume_action action; - enum utrace_syscall_action syscall; unsigned long events; if (!valid_signal(data)) return -EIO; - syscall = UTRACE_SYSCALL_RUN; - events = engine->flags & ~UTRACE_EVENT_SYSCALL; - action = UTRACE_RESUME; + context->sysemu = false; + events = engine->flags & ~UTRACE_EVENT_SYSCALL; + action = UTRACE_RESUME; switch (request) { #ifdef PTRACE_SINGLEBLOCK @@ -1046,8 +1050,9 @@ static int ptrace_resume(struct utrace_e return -EIO; action = UTRACE_SINGLESTEP; case PTRACE_SYSEMU: - syscall = UTRACE_SYSCALL_ABORT; - /* fallthrough */ + context->sysemu = true; + events |= UTRACE_EVENT(SYSCALL_ENTRY); + break; #endif case PTRACE_SYSCALL: