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 <security/audit/audit.h>
 
 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 <machine/pcb.h>
@@ -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 <machine/pcb.h>
@@ -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");
 }