From: Jeff Dike From: Bodo Stroesser This implements checking for the new ptrace option SYSEMU_SINGLESTEP (advanced sysemu) and allows the values 0,1,2 for /proc/sysemu, if advanced sysemu is available: 0 = don't use sysemu 1 = use sysemu, but don't use advanced sysemu 2 = use sysemu and advanced sysemu Signed-off-by: Bodo Stroesser Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton --- 25-akpm/arch/um/include/ptrace_user.h | 3 ++ 25-akpm/arch/um/include/sysdep-i386/ptrace.h | 3 ++ 25-akpm/arch/um/kernel/process.c | 38 +++++++++++++++++++++++++-- 25-akpm/arch/um/kernel/process_kern.c | 6 ++-- 4 files changed, 46 insertions(+), 4 deletions(-) diff -puN arch/um/include/ptrace_user.h~uml-detect-sysemu_singlestep arch/um/include/ptrace_user.h --- 25/arch/um/include/ptrace_user.h~uml-detect-sysemu_singlestep Fri Dec 3 13:50:42 2004 +++ 25-akpm/arch/um/include/ptrace_user.h Fri Dec 3 13:50:42 2004 @@ -21,6 +21,9 @@ extern void ptrace_pokeuser(unsigned lon #ifndef PTRACE_SYSEMU #define PTRACE_SYSEMU 31 #endif +#ifndef PTRACE_SYSEMU_SINGLESTEP +#define PTRACE_SYSEMU_SINGLESTEP 32 +#endif void set_using_sysemu(int value); int get_using_sysemu(void); diff -puN arch/um/include/sysdep-i386/ptrace.h~uml-detect-sysemu_singlestep arch/um/include/sysdep-i386/ptrace.h --- 25/arch/um/include/sysdep-i386/ptrace.h~uml-detect-sysemu_singlestep Fri Dec 3 13:50:42 2004 +++ 25-akpm/arch/um/include/sysdep-i386/ptrace.h Fri Dec 3 13:50:42 2004 @@ -15,6 +15,9 @@ #ifdef UML_CONFIG_MODE_SKAS #include "ptrace-skas.h" #endif +#ifndef PTRACE_SYSEMU_SINGLESTEP +#define PTRACE_SYSEMU_SINGLESTEP 32 +#endif #include "choose-mode.h" diff -puN arch/um/kernel/process.c~uml-detect-sysemu_singlestep arch/um/kernel/process.c --- 25/arch/um/kernel/process.c~uml-detect-sysemu_singlestep Fri Dec 3 13:50:42 2004 +++ 25-akpm/arch/um/kernel/process.c Fri Dec 3 13:50:42 2004 @@ -241,7 +241,7 @@ __uml_setup("nosysemu", nosysemu_cmd_par static void __init check_sysemu(void) { void *stack; - int pid, n, status; + int pid, syscall, n, status, count=0; printk("Checking syscall emulation patch for ptrace..."); sysemu_supported = 0; @@ -269,12 +269,46 @@ static void __init check_sysemu(void) sysemu_supported = 1; printk("OK\n"); set_using_sysemu(!force_sysemu_disabled); + + printk("Checking advanced syscall emulation patch for ptrace..."); + pid = start_ptraced_child(&stack); + while(1){ + count++; + if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0) + goto fail; + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); + if(n < 0) + panic("check_ptrace : wait failed, errno = %d", errno); + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) + panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), " + "got status = %d", status); + + syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, + 0); + if(syscall == __NR_getpid){ + if (!count) + panic("check_ptrace : SYSEMU_SINGLESTEP doesn't singlestep"); + n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, + os_getpid()); + if(n < 0) + panic("check_sysemu : failed to modify system " + "call return, errno = %d", errno); + break; + } + } + if (stop_ptraced_child(pid, stack, 0, 0) < 0) + goto fail_stopped; + + sysemu_supported = 2; + printk("OK\n"); + + if ( !force_sysemu_disabled ) + set_using_sysemu(sysemu_supported); return; fail: stop_ptraced_child(pid, stack, 1, 0); fail_stopped: - sysemu_supported = 0; printk("missing\n"); } diff -puN arch/um/kernel/process_kern.c~uml-detect-sysemu_singlestep arch/um/kernel/process_kern.c --- 25/arch/um/kernel/process_kern.c~uml-detect-sysemu_singlestep Fri Dec 3 13:50:42 2004 +++ 25-akpm/arch/um/kernel/process_kern.c Fri Dec 3 13:50:42 2004 @@ -404,7 +404,9 @@ int sysemu_supported; void set_using_sysemu(int value) { - atomic_set(&using_sysemu, sysemu_supported && value); + if (value > sysemu_supported) + return; + atomic_set(&using_sysemu, value); } int get_using_sysemu(void) @@ -427,7 +429,7 @@ static int proc_write_sysemu(struct file if (copy_from_user(tmp, buf, 1)) return -EFAULT; - if (tmp[0] == '0' || tmp[0] == '1') + if (tmp[0] >= '0' && tmp[0] <= '2') set_using_sysemu(tmp[0] - '0'); return count; /*We use the first char, but pretend to write everything*/ } _