PERFORCE change 144351 for review
John Birrell
jb at FreeBSD.org
Mon Jun 30 07:09:30 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=144351
Change 144351 by jb at freebsd3 on 2008/06/30 07:08:59
Add support for the DTrace linux syscall provider. It shares code with
the standard syscall provider.
The new provider can't be loaded as part of the 'dtraceall' kernel
module because it depends on the 'linux' kernel module.
Affected files ...
.. //depot/projects/dtrace/src/sys/cddl/dev/systrace/systrace.c#12 edit
.. //depot/projects/dtrace/src/sys/modules/dtrace/Makefile#33 edit
.. //depot/projects/dtrace/src/sys/modules/dtrace/linsystrace/Makefile#1 add
Differences ...
==== //depot/projects/dtrace/src/sys/cddl/dev/systrace/systrace.c#12 (text+ko) ====
@@ -50,15 +50,41 @@
#include <sys/proc.h>
#include <sys/selinfo.h>
#include <sys/smp.h>
-#include <sys/syscall.h>
+#include <sys/sysproto.h>
#include <sys/sysent.h>
-#include <sys/sysproto.h>
#include <sys/uio.h>
#include <sys/unistd.h>
#include <machine/stdarg.h>
#include <sys/dtrace.h>
+#ifdef LINUX_SYSTRACE
+#include <linux.h>
+#include <linux_syscall.h>
+#include <linux_proto.h>
+#include <linux_syscallnames.c>
+#include <linux_systrace.c>
+extern struct sysent linux_sysent[];
+#define DEVNAME "dtrace/linsystrace"
+#define PROVNAME "linsyscall"
+#define MAXSYSCALL LINUX_SYS_MAXSYSCALL
+#define SYSCALLNAMES linux_syscallnames
+#define SYSENT linux_sysent
+#else
+/*
+ * The syscall arguments are processed into a DTrace argument array
+ * using a generated function. See sys/kern/makesyscalls.sh.
+ */
+#include <sys/syscall.h>
+#include <kern/systrace_args.c>
+extern const char *syscallnames[];
+#define DEVNAME "dtrace/systrace"
+#define PROVNAME "syscall"
+#define MAXSYSCALL SYS_MAXSYSCALL
+#define SYSCALLNAMES syscallnames
+#define SYSENT sysent
+#endif
+
#define SYSTRACE_ARTIFICIAL_FRAMES 1
#define SYSTRACE_SHIFT 16
@@ -67,17 +93,13 @@
#define SYSTRACE_ENTRY(id) ((1 << SYSTRACE_SHIFT) | (id))
#define SYSTRACE_RETURN(id) (id)
-#if ((1 << SYSTRACE_SHIFT) <= SYS_MAXSYSCALL)
+#if ((1 << SYSTRACE_SHIFT) <= MAXSYSCALL)
#error 1 << SYSTRACE_SHIFT must exceed number of system calls
#endif
-extern char *syscallnames[];
-
static d_open_t systrace_open;
static int systrace_unload(void);
static void systrace_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
-static void systrace_args(int, void *, u_int64_t *, int *);
-static void systrace_probe(u_int32_t, int, struct sysent *, void *);
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 *);
@@ -87,9 +109,18 @@
static struct cdevsw systrace_cdevsw = {
.d_version = D_VERSION,
.d_open = systrace_open,
+#ifdef LINUX_SYSTRACE
+ .d_name = "linsystrace",
+#else
.d_name = "systrace",
+#endif
};
+static union {
+ const char **p_constnames;
+ char **pp_syscallnames;
+} uglyhack = { SYSCALLNAMES };
+
static dtrace_pattr_t systrace_attr = {
{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
@@ -114,12 +145,14 @@
static struct cdev *systrace_cdev;
static dtrace_provider_id_t systrace_id;
+#if !defined(LINUX_SYSTRACE)
/*
- * The syscall arguments are processed into a DTrace argument array
- * using a generated function. See sys/kern/makesyscalls.sh.
+ * Probe callback function.
+ *
+ * Note: This function is called for _all_ syscalls, regardless of which sysent
+ * array the syscall comes from. It could be a standard syscall or a
+ * compat syscall from something like Linux.
*/
-#include <kern/systrace_args.c>
-
static void
systrace_probe(u_int32_t id, int sysnum, struct sysent *sysent, void *params)
{
@@ -127,21 +160,20 @@
u_int64_t uargs[8];
/*
- * Check if this syscall has a custom argument conversion
- * function registered. If so, it is a syscall registered
- * by a loaded module.
+ * Check if this syscall has an argument conversion function
+ * registered.
*/
if (sysent->sy_systrace_args_func != NULL)
/*
* Convert the syscall parameters using the registered
* function.
*/
- (*sysent->sy_systrace_args_func)(params, uargs, &n_args);
+ (*sysent->sy_systrace_args_func)(sysnum, params, uargs, &n_args);
else
/*
* Use the built-in system call argument conversion
* function to translate the syscall structure fields
- * into thhe array of 64-bit values that DTrace
+ * into the array of 64-bit values that DTrace
* expects.
*/
systrace_args(sysnum, params, uargs, &n_args);
@@ -149,6 +181,7 @@
/* Process the probe using the converted argments. */
dtrace_probe(id, uargs[0], uargs[1], uargs[2], uargs[3], uargs[4]);
}
+#endif
static void
systrace_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
@@ -172,15 +205,15 @@
if (desc != NULL)
return;
- for (i = 0; i < SYS_MAXSYSCALL; i++) {
+ for (i = 0; i < MAXSYSCALL; i++) {
if (dtrace_probe_lookup(systrace_id, NULL,
- syscallnames[i], "entry") != 0)
+ uglyhack.pp_syscallnames[i], "entry") != 0)
continue;
- (void) dtrace_probe_create(systrace_id, NULL, syscallnames[i],
+ (void) dtrace_probe_create(systrace_id, NULL, uglyhack.pp_syscallnames[i],
"entry", SYSTRACE_ARTIFICIAL_FRAMES,
(void *)((uintptr_t)SYSTRACE_ENTRY(i)));
- (void) dtrace_probe_create(systrace_id, NULL, syscallnames[i],
+ (void) dtrace_probe_create(systrace_id, NULL, uglyhack.pp_syscallnames[i],
"return", SYSTRACE_ARTIFICIAL_FRAMES,
(void *)((uintptr_t)SYSTRACE_RETURN(i)));
}
@@ -209,10 +242,13 @@
{
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
+ if (SYSENT[sysnum].sy_systrace_args_func == NULL)
+ SYSENT[sysnum].sy_systrace_args_func = systrace_args;
+
if (SYSTRACE_ISENTRY((uintptr_t)parg))
- sysent[sysnum].sy_entry = id;
+ SYSENT[sysnum].sy_entry = id;
else
- sysent[sysnum].sy_return = id;
+ SYSENT[sysnum].sy_return = id;
}
static void
@@ -220,8 +256,8 @@
{
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
- sysent[sysnum].sy_entry = 0;
- sysent[sysnum].sy_return = 0;
+ SYSENT[sysnum].sy_entry = 0;
+ SYSENT[sysnum].sy_return = 0;
}
static void
@@ -229,13 +265,15 @@
{
/* Create the /dev/dtrace/systrace entry. */
systrace_cdev = make_dev(&systrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
- "dtrace/systrace");
+ DEVNAME);
- if (dtrace_register("syscall", &systrace_attr, DTRACE_PRIV_USER,
+ if (dtrace_register(PROVNAME, &systrace_attr, DTRACE_PRIV_USER,
NULL, &systrace_pops, NULL, &systrace_id) != 0)
return;
+#if !defined(LINUX_SYSTRACE)
systrace_probe_func = systrace_probe;
+#endif
}
@@ -247,7 +285,9 @@
if ((error = dtrace_unregister(systrace_id)) != 0)
return (error);
+#if !defined(LINUX_SYSTRACE)
systrace_probe_func = NULL;
+#endif
destroy_dev(systrace_cdev);
@@ -286,7 +326,16 @@
SYSINIT(systrace_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_load, NULL);
SYSUNINIT(systrace_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_unload, NULL);
+#ifdef LINUX_SYSTRACE
+DEV_MODULE(linsystrace, systrace_modevent, NULL);
+MODULE_VERSION(linsystrace, 1);
+MODULE_DEPEND(linsystrace, linux, 1, 1, 1);
+MODULE_DEPEND(linsystrace, systrace, 1, 1, 1);
+MODULE_DEPEND(linsystrace, dtrace, 1, 1, 1);
+MODULE_DEPEND(linsystrace, opensolaris, 1, 1, 1);
+#else
DEV_MODULE(systrace, systrace_modevent, NULL);
MODULE_VERSION(systrace, 1);
MODULE_DEPEND(systrace, dtrace, 1, 1, 1);
MODULE_DEPEND(systrace, opensolaris, 1, 1, 1);
+#endif
==== //depot/projects/dtrace/src/sys/modules/dtrace/Makefile#33 (text+ko) ====
@@ -7,6 +7,7 @@
dtrace \
dtraceall \
dtrace_test \
+ linsystrace \
profile \
prototype \
sdt \
More information about the p4-projects
mailing list