Index: lib/libc/sys/ptrace.2 =================================================================== --- lib/libc/sys/ptrace.2 +++ lib/libc/sys/ptrace.2 @@ -2,7 +2,7 @@ .\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $ .\" .\" This file is in the public domain. -.Dd August 29, 2016 +.Dd June 11, 2017 .Dt PTRACE 2 .Os .Sh NAME @@ -643,6 +643,26 @@ .Fa data arguments are used the same as for .Dv PT_CONTINUE. +.It Dv PT_GET_SC_ARGS +For the thread which is stopped in either +.Dv PL_FLAG_SCE +or +.Dv PL_FLAG_SCX +state, that is, on entry or exit to a syscall, +this request fetches the syscall arguments. +.Pp +The arguments are copied out into the buffer pointed to by the +.Fa addr +pointer, sequentially. +Each syscall argument is stored as the machine word. +Kernel copies out as many arguments as the syscall accepts, +see the +.Va pl_syscall_narg +member of the +.Vt struct ptrace_lwpinfo , +but not more than the +.Fa data +bytes in total are copied. .It Dv PT_FOLLOW_FORK This request controls tracing for new child processes of a traced process. If Index: sys/amd64/amd64/trap.c =================================================================== --- sys/amd64/amd64/trap.c +++ sys/amd64/amd64/trap.c @@ -829,16 +829,18 @@ } int -cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cpu_fetch_syscall_args(struct thread *td) { struct proc *p; struct trapframe *frame; register_t *argp; + struct syscall_args *sa; caddr_t params; int reg, regcnt, error; p = td->td_proc; frame = td->td_frame; + sa = &td->td_sa; reg = 0; regcnt = 6; @@ -889,7 +891,6 @@ void amd64_syscall(struct thread *td, int traced) { - struct syscall_args sa; int error; ksiginfo_t ksi; @@ -899,7 +900,7 @@ /* NOT REACHED */ } #endif - error = syscallenter(td, &sa); + error = syscallenter(td); /* * Traced syscall. @@ -915,15 +916,16 @@ KASSERT(PCB_USER_FPU(td->td_pcb), ("System call %s returning with kernel FPU ctx leaked", - syscallname(td->td_proc, sa.code))); + syscallname(td->td_proc, td->td_sa.code))); KASSERT(td->td_pcb->pcb_save == get_pcb_user_save_td(td), ("System call %s returning with mangled pcb_save", - syscallname(td->td_proc, sa.code))); + syscallname(td->td_proc, td->td_sa.code))); KASSERT(td->td_md.md_invl_gen.gen == 0, ("System call %s returning with leaked invl_gen %lu", - syscallname(td->td_proc, sa.code), td->td_md.md_invl_gen.gen)); + syscallname(td->td_proc, td->td_sa.code), + td->td_md.md_invl_gen.gen)); - syscallret(td, error, &sa); + syscallret(td, error); /* * If the user-supplied value of %rip is not a canonical Index: sys/amd64/cloudabi32/cloudabi32_sysvec.c =================================================================== --- sys/amd64/cloudabi32/cloudabi32_sysvec.c +++ sys/amd64/cloudabi32/cloudabi32_sysvec.c @@ -90,11 +90,15 @@ } static int -cloudabi32_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cloudabi32_fetch_syscall_args(struct thread *td) { - struct trapframe *frame = td->td_frame; + struct trapframe *frame; + struct syscall_args *sa; int error; + frame = td->td_frame; + sa = &td->td_sa; + /* Obtain system call number. */ sa->code = frame->tf_rax; if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL) Index: sys/amd64/cloudabi64/cloudabi64_sysvec.c =================================================================== --- sys/amd64/cloudabi64/cloudabi64_sysvec.c +++ sys/amd64/cloudabi64/cloudabi64_sysvec.c @@ -87,9 +87,13 @@ } static int -cloudabi64_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cloudabi64_fetch_syscall_args(struct thread *td) { - struct trapframe *frame = td->td_frame; + struct trapframe *frame; + struct syscall_args *sa; + + frame = td->td_frame; + sa = &td->td_sa; /* Obtain system call number. */ sa->code = frame->tf_rax; Index: sys/amd64/ia32/ia32_syscall.c =================================================================== --- sys/amd64/ia32/ia32_syscall.c +++ sys/amd64/ia32/ia32_syscall.c @@ -105,16 +105,18 @@ } int -ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +ia32_fetch_syscall_args(struct thread *td) { struct proc *p; struct trapframe *frame; + struct syscall_args *sa; caddr_t params; u_int32_t args[8], tmp; int error, i; p = td->td_proc; frame = td->td_frame; + sa = &td->td_sa; params = (caddr_t)frame->tf_rsp + sizeof(u_int32_t); sa->code = frame->tf_rax; @@ -175,7 +177,6 @@ ia32_syscall(struct trapframe *frame) { struct thread *td; - struct syscall_args sa; register_t orig_tf_rflags; int error; ksiginfo_t ksi; @@ -184,7 +185,7 @@ td = curthread; td->td_frame = frame; - error = syscallenter(td, &sa); + error = syscallenter(td); /* * Traced syscall. @@ -198,7 +199,7 @@ trapsignal(td, &ksi); } - syscallret(td, error, &sa); + syscallret(td, error); } static void Index: sys/amd64/include/proc.h =================================================================== --- sys/amd64/include/proc.h +++ sys/amd64/include/proc.h @@ -70,6 +70,13 @@ #define KINFO_PROC_SIZE 1088 #define KINFO_PROC32_SIZE 768 +struct syscall_args { + u_int code; + struct sysent *callp; + register_t args[8]; + int narg; +}; + #ifdef _KERNEL /* Get the current kernel thread stack usage. */ @@ -92,13 +99,6 @@ extern struct mtx dt_lock; extern int max_ldt_segment; - -struct syscall_args { - u_int code; - struct sysent *callp; - register_t args[8]; - int narg; -}; #endif /* _KERNEL */ #endif /* !_MACHINE_PROC_H_ */ Index: sys/amd64/linux/linux_sysvec.c =================================================================== --- sys/amd64/linux/linux_sysvec.c +++ sys/amd64/linux/linux_sysvec.c @@ -126,7 +126,7 @@ static void linux_vdso_install(void *param); static void linux_vdso_deinstall(void *param); static void linux_set_syscall_retval(struct thread *td, int error); -static int linux_fetch_syscall_args(struct thread *td, struct syscall_args *sa); +static int linux_fetch_syscall_args(struct thread *td); static void linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack); static int linux_vsyscall(struct thread *td); @@ -217,13 +217,15 @@ } static int -linux_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +linux_fetch_syscall_args(struct thread *td) { struct proc *p; struct trapframe *frame; + struct syscall_args *sa; p = td->td_proc; frame = td->td_frame; + sa = &td->td_sa; sa->args[0] = frame->tf_rdi; sa->args[1] = frame->tf_rsi; Index: sys/amd64/linux32/linux32_sysvec.c =================================================================== --- sys/amd64/linux32/linux32_sysvec.c +++ sys/amd64/linux32/linux32_sysvec.c @@ -725,13 +725,15 @@ } static int -linux32_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +linux32_fetch_syscall_args(struct thread *td) { struct proc *p; struct trapframe *frame; + struct syscall_args *sa; p = td->td_proc; frame = td->td_frame; + sa = &td->td_sa; sa->args[0] = frame->tf_rbx; sa->args[1] = frame->tf_rcx; Index: sys/arm/arm/syscall.c =================================================================== --- sys/arm/arm/syscall.c +++ sys/arm/arm/syscall.c @@ -99,12 +99,14 @@ void swi_handler(struct trapframe *); int -cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cpu_fetch_syscall_args(struct thread *td) { struct proc *p; register_t *ap; + struct syscall_args *sa; int error; + sa = &td->td_sa; sa->code = td->td_frame->tf_r7; ap = &td->td_frame->tf_r0; if (sa->code == SYS_syscall) { @@ -141,15 +143,14 @@ static void syscall(struct thread *td, struct trapframe *frame) { - struct syscall_args sa; int error; - sa.nap = 4; + td->td_sa.nap = 4; - error = syscallenter(td, &sa); + error = syscallenter(td); KASSERT(error != 0 || td->td_ar == NULL, ("returning from syscall with td_ar set!")); - syscallret(td, error, &sa); + syscallret(td, error); } void Index: sys/arm/cloudabi32/cloudabi32_sysvec.c =================================================================== --- sys/arm/cloudabi32/cloudabi32_sysvec.c +++ sys/arm/cloudabi32/cloudabi32_sysvec.c @@ -67,11 +67,15 @@ } static int -cloudabi32_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cloudabi32_fetch_syscall_args(struct thread *td) { - struct trapframe *frame = td->td_frame; + struct trapframe *frame; + struct syscall_args *sa; int error; + frame = td->td_frame; + sa = &td->td_sa; + /* Obtain system call number. */ sa->code = frame->tf_r12; if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL) Index: sys/arm64/arm64/trap.c =================================================================== --- sys/arm64/arm64/trap.c +++ sys/arm64/arm64/trap.c @@ -92,15 +92,17 @@ } int -cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cpu_fetch_syscall_args(struct thread *td) { struct proc *p; register_t *ap; + struct syscall_args *sa; int nap; nap = 8; p = td->td_proc; ap = td->td_frame->tf_x; + sa = &td->td_sa; sa->code = td->td_frame->tf_x[8]; @@ -132,12 +134,11 @@ static void svc_handler(struct thread *td, struct trapframe *frame) { - struct syscall_args sa; int error; if ((frame->tf_esr & ESR_ELx_ISS_MASK) == 0) { - error = syscallenter(td, &sa); - syscallret(td, error, &sa); + error = syscallenter(td); + syscallret(td, error); } else { call_trapsignal(td, SIGILL, ILL_ILLOPN, (void *)frame->tf_elr); userret(td, frame); Index: sys/arm64/cloudabi64/cloudabi64_sysvec.c =================================================================== --- sys/arm64/cloudabi64/cloudabi64_sysvec.c +++ sys/arm64/cloudabi64/cloudabi64_sysvec.c @@ -67,11 +67,15 @@ } static int -cloudabi64_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cloudabi64_fetch_syscall_args(struct thread *td) { - struct trapframe *frame = td->td_frame; + struct trapframe *frame; + struct syscall_args *sa; int i; + frame = td->td_frame; + sa = &td->td_sa; + /* Obtain system call number. */ sa->code = frame->tf_x[8]; if (sa->code >= CLOUDABI64_SYS_MAXSYSCALL) Index: sys/arm64/include/proc.h =================================================================== --- sys/arm64/include/proc.h +++ sys/arm64/include/proc.h @@ -45,8 +45,6 @@ #define KINFO_PROC_SIZE 1088 -#ifdef _KERNEL - #define MAXARGS 8 struct syscall_args { u_int code; @@ -55,6 +53,4 @@ int narg; }; -#endif - #endif /* !_MACHINE_PROC_H_ */ Index: sys/compat/ia32/ia32_util.h =================================================================== --- sys/compat/ia32/ia32_util.h +++ sys/compat/ia32/ia32_util.h @@ -50,7 +50,7 @@ #define IA32_MAXVMEM 0 /* Unlimited */ struct syscall_args; -int ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa); +int ia32_fetch_syscall_args(struct thread *td); void ia32_set_syscall_retval(struct thread *, int); void ia32_fixlimit(struct rlimit *rl, int which); Index: sys/i386/cloudabi32/cloudabi32_sysvec.c =================================================================== --- sys/i386/cloudabi32/cloudabi32_sysvec.c +++ sys/i386/cloudabi32/cloudabi32_sysvec.c @@ -85,11 +85,15 @@ } static int -cloudabi32_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cloudabi32_fetch_syscall_args(struct thread *td) { - struct trapframe *frame = td->td_frame; + struct trapframe *frame; + struct syscall_args *sa; int error; + frame = td->td_frame; + sa = &td->td_sa; + /* Obtain system call number. */ sa->code = frame->tf_eax; if (sa->code >= CLOUDABI32_SYS_MAXSYSCALL) Index: sys/i386/i386/trap.c =================================================================== --- sys/i386/i386/trap.c +++ sys/i386/i386/trap.c @@ -1012,16 +1012,18 @@ } int -cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cpu_fetch_syscall_args(struct thread *td) { struct proc *p; struct trapframe *frame; + struct syscall_args *sa; caddr_t params; long tmp; int error; p = td->td_proc; frame = td->td_frame; + sa = &td->td_sa; params = (caddr_t)frame->tf_esp + sizeof(int); sa->code = frame->tf_eax; @@ -1082,7 +1084,6 @@ syscall(struct trapframe *frame) { struct thread *td; - struct syscall_args sa; register_t orig_tf_eflags; int error; ksiginfo_t ksi; @@ -1099,7 +1100,7 @@ td = curthread; td->td_frame = frame; - error = syscallenter(td, &sa); + error = syscallenter(td); /* * Traced syscall. @@ -1115,10 +1116,10 @@ KASSERT(PCB_USER_FPU(td->td_pcb), ("System call %s returning with kernel FPU ctx leaked", - syscallname(td->td_proc, sa.code))); + syscallname(td->td_proc, td->td_sa.code))); KASSERT(td->td_pcb->pcb_save == get_pcb_user_save_td(td), ("System call %s returning with mangled pcb_save", - syscallname(td->td_proc, sa.code))); + syscallname(td->td_proc, td->td_sa.code))); - syscallret(td, error, &sa); + syscallret(td, error); } Index: sys/i386/include/proc.h =================================================================== --- sys/i386/include/proc.h +++ sys/i386/include/proc.h @@ -60,6 +60,13 @@ #define KINFO_PROC_SIZE 768 +struct syscall_args { + u_int code; + struct sysent *callp; + register_t args[8]; + int narg; +}; + #ifdef _KERNEL /* Get the current kernel thread stack usage. */ @@ -77,13 +84,6 @@ void user_ldt_deref(struct proc_ldt *pldt); extern struct mtx dt_lock; - -struct syscall_args { - u_int code; - struct sysent *callp; - register_t args[8]; - int narg; -}; #endif /* _KERNEL */ #endif /* !_MACHINE_PROC_H_ */ Index: sys/i386/linux/linux_sysvec.c =================================================================== --- sys/i386/linux/linux_sysvec.c +++ sys/i386/linux/linux_sysvec.c @@ -850,13 +850,15 @@ } static int -linux_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +linux_fetch_syscall_args(struct thread *td) { struct proc *p; struct trapframe *frame; + struct syscall_args *sa; p = td->td_proc; frame = td->td_frame; + sa = &td->td_sa; sa->code = frame->tf_eax; sa->args[0] = frame->tf_ebx; Index: sys/kern/init_main.c =================================================================== --- sys/kern/init_main.c +++ sys/kern/init_main.c @@ -360,8 +360,7 @@ #endif static int -null_fetch_syscall_args(struct thread *td __unused, - struct syscall_args *sa __unused) +null_fetch_syscall_args(struct thread *td __unused) { panic("null_fetch_syscall_args"); Index: sys/kern/kern_fork.c =================================================================== --- sys/kern/kern_fork.c +++ sys/kern/kern_fork.c @@ -1099,7 +1099,7 @@ */ PROC_LOCK(p); td->td_dbgflags |= TDB_SCX; - _STOPEVENT(p, S_SCX, td->td_dbg_sc_code); + _STOPEVENT(p, S_SCX, td->td_sa.code); if ((p->p_ptevents & PTRACE_SCX) != 0 || (td->td_dbgflags & TDB_BORN) != 0) ptracestop(td, SIGTRAP, NULL); Index: sys/kern/kern_sig.c =================================================================== --- sys/kern/kern_sig.c +++ sys/kern/kern_sig.c @@ -150,6 +150,10 @@ SYSCTL_INT(_kern_sigqueue, OID_AUTO, alloc_fail, CTLFLAG_RD, &signal_alloc_fail, 0, "signals failed to be allocated"); +static int kern_lognosys = 0; +SYSCTL_INT(_kern, OID_AUTO, lognosys, CTLFLAG_RWTUN, &kern_lognosys, 0, + "Log invalid syscalls"); + SYSINIT(signal, SI_SUB_P1003_1B, SI_ORDER_FIRST+3, sigqueue_start, NULL); /* @@ -3568,11 +3572,16 @@ int nosys(struct thread *td, struct nosys_args *args) { - struct proc *p = td->td_proc; + struct proc *p; + + p = td->td_proc; PROC_LOCK(p); tdsignal(td, SIGSYS); PROC_UNLOCK(p); + if (kern_lognosys) + uprintf("pid %d comm %s: nosys %d\n", p->p_pid, p->p_comm, + td->td_sa.code); return (ENOSYS); } Index: sys/kern/kern_thread.c =================================================================== --- sys/kern/kern_thread.c +++ sys/kern/kern_thread.c @@ -80,9 +80,9 @@ "struct thread KBI td_flags"); _Static_assert(offsetof(struct thread, td_pflags) == 0xfc, "struct thread KBI td_pflags"); -_Static_assert(offsetof(struct thread, td_frame) == 0x410, +_Static_assert(offsetof(struct thread, td_frame) == 0x460, "struct thread KBI td_frame"); -_Static_assert(offsetof(struct thread, td_emuldata) == 0x4b8, +_Static_assert(offsetof(struct thread, td_emuldata) == 0x508, "struct thread KBI td_emuldata"); _Static_assert(offsetof(struct proc, p_flag) == 0xb0, "struct proc KBI p_flag"); @@ -100,9 +100,9 @@ "struct thread KBI td_flags"); _Static_assert(offsetof(struct thread, td_pflags) == 0xa4, "struct thread KBI td_pflags"); -_Static_assert(offsetof(struct thread, td_frame) == 0x2c8, +_Static_assert(offsetof(struct thread, td_frame) == 0x2ec, "struct thread KBI td_frame"); -_Static_assert(offsetof(struct thread, td_emuldata) == 0x314, +_Static_assert(offsetof(struct thread, td_emuldata) == 0x338, "struct thread KBI td_emuldata"); _Static_assert(offsetof(struct proc, p_flag) == 0x68, "struct proc KBI p_flag"); Index: sys/kern/subr_syscall.c =================================================================== --- sys/kern/subr_syscall.c +++ sys/kern/subr_syscall.c @@ -53,13 +53,15 @@ #include static inline int -syscallenter(struct thread *td, struct syscall_args *sa) +syscallenter(struct thread *td) { struct proc *p; + struct syscall_args *sa; int error, traced; VM_CNT_INC(v_syscall); p = td->td_proc; + sa = &td->td_sa; td->td_pticks = 0; if (td->td_cowgen != p->p_cowgen) @@ -72,7 +74,7 @@ td->td_dbgflags |= TDB_SCE; PROC_UNLOCK(p); } - error = (p->p_sysent->sv_fetch_syscall_args)(td, sa); + error = (p->p_sysent->sv_fetch_syscall_args)(td); #ifdef KTRACE if (KTRPOINT(td, KTR_SYSCALL)) ktrsyscall(sa->code, sa->narg, sa->args); @@ -86,8 +88,6 @@ STOPEVENT(p, S_SCE, sa->narg); if (p->p_flag & P_TRACED) { PROC_LOCK(p); - td->td_dbg_sc_code = sa->code; - td->td_dbg_sc_narg = sa->narg; if (p->p_ptevents & PTRACE_SCE) ptracestop((td), SIGTRAP, NULL); PROC_UNLOCK(p); @@ -97,11 +97,7 @@ * Reread syscall number and arguments if * debugger modified registers or memory. */ - error = (p->p_sysent->sv_fetch_syscall_args)(td, sa); - PROC_LOCK(p); - td->td_dbg_sc_code = sa->code; - td->td_dbg_sc_narg = sa->narg; - PROC_UNLOCK(p); + error = (p->p_sysent->sv_fetch_syscall_args)(td); #ifdef KTRACE if (KTRPOINT(td, KTR_SYSCALL)) ktrsyscall(sa->code, sa->narg, sa->args); @@ -163,9 +159,10 @@ } static inline void -syscallret(struct thread *td, int error, struct syscall_args *sa) +syscallret(struct thread *td, int error) { struct proc *p, *p2; + struct syscall_args *sa; ksiginfo_t ksi; int traced, error1; @@ -173,6 +170,7 @@ ("fork() did not clear TDP_FORKING upon completion")); p = td->td_proc; + sa = &td->td_sa; if ((trap_enotcap || (p->p_flag2 & P2_TRAPCAP) != 0) && IN_CAPABILITY_MODE(td)) { error1 = (td->td_pflags & TDP_NERRNO) == 0 ? error : Index: sys/kern/sys_process.c =================================================================== --- sys/kern/sys_process.c +++ sys/kern/sys_process.c @@ -586,6 +586,7 @@ struct ptrace_lwpinfo32 pl32; struct ptrace_vm_entry32 pve32; #endif + char args[nitems(td->td_sa.args) * sizeof(register_t)]; int ptevents; } r; void *addr; @@ -606,6 +607,7 @@ case PT_GETFPREGS: case PT_GETDBREGS: case PT_LWPINFO: + case PT_GET_SC_ARGS: break; case PT_SETREGS: error = COPYIN(uap->addr, &r.reg, sizeof r.reg); @@ -663,6 +665,10 @@ /* NB: The size in uap->data is validated in kern_ptrace(). */ error = copyout(&r.pl, uap->addr, uap->data); break; + case PT_GET_SC_ARGS: + error = copyout(r.args, uap->addr, MIN(uap->data, + sizeof(r.args))); + break; } return (error); @@ -739,6 +745,7 @@ case PT_GET_EVENT_MASK: case PT_SET_EVENT_MASK: case PT_DETACH: + case PT_GET_SC_ARGS: sx_xlock(&proctree_lock); proctree_locked = 1; break; @@ -1009,6 +1016,28 @@ p->p_pid, p->p_ptevents, tmp); p->p_ptevents = tmp; break; + + case PT_GET_SC_ARGS: + CTR1(KTR_PTRACE, "PT_GET_SC_ARGS: pid %d", p->p_pid); + if ((td2->td_dbgflags & (TDB_SCE | TDB_SCX)) == 0 +#ifdef COMPAT_FREEBSD32 + || (wrap32 && !safe) +#endif + ) { + error = EINVAL; + break; + } + bzero(addr, sizeof(td2->td_sa.args)); +#ifdef COMPAT_FREEBSD32 + if (wrap32) + for (num = 0; num < nitems(td2->td_sa.args); num++) + ((uint32_t *)addr)[num] = (uint32_t) + td2->td_sa.args[num]; + else +#endif + bcopy(td2->td_sa.args, addr, td2->td_sa.narg * + sizeof(register_t)); + break; case PT_STEP: case PT_CONTINUE: @@ -1347,8 +1376,8 @@ pl->pl_siglist = td2->td_siglist; strcpy(pl->pl_tdname, td2->td_name); if ((td2->td_dbgflags & (TDB_SCE | TDB_SCX)) != 0) { - pl->pl_syscall_code = td2->td_dbg_sc_code; - pl->pl_syscall_narg = td2->td_dbg_sc_narg; + pl->pl_syscall_code = td2->td_sa.code; + pl->pl_syscall_narg = td2->td_sa.narg; } else { pl->pl_syscall_code = 0; pl->pl_syscall_narg = 0; Index: sys/mips/include/proc.h =================================================================== --- sys/mips/include/proc.h +++ sys/mips/include/proc.h @@ -80,7 +80,6 @@ /* empty */ }; -#ifdef _KERNEL struct syscall_args { u_int code; struct sysent *callp; @@ -88,7 +87,6 @@ int narg; struct trapframe *trapframe; }; -#endif #ifdef __mips_n64 #define KINFO_PROC_SIZE 1088 Index: sys/mips/mips/trap.c =================================================================== --- sys/mips/mips/trap.c +++ sys/mips/mips/trap.c @@ -334,12 +334,16 @@ extern void fswintrberr(void); /* XXX */ int -cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cpu_fetch_syscall_args(struct thread *td) { - struct trapframe *locr0 = td->td_frame; + struct trapframe *locr0; struct sysentvec *se; + struct syscall_args *sa; int error, nsaved; + locr0 = td->td_frame; + sa = &td->td_sa; + bzero(sa->args, sizeof(sa->args)); /* compute next PC after syscall instruction */ @@ -785,19 +789,18 @@ case T_SYSCALL + T_USER: { - struct syscall_args sa; int error; - sa.trapframe = trapframe; - error = syscallenter(td, &sa); + td->td_sa.trapframe = trapframe; + error = syscallenter(td); #if !defined(SMP) && (defined(DDB) || defined(DEBUG)) if (trp == trapdebug) - trapdebug[TRAPSIZE - 1].code = sa.code; + trapdebug[TRAPSIZE - 1].code = td->td_sa.code; else - trp[-1].code = sa.code; + trp[-1].code = td->td_sa.code; #endif - trapdebug_enter(td->td_frame, -sa.code); + trapdebug_enter(td->td_frame, -td->td_sa.code); /* * The sync'ing of I & D caches for SYS_ptrace() is @@ -805,7 +808,7 @@ * instead of being done here under a special check * for SYS_ptrace(). */ - syscallret(td, error, &sa); + syscallret(td, error); return (trapframe->pc); } Index: sys/powerpc/include/proc.h =================================================================== --- sys/powerpc/include/proc.h +++ sys/powerpc/include/proc.h @@ -53,6 +53,13 @@ #define KINFO_PROC_SIZE 768 #endif +struct syscall_args { + u_int code; + struct sysent *callp; + register_t args[10]; + int narg; +}; + #ifdef _KERNEL #include @@ -65,13 +72,6 @@ td->td_kstack_pages * PAGE_SIZE - \ (char *)&td; \ } while (0) - -struct syscall_args { - u_int code; - struct sysent *callp; - register_t args[10]; - int narg; -}; #endif #endif /* !_MACHINE_PROC_H_ */ Index: sys/powerpc/powerpc/trap.c =================================================================== --- sys/powerpc/powerpc/trap.c +++ sys/powerpc/powerpc/trap.c @@ -496,16 +496,18 @@ } int -cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cpu_fetch_syscall_args(struct thread *td) { struct proc *p; struct trapframe *frame; + struct syscall_args *sa; caddr_t params; size_t argsz; int error, n, i; p = td->td_proc; frame = td->td_frame; + sa = &td->td_sa; sa->code = frame->fixreg[0]; params = (caddr_t)(frame->fixreg + FIRSTARG); @@ -587,7 +589,6 @@ syscall(struct trapframe *frame) { struct thread *td; - struct syscall_args sa; int error; td = curthread; @@ -602,8 +603,8 @@ "r"(td->td_pcb->pcb_cpu.aim.usr_vsid), "r"(USER_SLB_SLBE)); #endif - error = syscallenter(td, &sa); - syscallret(td, error, &sa); + error = syscallenter(td); + syscallret(td, error); } #if defined(__powerpc64__) && defined(AIM) Index: sys/riscv/include/proc.h =================================================================== --- sys/riscv/include/proc.h +++ sys/riscv/include/proc.h @@ -45,8 +45,6 @@ #define KINFO_PROC_SIZE 1088 -#ifdef _KERNEL - #define MAXARGS 8 struct syscall_args { u_int code; @@ -55,6 +53,4 @@ int narg; }; -#endif - #endif /* !_MACHINE_PROC_H_ */ Index: sys/riscv/riscv/trap.c =================================================================== --- sys/riscv/riscv/trap.c +++ sys/riscv/riscv/trap.c @@ -89,14 +89,16 @@ } int -cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cpu_fetch_syscall_args(struct thread *td) { struct proc *p; register_t *ap; + struct syscall_args *sa; int nap; nap = NARGREG; p = td->td_proc; + sa = &td->td_sa; ap = &td->td_frame->tf_a[0]; sa->code = td->td_frame->tf_t[0]; @@ -151,15 +153,14 @@ static void svc_handler(struct trapframe *frame) { - struct syscall_args sa; struct thread *td; int error; td = curthread; td->td_frame = frame; - error = syscallenter(td, &sa); - syscallret(td, error, &sa); + error = syscallenter(td); + syscallret(td, error); } static void Index: sys/sparc64/include/proc.h =================================================================== --- sys/sparc64/include/proc.h +++ sys/sparc64/include/proc.h @@ -53,6 +53,13 @@ #define KINFO_PROC_SIZE 1088 +struct syscall_args { + u_int code; + struct sysent *callp; + register_t args[8]; + int narg; +}; + #ifdef _KERNEL #include @@ -66,13 +73,6 @@ (char *)&td; \ } while (0) -struct syscall_args { - u_int code; - struct sysent *callp; - register_t args[8]; - int narg; -}; - #endif #endif /* !_MACHINE_PROC_H_ */ Index: sys/sparc64/sparc64/trap.c =================================================================== --- sys/sparc64/sparc64/trap.c +++ sys/sparc64/sparc64/trap.c @@ -538,17 +538,19 @@ #define REG_MAXARGS 6 int -cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa) +cpu_fetch_syscall_args(struct thread *td) { struct trapframe *tf; struct proc *p; register_t *argp; + struct syscall_args *sa; int reg; int regcnt; int error; p = td->td_proc; tf = td->td_frame; + sa = &td->td_sa; reg = 0; regcnt = REG_MAXARGS; @@ -596,7 +598,6 @@ syscall(struct trapframe *tf) { struct thread *td; - struct syscall_args sa; int error; td = curthread; @@ -612,6 +613,6 @@ td->td_pcb->pcb_tpc = tf->tf_tpc; TF_DONE(tf); - error = syscallenter(td, &sa); - syscallret(td, error, &sa); + error = syscallenter(td); + syscallret(td, error); } Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h +++ sys/sys/proc.h @@ -142,6 +142,7 @@ * j - locked by proc slock * k - only accessed by curthread * k*- only accessed by curthread and from an interrupt + * kx- only accessed by curthread and by debugger * l - the attaching proc or attaching proc parent * m - Giant * n - not locked, lazy @@ -296,11 +297,11 @@ u_char td_pri_class; /* (t) Scheduling class. */ u_char td_user_pri; /* (t) User pri from estcpu and nice. */ u_char td_base_user_pri; /* (t) Base user pri */ - u_int td_dbg_sc_code; /* (c) Syscall code to debugger. */ - u_int td_dbg_sc_narg; /* (c) Syscall arg count to debugger.*/ uintptr_t td_rb_list; /* (k) Robust list head. */ uintptr_t td_rbp_list; /* (k) Robust priv list head. */ uintptr_t td_rb_inact; /* (k) Current in-action mutex loc. */ + struct syscall_args td_sa; /* (kx) Syscall parameters. Copied on + fork for child tracing. */ #define td_endcopy td_pcb /* @@ -1053,7 +1054,7 @@ void cpu_exit(struct thread *); void exit1(struct thread *, int, int) __dead2; void cpu_copy_thread(struct thread *td, struct thread *td0); -int cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa); +int cpu_fetch_syscall_args(struct thread *td); void cpu_fork(struct thread *, struct proc *, struct thread *, int); void cpu_fork_kthread_handler(struct thread *, void (*)(void *), void *); void cpu_set_syscall_retval(struct thread *, int); Index: sys/sys/ptrace.h =================================================================== --- sys/sys/ptrace.h +++ sys/sys/ptrace.h @@ -69,6 +69,8 @@ #define PT_GET_EVENT_MASK 25 /* get mask of optional events */ #define PT_SET_EVENT_MASK 26 /* set mask of optional events */ +#define PT_GET_SC_ARGS 27 /* fetch syscall args */ + #define PT_GETREGS 33 /* get general-purpose registers */ #define PT_SETREGS 34 /* set general-purpose registers */ #define PT_GETFPREGS 35 /* get floating-point registers */ Index: sys/sys/sysent.h =================================================================== --- sys/sys/sysent.h +++ sys/sys/sysent.h @@ -119,8 +119,7 @@ u_long *sv_maxssiz; u_int sv_flags; void (*sv_set_syscall_retval)(struct thread *, int); - int (*sv_fetch_syscall_args)(struct thread *, struct - syscall_args *); + int (*sv_fetch_syscall_args)(struct thread *); const char **sv_syscallnames; vm_offset_t sv_timekeep_base; vm_offset_t sv_shared_page_base; Index: tools/test/ptrace/scescx.c =================================================================== --- tools/test/ptrace/scescx.c +++ tools/test/ptrace/scescx.c @@ -97,6 +97,11 @@ { PL_FLAG_EXEC, "EXEC" }, { PL_FLAG_SI, "SI" }, { PL_FLAG_FORKED, "FORKED" }, + { PL_FLAG_CHILD, "CHILD" }, + { PL_FLAG_BORN, "LWPBORN" }, + { PL_FLAG_EXITED, "LWPEXITED" }, + { PL_FLAG_VFORKED, "VFORKED" }, + { PL_FLAG_VFORK_DONE, "VFORKDONE" }, }; char de[32]; unsigned first, flags, i; @@ -176,12 +181,33 @@ static void wait_info(int pid, int status, struct ptrace_lwpinfo *lwpinfo) { + long *args; + int error, i; printf(TRACE "pid %d wait %s", pid, decode_wait_status(status)); if (lwpinfo != NULL) { printf(" event %s flags %s", decode_pl_event(lwpinfo), decode_pl_flags(lwpinfo)); + if ((lwpinfo->pl_flags & (PL_FLAG_SCE | PL_FLAG_SCX)) != 0) { + printf(" sc%d", lwpinfo->pl_syscall_code); + args = calloc(lwpinfo->pl_syscall_narg, sizeof(long)); + error = ptrace(PT_GET_SC_ARGS, lwpinfo->pl_lwpid, + (caddr_t)args, lwpinfo->pl_syscall_narg * + sizeof(long)); + if (error == 0) { + for (i = 0; i < (int)lwpinfo->pl_syscall_narg; + i++) { + printf("%c%#lx", i == 0 ? '(' : ',', + args[i]); + } + } else { + fprintf(stderr, "PT_GET_SC_ARGS failed: %s", + strerror(errno)); + } + printf(")"); + free(args); + } } printf("\n"); }