From: Bodo Stroesser This patch is based on 2.6.9-vanilla + host-skas3-2.6.9-v7.patch + patch-2.6.9-skas-v7-reorganize It implements the new ptrace option PTRACE_SYSEMU_SINGLESTEP this new option can be used by UML to singlestep a process. Then it will receive the common syscall interceptions plus a singlestep trap for each non syscall instruction. Signed-off-by: Bodo Stroesser Signed-off-by: Paolo 'Blaisorblade' Giarrusso --- clean-linux-2.6.11-paolo/arch/i386/kernel/ptrace.c | 27 ++++++++++++++------- clean-linux-2.6.11-paolo/include/linux/ptrace.h | 1 2 files changed, 20 insertions(+), 8 deletions(-) diff -puN arch/i386/kernel/ptrace.c~sysemu-add-SYSEMU_SINGLESTEP arch/i386/kernel/ptrace.c --- clean-linux-2.6.11/arch/i386/kernel/ptrace.c~sysemu-add-SYSEMU_SINGLESTEP 2005-07-10 16:55:38.000000000 +0200 +++ clean-linux-2.6.11-paolo/arch/i386/kernel/ptrace.c 2005-07-10 16:57:36.000000000 +0200 @@ -517,12 +517,10 @@ asmlinkage int sys_ptrace(long request, if (request == PTRACE_SYSEMU) { set_tsk_thread_flag(child, TIF_SYSCALL_EMU); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - } - else if (request == PTRACE_SYSCALL) { + } else if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); - } - else { + } else { clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); } @@ -548,11 +546,17 @@ asmlinkage int sys_ptrace(long request, wake_up_process(child); break; + case PTRACE_SYSEMU_SINGLESTEP: /* Same as SYSEMU, but singlestep if not syscall */ case PTRACE_SINGLESTEP: /* set the trap flag. */ ret = -EIO; if ((unsigned long) data > _NSIG) break; - clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + + if (request == PTRACE_SYSEMU_SINGLESTEP) + set_tsk_thread_flag(child, TIF_SYSCALL_EMU); + else + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_singlestep(child); child->exit_code = data; @@ -739,7 +743,10 @@ void send_sigtrap(struct task_struct *ts __attribute__((regparm(3))) int do_syscall_trace(struct pt_regs *regs, int entryexit) { - int is_sysemu, is_singlestep; + int is_sysemu = test_thread_flag(TIF_SYSCALL_EMU); + /* With TIF_SYSCALL_EMU set we want to ignore TIF_SINGLESTEP */ + int is_singlestep = !is_sysemu && test_thread_flag(TIF_SINGLESTEP); + if (unlikely(current->audit_context)) { if (!entryexit) audit_syscall_entry(current, regs->orig_eax, @@ -751,8 +758,11 @@ int do_syscall_trace(struct pt_regs *reg if (!(current->ptrace & PT_PTRACED)) return 0; - is_sysemu = test_thread_flag(TIF_SYSCALL_EMU); - is_singlestep = test_thread_flag(TIF_SINGLESTEP); + /* If a process stops on the 1st tracepoint with SYSCALL_TRACE + * and then is resumed with SYSEMU_SINGLESTEP, it will come in + * here. We have to check this and return */ + if (is_sysemu && entryexit) + return 0; /* Fake a debug trap */ if (is_singlestep) @@ -779,6 +789,7 @@ int do_syscall_trace(struct pt_regs *reg if ( !is_sysemu ) return 0; + regs->orig_eax = -1; /* force skip of syscall restarting */ if (unlikely(current->audit_context)) audit_syscall_exit(current, regs->eax); return 1; diff -puN include/linux/ptrace.h~sysemu-add-SYSEMU_SINGLESTEP include/linux/ptrace.h --- clean-linux-2.6.11/include/linux/ptrace.h~sysemu-add-SYSEMU_SINGLESTEP 2005-07-10 16:55:38.000000000 +0200 +++ clean-linux-2.6.11-paolo/include/linux/ptrace.h 2005-07-10 16:55:38.000000000 +0200 @@ -21,6 +21,7 @@ #define PTRACE_SYSCALL 24 #define PTRACE_SYSEMU 31 +#define PTRACE_SYSEMU_SINGLESTEP 32 /* 0x4200-0x4300 are reserved for architecture-independent additions. */ #define PTRACE_SETOPTIONS 0x4200 _