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:

Reply via email to