X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fum%2Fkernel%2Ftt%2Ftracer.c;h=257a16e84da5bd3029e750c5d7b7b9229d71c173;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=deef43bb558d4ab5f9af1c2b3abf4c9acc96e9af;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index deef43bb5..257a16e84 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include "user.h" @@ -25,7 +26,6 @@ #include "mem_user.h" #include "process.h" #include "kern_util.h" -#include "frame.h" #include "chan_user.h" #include "ptrace_user.h" #include "mode.h" @@ -72,6 +72,8 @@ void attach_process(int pid) (ptrace(PTRACE_CONT, pid, 0, 0) < 0)) tracer_panic("OP_FORK failed to attach pid"); wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); + if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) + tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno); if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) tracer_panic("OP_FORK failed to continue process"); } @@ -82,6 +84,7 @@ void tracer_panic(char *format, ...) va_start(ap, format); vprintf(format, ap); + va_end(ap); printf("\n"); while(1) pause(); } @@ -141,7 +144,7 @@ static void sleeping_process_signal(int pid, int sig) * any more, the trace of those will land here. So, we need to just * PTRACE_SYSCALL it. */ - case SIGTRAP: + case (SIGTRAP + 0x80): if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) tracer_panic("sleeping_process_signal : Failed to " "PTRACE_SYSCALL pid %d, errno = %d\n", @@ -184,8 +187,8 @@ int tracer(int (*init_proc)(void *), void *sp) unsigned long eip = 0; int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0; + int local_using_sysemu = 0; - capture_signal_stack(); signal(SIGPIPE, SIG_IGN); setup_tracer_winch(); tracing_pid = os_getpid(); @@ -197,6 +200,10 @@ int tracer(int (*init_proc)(void *), void *sp) printf("waitpid on idle thread failed, errno = %d\n", errno); exit(1); } + if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) { + printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno); + exit(1); + } if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ printf("Failed to continue idle thread, errno = %d\n", errno); exit(1); @@ -297,11 +304,24 @@ int tracer(int (*init_proc)(void *), void *sp) tracing = is_tracing(task); old_tracing = tracing; + /* Assume: no syscall, when coming from user */ + if ( tracing ) + do_sigtrap(task); + switch(sig){ case SIGUSR1: sig = 0; op = do_proc_op(task, proc_id); switch(op){ + /* + * This is called when entering user mode; after + * this, we start intercepting syscalls. + * + * In fact, a process is started in kernel mode, + * so with is_tracing() == 0 (and that is reset + * when executing syscalls, since UML kernel has + * the right to do syscalls); + */ case OP_TRACE_ON: arch_leave_kernel(task, pid); tracing = 1; @@ -310,7 +330,13 @@ int tracer(int (*init_proc)(void *), void *sp) case OP_HALT: unmap_physmem(); kmalloc_ok = 0; - ptrace(PTRACE_KILL, pid, 0, 0); + os_kill_ptraced_process(pid, 0); + /* Now let's reap remaining zombies */ + errno = 0; + do { + waitpid(-1, &status, + WUNTRACED); + } while (errno != ECHILD); return(op == OP_REBOOT); case OP_NONE: printf("Detaching pid %d\n", pid); @@ -324,15 +350,26 @@ int tracer(int (*init_proc)(void *), void *sp) */ pid = cpu_tasks[proc_id].pid; break; + case (SIGTRAP + 0x80): + if(!tracing && (debugger_pid != -1)){ + child_signal(pid, status & 0x7fff); + continue; + } + tracing = 0; + /* local_using_sysemu has been already set + * below, since if we are here, is_tracing() on + * the traced task was 1, i.e. the process had + * already run through one iteration of the + * loop which executed a OP_TRACE_ON request.*/ + do_syscall(task, pid, local_using_sysemu); + sig = SIGUSR2; + break; case SIGTRAP: if(!tracing && (debugger_pid != -1)){ child_signal(pid, status); continue; } tracing = 0; - if(do_syscall(task, pid)) - sig = SIGUSR2; - else clear_singlestep(task); break; case SIGPROF: if(tracing) sig = 0; @@ -349,6 +386,7 @@ int tracer(int (*init_proc)(void *), void *sp) case SIGBUS: case SIGILL: case SIGWINCH: + default: tracing = 0; break; @@ -367,16 +405,15 @@ int tracer(int (*init_proc)(void *), void *sp) continue; } - if(tracing){ - if(singlestepping_tt(task)) - cont_type = PTRACE_SINGLESTEP; - else cont_type = PTRACE_SYSCALL; - } - else cont_type = PTRACE_CONT; + local_using_sysemu = get_using_sysemu(); - if((cont_type == PTRACE_CONT) && - (debugger_pid != -1) && strace) + if(tracing) + cont_type = SELECT_PTRACE_OPERATION(local_using_sysemu, + singlestepping(task)); + else if((debugger_pid != -1) && strace) cont_type = PTRACE_SYSCALL; + else + cont_type = PTRACE_CONT; if(ptrace(cont_type, pid, 0, sig) != 0){ tracer_panic("ptrace failed to continue "