diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index d8144f2c..61385b53 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -391,7 +391,7 @@ void set_single_step(struct process *proc) extern void coredump(struct process *proc, void *regs); -static void ptrace_report_signal(struct process *proc, struct x86_regs *regs, int sig) +void ptrace_report_signal(struct process *proc, int sig) { long rc; @@ -401,6 +401,7 @@ static void ptrace_report_signal(struct process *proc, struct x86_regs *regs, in proc->ftn->exit_status = sig; /* Transition process state */ proc->ftn->status = PS_TRACED; + proc->ftn->ptrace &= ~PT_TRACE_SYSCALL_MASK; ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock); if (proc->ftn->parent) { /* kill SIGCHLD */ @@ -525,7 +526,7 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin case SIGTTIN: case SIGTTOU: if(ptraceflag){ - ptrace_report_signal(proc, regs, orgsig); + ptrace_report_signal(proc, orgsig); } else{ dkprintf("do_signal,SIGSTOP,changing state\n"); diff --git a/kernel/include/process.h b/kernel/include/process.h index a2816e73..fa294771 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -62,6 +62,9 @@ #define PT_TRACED 0x80 /* The process is ptraced */ #define PT_TRACE_EXEC 0x100 /* Trace execve(2) */ +#define PT_TRACE_SYSCALL_ENTER 0x200 /* Trace syscall enter */ +#define PT_TRACE_SYSCALL_EXIT 0x400 /* Trace syscall exit */ +#define PT_TRACE_SYSCALL_MASK (PT_TRACE_SYSCALL_ENTER | PT_TRACE_SYSCALL_EXIT) #define PTRACE_TRACEME 0 #define PTRACE_PEEKTEXT 1 diff --git a/kernel/process.c b/kernel/process.c index d16e8a33..35aa6a68 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -387,7 +387,6 @@ int ptrace_traceme(void){ } clear_single_step(proc); - /* TODO: other flags may reset */ out: dkprintf("ptrace_traceme,returning,error=%d\n", error); diff --git a/kernel/syscall.c b/kernel/syscall.c index 1acf3b1d..72befdd3 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1433,53 +1433,42 @@ SYSCALL_DECLARE(arch_prctl) ihk_mc_syscall_arg1(ctx)); } +extern void ptrace_report_signal(struct process *proc, int sig); static int ptrace_report_exec(struct process *proc) { - dkprintf("ptrace_report_exec,enter\n"); - int error = 0; - long rc; - struct siginfo info; + int ptrace = proc->ftn->ptrace; - if (!(proc->ftn->ptrace & (PT_TRACE_EXEC|PTRACE_O_TRACEEXEC))) { - goto out; + if (ptrace & (PT_TRACE_EXEC|PTRACE_O_TRACEEXEC)) { + int sig = (SIGTRAP | (PTRACE_EVENT_EXEC << 8)); + ptrace_report_signal(proc, sig); } + return 0; +} - /* Save reason why stopped and process state for wait4() to reap */ - ihk_mc_spinlock_lock_noirq(&proc->ftn->lock); - proc->ftn->exit_status = (SIGTRAP | (PTRACE_EVENT_EXEC << 8)); - /* Transition process state */ - proc->ftn->status = PS_TRACED; - ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock); - dkprintf("ptrace_report_exec,kill SIGCHLD\n"); - if (proc->ftn->parent) { - /* kill SIGCHLD */ - ihk_mc_spinlock_lock_noirq(&proc->ftn->parent->lock); - if (proc->ftn->parent->owner) { - memset(&info, '\0', sizeof info); - info.si_signo = SIGCHLD; - info.si_code = CLD_TRAPPED; - info._sifields._sigchld.si_pid = proc->ftn->pid; - info._sifields._sigchld.si_status = proc->ftn->exit_status; - rc = do_kill(proc->ftn->parent->pid, -1, SIGCHLD, &info, 0); - if(rc < 0) { - dkprintf("ptrace_report_exec,do_kill failed\n"); - } +static void ptrace_syscall_enter(struct process *proc) +{ + int ptrace = proc->ftn->ptrace; + + if (ptrace & PT_TRACE_SYSCALL_ENTER) { + int sig = (SIGTRAP | ((ptrace & PTRACE_O_TRACESYSGOOD) ? 0x80 : 0)); + ptrace_report_signal(proc, sig); + ihk_mc_spinlock_lock_noirq(&proc->ftn->lock); + if (proc->ftn->ptrace & PT_TRACE_SYSCALL_ENTER) { + proc->ftn->ptrace |= PT_TRACE_SYSCALL_EXIT; } - ihk_mc_spinlock_unlock_noirq(&proc->ftn->parent->lock); - - /* Wake parent (if sleeping in wait4()) */ - waitq_wakeup(&proc->ftn->parent->waitpid_q); + ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock); } +} - /* Sleep */ - dkprintf("ptrace_report_exec,sleeping\n"); - - schedule(); - dkprintf("ptrace_report_exec,woken up\n"); +static void ptrace_syscall_exit(struct process *proc) +{ + int ptrace = proc->ftn->ptrace; -out: - return error; + if (ptrace & PT_TRACE_SYSCALL_EXIT) { + int sig = (SIGTRAP | ((ptrace & PTRACE_O_TRACESYSGOOD) ? 0x80 : 0)); + ptrace_report_signal(proc, sig); + } } static int ptrace_check_clone_event(struct process *proc, int clone_flags) @@ -1522,6 +1511,7 @@ static int ptrace_report_clone(struct process *proc, struct process *new, int ev /* Transition process state */ proc->ftn->status = PS_TRACED; proc->ftn->ptrace_eventmsg = new->ftn->pid; + proc->ftn->ptrace &= ~PT_TRACE_SYSCALL_MASK; ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock); dkprintf("ptrace_report_clone,kill SIGCHLD\n"); @@ -2613,9 +2603,12 @@ static int ptrace_wakeup_sig(int pid, long request, long data) { if (request == PTRACE_SINGLESTEP) { set_single_step(child); } + ihk_mc_spinlock_lock_noirq(&child->ftn->lock); + child->ftn->ptrace &= ~PT_TRACE_SYSCALL_MASK; if (request == PTRACE_SYSCALL) { - /* TODO: may set PTRACE_SYSCALL flag */ + child->ftn->ptrace |= PT_TRACE_SYSCALL_ENTER; } + ihk_mc_spinlock_unlock_noirq(&child->ftn->lock); if(data != 0 && data != SIGSTOP) { struct process *proc; @@ -2908,8 +2901,7 @@ static int ptrace_attach(int pid) } } - proc->uctx->rflags &= ~RFLAGS_TF; /* SingleStep clear */ - /* TODO: other flags may reset */ + clear_single_step(proc); memset(&info, '\0', sizeof info); info.si_signo = SIGSTOP; @@ -2991,7 +2983,6 @@ found: } clear_single_step(proc); - /* TODO: other flags may clear */ if (data != 0) { memset(&info, '\0', sizeof info); @@ -3117,7 +3108,8 @@ SYSCALL_DECLARE(ptrace) dkprintf("ptrace: unimplemented ptrace(PTRACE_GETFPXREGS) called.\n"); break; case PTRACE_SYSCALL: - dkprintf("ptrace: unimplemented ptrace(PTRACE_SYSCALL) called.\n"); + dkprintf("ptrace: PTRACE_SYSCALL: data=%d\n", data); + error = ptrace_wakeup_sig(pid, request, data); break; case PTRACE_GETSIGINFO: dkprintf("ptrace: unimplemented ptrace(PTRACE_GETSIGINFO) called.\n"); @@ -4037,6 +4029,9 @@ long syscall(int num, ihk_mc_user_context_t *ctx) cpu_enable_interrupt(); + if (cpu_local_var(current)->ftn->ptrace) { + ptrace_syscall_enter(cpu_local_var(current)); + } #if 0 if(num != 24) // if not sched_yield @@ -4083,6 +4078,10 @@ long syscall(int num, ihk_mc_user_context_t *ctx) check_signal(l, NULL); check_need_resched(); + if (cpu_local_var(current)->ftn->ptrace) { + ptrace_syscall_exit(cpu_local_var(current)); + } + return l; }