svn commit: r292388 - in head/sys: cddl/dev/dtrace cddl/dev/systrace kern sys
Mark Johnston
markj at FreeBSD.org
Thu Dec 17 00:00:30 UTC 2015
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 <sys/systm.h>
#include <sys/conf.h>
#include <sys/cpuvar.h>
+#include <sys/dtrace.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
#include <sys/kdb.h>
@@ -53,9 +54,10 @@ __FBSDID("$FreeBSD$");
#include <sys/sysproto.h>
#include <sys/uio.h>
#include <sys/unistd.h>
-#include <machine/stdarg.h>
-#include <sys/dtrace.h>
+#include <cddl/dev/dtrace/dtrace_cddl.h>
+
+#include <machine/stdarg.h>
#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;
More information about the svn-src-head
mailing list