From owner-svn-src-all@freebsd.org Thu Dec 17 00:00:30 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5CE7DA48B03; Thu, 17 Dec 2015 00:00:30 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id CFC5D1255; Thu, 17 Dec 2015 00:00:29 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tBH00SAC026330; Thu, 17 Dec 2015 00:00:28 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tBH00RRT026326; Thu, 17 Dec 2015 00:00:27 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201512170000.tBH00RRT026326@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Thu, 17 Dec 2015 00:00:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r292388 - in head/sys: cddl/dev/dtrace cddl/dev/systrace kern sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Dec 2015 00:00:30 -0000 Author: markj Date: Thu Dec 17 00:00:27 2015 New Revision: 292388 URL: https://svnweb.freebsd.org/changeset/base/292388 Log: Support an arbitrary number of arguments to DTrace syscall probes. Rather than pushing all eight possible arguments into dtrace_probe()'s stack frame, make the syscall_args struct for the current syscall available via the current thread. Using a custom getargval method for the systrace provider, this allows any syscall argument to be fetched, even in kernels that have modified the maximum number of system call arguments. Sponsored by: EMC / Isilon Storage Division Modified: head/sys/cddl/dev/dtrace/dtrace_cddl.h head/sys/cddl/dev/systrace/systrace.c head/sys/kern/subr_syscall.c head/sys/sys/sysent.h Modified: head/sys/cddl/dev/dtrace/dtrace_cddl.h ============================================================================== --- head/sys/cddl/dev/dtrace/dtrace_cddl.h Wed Dec 16 23:53:16 2015 (r292387) +++ head/sys/cddl/dev/dtrace/dtrace_cddl.h Thu Dec 17 00:00:27 2015 (r292388) @@ -83,8 +83,8 @@ typedef struct kdtrace_thread { uintptr_t td_dtrace_regv; #endif u_int64_t td_hrtime; /* Last time on cpu. */ - int td_errno; /* Syscall return value. */ void *td_dtrace_sscr; /* Saved scratch space location. */ + void *td_systrace_args; /* syscall probe arguments. */ } kdtrace_thread_t; /* @@ -110,6 +110,7 @@ typedef struct kdtrace_thread { #define t_dtrace_astpc td_dtrace->td_dtrace_astpc #define t_dtrace_regv td_dtrace->td_dtrace_regv #define t_dtrace_sscr td_dtrace->td_dtrace_sscr +#define t_dtrace_systrace_args td_dtrace->td_systrace_args #define p_dtrace_helpers p_dtrace->p_dtrace_helpers #define p_dtrace_count p_dtrace->p_dtrace_count #define p_dtrace_probes p_dtrace->p_dtrace_probes Modified: head/sys/cddl/dev/systrace/systrace.c ============================================================================== --- head/sys/cddl/dev/systrace/systrace.c Wed Dec 16 23:53:16 2015 (r292387) +++ head/sys/cddl/dev/systrace/systrace.c Thu Dec 17 00:00:27 2015 (r292388) @@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -53,9 +54,10 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include +#include + +#include #ifdef LINUX_SYSTRACE #if defined(__amd64__) @@ -138,6 +140,7 @@ static void systrace_unload(void *); static void systrace_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *); +static uint64_t systrace_getargval(void *, dtrace_id_t, void *, int, int); static void systrace_provide(void *, dtrace_probedesc_t *); static void systrace_destroy(void *, dtrace_id_t, void *); static void systrace_enable(void *, dtrace_id_t, void *); @@ -164,16 +167,13 @@ static dtrace_pops_t systrace_pops = { NULL, NULL, systrace_getargdesc, - NULL, + systrace_getargval, NULL, systrace_destroy }; static dtrace_provider_id_t systrace_id; -typedef void (*systrace_dtrace_probe_t)(dtrace_id_t, uintptr_t, uintptr_t, - uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); - #ifdef NATIVE_ABI /* * Probe callback function. @@ -183,48 +183,48 @@ typedef void (*systrace_dtrace_probe_t)( * compat syscall from something like Linux. */ static void -systrace_probe(uint32_t id, int sysnum, struct sysent *sysent, void *params, - int ret) +systrace_probe(struct syscall_args *sa, enum systrace_probe_t type, int retval) { - uint64_t uargs[8]; - systrace_dtrace_probe_t probe; - int n_args = 0; + uint64_t uargs[nitems(sa->args)]; + dtrace_id_t id; + int n_args, sysnum; + sysnum = sa->code; memset(uargs, 0, sizeof(uargs)); - /* - * Check if this syscall has an argument conversion function - * registered. - */ - if (params != NULL && sysent->sy_systrace_args_func != NULL) { - /* - * Convert the syscall parameters using the registered - * function. - */ - (*sysent->sy_systrace_args_func)(sysnum, params, uargs, - &n_args); - } else if (params != NULL) { + if (type == SYSTRACE_ENTRY) { + id = sa->callp->sy_entry; + + if (sa->callp->sy_systrace_args_func != NULL) + /* + * Convert the syscall parameters using the registered + * function. + */ + (*sa->callp->sy_systrace_args_func)(sysnum, sa->args, + uargs, &n_args); + else + /* + * Use the built-in system call argument conversion + * function to translate the syscall structure fields + * into the array of 64-bit values that DTrace expects. + */ + systrace_args(sysnum, sa->args, uargs, &n_args); /* - * Use the built-in system call argument conversion - * function to translate the syscall structure fields - * into the array of 64-bit values that DTrace - * expects. + * Save probe arguments now so that we can retrieve them if + * the getargval method is called from further down the stack. */ - systrace_args(sysnum, params, uargs, &n_args); + curthread->t_dtrace_systrace_args = uargs; } else { - /* - * Since params is NULL, this is a 'return' probe. - * Set arg0 and arg1 as the return value of this syscall. - */ - uargs[0] = uargs[1] = ret; + id = sa->callp->sy_return; + + curthread->t_dtrace_systrace_args = NULL; + /* Set arg0 and arg1 as the return value of this syscall. */ + uargs[0] = uargs[1] = retval; } /* Process the probe using the converted argments. */ - probe = (systrace_dtrace_probe_t)dtrace_probe; - probe(id, uargs[0], uargs[1], uargs[2], uargs[3], uargs[4], uargs[5], - uargs[6], uargs[7]); + dtrace_probe(id, uargs[0], uargs[1], uargs[2], uargs[3], uargs[4]); } - #endif static void @@ -244,6 +244,21 @@ systrace_getargdesc(void *arg, dtrace_id desc->dtargd_ndx = DTRACE_ARGNONE; } +static uint64_t +systrace_getargval(void *arg __unused, dtrace_id_t id __unused, + void *parg __unused, int argno, int aframes __unused) +{ + uint64_t *uargs; + + uargs = curthread->t_dtrace_systrace_args; + if (uargs == NULL) + /* This is a return probe. */ + return (0); + if (argno >= nitems(((struct syscall_args *)NULL)->args)) + return (0); + return (uargs[argno]); +} + static void systrace_provide(void *arg, dtrace_probedesc_t *desc) { Modified: head/sys/kern/subr_syscall.c ============================================================================== --- head/sys/kern/subr_syscall.c Wed Dec 16 23:53:16 2015 (r292387) +++ head/sys/kern/subr_syscall.c Thu Dec 17 00:00:27 2015 (r292388) @@ -126,14 +126,9 @@ syscallenter(struct thread *td, struct s goto retval; #ifdef KDTRACE_HOOKS - /* - * If the systrace module has registered it's probe - * callback and if there is a probe active for the - * syscall 'entry', process the probe. - */ + /* Give the syscall:::entry DTrace probe a chance to fire. */ if (systrace_probe_func != NULL && sa->callp->sy_entry != 0) - (*systrace_probe_func)(sa->callp->sy_entry, sa->code, - sa->callp, sa->args, 0); + (*systrace_probe_func)(sa, SYSTRACE_ENTRY, 0); #endif AUDIT_SYSCALL_ENTER(sa->code, td); @@ -145,14 +140,10 @@ syscallenter(struct thread *td, struct s td->td_errno = error; #ifdef KDTRACE_HOOKS - /* - * If the systrace module has registered it's probe - * callback and if there is a probe active for the - * syscall 'return', process the probe. - */ + /* Give the syscall:::return DTrace probe a chance to fire. */ if (systrace_probe_func != NULL && sa->callp->sy_return != 0) - (*systrace_probe_func)(sa->callp->sy_return, sa->code, - sa->callp, NULL, (error) ? -1 : td->td_retval[0]); + (*systrace_probe_func)(sa, SYSTRACE_RETURN, + error ? -1 : td->td_retval[0]); #endif syscall_thread_exit(td, sa->callp); } Modified: head/sys/sys/sysent.h ============================================================================== --- head/sys/sys/sysent.h Wed Dec 16 23:53:16 2015 (r292387) +++ head/sys/sys/sysent.h Thu Dec 17 00:00:27 2015 (r292388) @@ -38,18 +38,18 @@ struct rlimit; struct sysent; struct thread; struct ksiginfo; +struct syscall_args; + +enum systrace_probe_t { + SYSTRACE_ENTRY, + SYSTRACE_RETURN, +}; typedef int sy_call_t(struct thread *, void *); -/* Used by the machine dependent syscall() code. */ -typedef void (*systrace_probe_func_t)(u_int32_t, int, struct sysent *, void *, - int); - -/* - * Used by loaded syscalls to convert arguments to a DTrace array - * of 64-bit arguments. - */ -typedef void (*systrace_args_func_t)(int, void *, u_int64_t *, int *); +typedef void (*systrace_probe_func_t)(struct syscall_args *, + enum systrace_probe_t, int); +typedef void (*systrace_args_func_t)(int, void *, uint64_t *, int *); extern systrace_probe_func_t systrace_probe_func; @@ -84,7 +84,6 @@ struct sysent { /* system call table * struct image_params; struct __sigset; -struct syscall_args; struct trapframe; struct vnode;