Current-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Revisiting DTrace syscall provider
Patch simplified to handle non-native and indirect syscalls properly.
(also netbsd32...) These diffs don't include the diffs to the compat
code or to the cddl code. I'd like to start committing this stuff soon...
The syscall_args conversion function has moved to struct emul to save
space and time.
christos
Index: kern/Makefile
===================================================================
RCS file: /cvsroot/src/sys/kern/Makefile,v
retrieving revision 1.17
diff -u -u -r1.17 Makefile
--- kern/Makefile 16 Jan 2014 01:15:34 -0000 1.17
+++ kern/Makefile 7 Mar 2015 07:05:23 -0000
@@ -11,7 +11,7 @@
@false
SYSCALLSRC = makesyscalls.sh syscalls.conf syscalls.master
-init_sysent.c syscalls.c ../sys/syscall.h ../sys/syscallargs.h: ${SYSCALLSRC}
+init_sysent.c syscalls.c systrace_args.c ../sys/syscall.h ../sys/syscallargs.h: ${SYSCALLSRC}
${HOST_SH} makesyscalls.sh syscalls.conf syscalls.master
VNODEIFSRC = vnode_if.sh vnode_if.src
Index: kern/files.kern
===================================================================
RCS file: /cvsroot/src/sys/kern/files.kern,v
retrieving revision 1.2
diff -u -u -r1.2 files.kern
--- kern/files.kern 12 Oct 2014 04:38:28 -0000 1.2
+++ kern/files.kern 7 Mar 2015 07:05:23 -0000
@@ -168,7 +168,7 @@
file kern/sys_sig.c kern
file kern/sys_sched.c kern
file kern/sys_socket.c kern
-file kern/syscalls.c syscall_debug
+file kern/syscalls.c syscall_debug | kdtrace_hooks
file kern/sysv_ipc.c sysvshm | sysvsem | sysvmsg
file kern/sysv_msg.c sysvmsg
file kern/sysv_sem.c sysvsem
Index: kern/kern_syscall.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_syscall.c,v
retrieving revision 1.9
diff -u -u -r1.9 kern_syscall.c
--- kern/kern_syscall.c 14 Dec 2013 06:27:57 -0000 1.9
+++ kern/kern_syscall.c 7 Mar 2015 07:05:23 -0000
@@ -37,6 +37,7 @@
#include "opt_syscall_debug.h"
#include "opt_ktrace.h"
#include "opt_ptrace.h"
+#include "opt_dtrace.h"
#endif
/* XXX To get syscall prototypes. */
@@ -55,6 +56,10 @@
#include <sys/ktrace.h>
#include <sys/ptrace.h>
+#ifdef KDTRACE_HOOKS
+systrace_probe_func_t systrace_probe_func;
+#endif
+
int
sys_nomodule(struct lwp *l, const void *v, register_t *retval)
{
@@ -370,15 +375,22 @@
* a system call is actually executed.
*/
int
-trace_enter(register_t code, const register_t *args, int narg)
+trace_enter(register_t code, const struct sysent *sy, const void *args)
{
int error = 0;
+#ifdef KDTRACE_HOOKS
+ if (sy->sy_entry) {
+ KASSERT(systrace_probe_func);
+ (*systrace_probe_func)(sy->sy_entry, code, sy, args, 0);
+ }
+#endif
+
#ifdef SYSCALL_DEBUG
scdebug_call(code, args);
#endif /* SYSCALL_DEBUG */
- ktrsyscall(code, args, narg);
+ ktrsyscall(code, args, sy->sy_narg);
#ifdef PTRACE
if ((curlwp->l_proc->p_slflag & (PSL_SYSCALL|PSL_TRACED)) ==
@@ -401,12 +413,21 @@
* system call number range for emulation the process runs under.
*/
void
-trace_exit(register_t code, register_t rval[], int error)
+trace_exit(register_t code, const struct sysent *sy, const void *args,
+ register_t rval[], int error)
{
#ifdef PTRACE
struct proc *p = curlwp->l_proc;
#endif
+#ifdef KDTRACE_HOOKS
+ if (sy->sy_return) {
+ KASSERT(systrace_probe_func);
+ (*systrace_probe_func)(sy->sy_return, code, sy, args,
+ error ? -1 : rval[0]);
+ }
+#endif
+
#ifdef SYSCALL_DEBUG
scdebug_ret(code, error, rval);
#endif /* SYSCALL_DEBUG */
Index: kern/makesyscalls.sh
===================================================================
RCS file: /cvsroot/src/sys/kern/makesyscalls.sh,v
retrieving revision 1.145
diff -u -u -r1.145 makesyscalls.sh
--- kern/makesyscalls.sh 24 Jul 2014 11:58:45 -0000 1.145
+++ kern/makesyscalls.sh 7 Mar 2015 07:05:23 -0000
@@ -61,6 +61,7 @@
# source the config file.
sys_nosys="sys_nosys" # default is sys_nosys(), if not specified otherwise
maxsysargs=8 # default limit is 8 (32bit) arguments
+systrace="/dev/null"
rumpcalls="/dev/null"
rumpcallshdr="/dev/null"
rumpsysmap="/dev/null"
@@ -75,15 +76,17 @@
sysnamesbottom="sysnames.bottom"
rumptypes="rumphdr.types"
rumpprotos="rumphdr.protos"
+systracetmp="systrace.$$"
+systraceret="systraceret.$$"
-trap "rm $sysdcl $sysprotos $sysent $sysnamesbottom $rumpsysent $rumptypes $rumpprotos" 0
+trap "rm $sysdcl $sysprotos $sysent $sysnamesbottom $rumpsysent $rumptypes $rumpprotos $systracetmp $systraceret" 0
# Awk program (must support nawk extensions)
# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere.
awk=${AWK:-awk}
# Does this awk have a "toupper" function?
-have_toupper=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null`
+have_toupper="$($awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null)"
# If this awk does not define "toupper" then define our own.
if [ "$have_toupper" = TRUE ] ; then
@@ -137,6 +140,9 @@
sysnumhdr = \"$sysnumhdr\"
sysarghdr = \"$sysarghdr\"
sysarghdrextra = \"$sysarghdrextra\"
+ systrace = \"$systrace\"
+ systracetmp = \"$systracetmp\"
+ systraceret = \"$systraceret\"
rumpcalls = \"$rumpcalls\"
rumpcallshdr = \"$rumpcallshdr\"
rumpsysent = \"$rumpsysent\"
@@ -211,6 +217,10 @@
printf "/* %s */\n\n", tag > rumpcallshdr
printf "/*\n * System call protos in rump namespace.\n *\n" > rumpcallshdr
printf " * DO NOT EDIT-- this file is automatically generated.\n" > rumpcallshdr
+
+ printf "/* %s */\n\n", tag > systrace
+ printf "/*\n * System call argument to DTrace register array converstion.\n *\n" > systrace
+ printf " * DO NOT EDIT-- this file is automatically generated.\n" > systrace
}
NR == 1 {
sub(/ $/, "")
@@ -324,6 +334,17 @@
"\t\t<= %sMAXSYSARGS * sizeof (%s) ? 1 : -1];\n", \
constprefix, registertype) >sysarghdr
+ printf " * This file is part of the DTrace syscall provider.\n */\n\n" > systrace
+ printf "static void\nsystrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)\n{\n" > systrace
+ printf "\tint64_t *iarg = (int64_t *) uarg;\n" > systrace
+ printf "\tswitch (sysnum) {\n" > systrace
+
+ printf "static void\nsystrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)\n{\n\tconst char *p = NULL;\n" > systracetmp
+ printf "\tswitch (sysnum) {\n" > systracetmp
+
+ printf "static void\nsystrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)\n{\n\tconst char *p = NULL;\n" > systraceret
+ printf "\tswitch (sysnum) {\n" > systraceret
+
# compat types from syscalls.master. this is slightly ugly,
# but given that we have so few compats from over 17 years,
# a more complicated solution is not currently warranted.
@@ -376,6 +397,9 @@
print > sysnumhdr
print > sysprotos
print > sysnamesbottom
+ print > systrace
+ print > systracetmp
+ print > systraceret
# XXX: technically we do not want to have conditionals in rump,
# but it is easier to just let the cpp handle them than try to
@@ -647,7 +671,7 @@
eno[1] = "rumpns_sys_nomodule"
flags[0] = "SYCALL_NOSYS"
flags[1] = "0"
- printf("\t{ 0, 0, %s,\n\t (sy_call_t *)%s }, \t" \
+ printf("\t{ 0, 0, %s,\n\t (sy_call_t *)%s, 0, 0 }, \t" \
"/* %d = %s */\n", \
flags[modular], eno[modular], syscall, funcalias) \
> rumpsysent
@@ -665,7 +689,7 @@
fn="(sy_call_t *)rumpns_sys_nomodule"
else
fn="(sy_call_t *)rumpns_enosys"
- printf("0,\n\t %s },", fn) > rumpsysent
+ printf("0,\n\t %s, 0, 0 },", fn) > rumpsysent
for (i = 0; i < (33 - length(fn)) / 8; i++)
printf("\t") > rumpsysent
printf("/* %d = %s%s */\n", syscall, compatwrap_, funcalias) > rumpsysent
@@ -697,6 +721,45 @@
syscall, wfn, funcalias, rumpentry) > rumpsysmap
}
+function putsystrace(type, compatwrap_) {
+ printf("\t/* %s */\n\tcase %d: {\n", funcname, syscall) > systrace
+ printf("\t/* %s */\n\tcase %d:\n", funcname, syscall) > systracetmp
+ printf("\t/* %s */\n\tcase %d:\n", funcname, syscall) > systraceret
+ if (argc > 0) {
+ printf("\t\tswitch(ndx) {\n") > systracetmp
+ printf("\t\tstruct %s%s_args *p = params;\n", compatwrap_, funcname) > systrace
+ for (i = 1; i <= argc; i++) {
+ arg = argtype[i]
+ sub("__restrict$", "", arg)
+ printf("\t\tcase %d:\n\t\t\tp = \"%s\";\n\t\t\tbreak;\n", i - 1, arg) > systracetmp
+ if (arg ~ /.*p_t$/ || arg ~ /.*p$/ || arg ~ /.*_t_p$/ ||
+ arg ~ /.*_pointer_t$/)
+ printf("\t\tuarg[%d] = (intptr_t) SCARG(p, %s).i32; /* %s */\n", \
+ i - 1, \
+ argname[i], arg) > systrace
+ else if (index(arg, "*") > 0 || arg == "caddr_t")
+ printf("\t\tuarg[%d] = (intptr_t) SCARG(p, %s); /* %s */\n", \
+ i - 1, \
+ argname[i], arg) > systrace
+ else if (substr(arg, 1, 1) == "u" || arg == "size_t")
+ printf("\t\tuarg[%d] = SCARG(p, %s); /* %s */\n", \
+ i - 1, \
+ argname[i], arg) > systrace
+ else
+ printf("\t\tiarg[%d] = SCARG(p, %s); /* %s */\n", \
+ i - 1, \
+ argname[i], arg) > systrace
+ }
+ printf("\t\tdefault:\n\t\t\tbreak;\n\t\t};\n") > systracetmp
+
+ printf("\t\tif (ndx == 0 || ndx == 1)\n") > systraceret
+ printf("\t\t\tp = \"%s\";\n", returntype) > systraceret
+ printf("\t\tbreak;\n") > systraceret
+ }
+ printf("\t\t*n_args = %d;\n\t\tbreak;\n\t}\n", argc) > systrace
+ printf("\t\tbreak;\n") > systracetmp
+}
+
function putent(type, compatwrap) {
# output syscall declaration for switch table.
if (compatwrap == "")
@@ -708,6 +771,7 @@
else {
arg_type = "struct " compatwrap_ funcname "_args";
}
+ putsystrace(type, compatwrap_)
proto = "int\t" compatwrap_ funcname "(struct lwp *, const " \
arg_type " *, register_t *);\n"
if (sysmap[proto] != 1) {
@@ -729,7 +793,7 @@
else
wfn = compatwrap "(" funcname ")";
wfn_cast="(sy_call_t *)" wfn
- printf("%s,\n\t %s },", sycall_flags, wfn_cast) > sysent
+ printf("%s,\n\t %s, 0, 0 },", sycall_flags, wfn_cast) > sysent
for (i = 0; i < (33 - length(wfn_cast)) / 8; i++)
printf("\t") > sysent
printf("/* %d = %s%s */\n", syscall, compatwrap_, funcalias) > sysent
@@ -922,9 +986,9 @@
else
sys_stub = sys_nosys;
- printf("\t{ 0, 0, 0,\n\t %s },\t\t\t/* %d = %s */\n", \
+ printf("\t{ 0, 0, 0,\n\t %s, 0, 0 },\t\t\t/* %d = %s */\n", \
sys_stub, syscall, comment) > sysent
- printf("\t{ 0, 0, SYCALL_NOSYS,\n\t %s },\t\t/* %d = %s */\n", \
+ printf("\t{ 0, 0, SYCALL_NOSYS,\n\t %s, 0, 0 },\t\t/* %d = %s */\n", \
"(sy_call_t *)rumpns_enosys", syscall, comment) > rumpsysent
printf("\t/* %3d */\t\"#%d (%s)\",\n", syscall, syscall, comment) \
> sysnamesbottom
@@ -989,9 +1053,9 @@
exit 1
}
while (syscall < nsysent) {
- printf("\t{ 0, 0, 0,\n\t %s },\t\t\t/* %d = filler */\n", \
+ printf("\t{ 0, 0, 0,\n\t %s, 0, 0 },\t\t\t/* %d = filler */\n", \
sys_nosys, syscall) > sysent
- printf("\t{ 0, 0, SYCALL_NOSYS,\n\t %s },\t\t/* %d = filler */\n", \
+ printf("\t{ 0, 0, SYCALL_NOSYS,\n\t %s, 0, 0 },\t\t/* %d = filler */\n", \
"(sy_call_t *)rumpns_enosys", syscall) > rumpsysent
printf("\t/* %3d */\t\"# filler\",\n", syscall) \
> sysnamesbottom
@@ -1009,6 +1073,9 @@
printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, maxsyscall) > sysnumhdr
if (nsysent)
printf("#define\t%sNSYSENT\t%d\n", constprefix, nsysent) > sysnumhdr
+ printf "\tdefault:\n\t\t*n_args = 0;\n\t\tbreak;\n\t};\n}\n" > systrace
+ printf "\tdefault:\n\t\tbreak;\n\t};\n\tif (p != NULL)\n\t\tstrlcpy(desc, p, descsz);\n}\n" > systracetmp
+ printf "\tdefault:\n\t\tbreak;\n\t};\n\tif (p != NULL)\n\t\tstrlcpy(desc, p, descsz);\n}\n" > systraceret
} '
cat $sysprotos >> $sysarghdr
@@ -1026,5 +1093,8 @@
#chmod 444 $sysnames $sysnumhdr $syssw
+cat $systracetmp >> $systrace
+cat $systraceret >> $systrace
+
echo Generated following files:
-echo $sysarghdr $sysnumhdr $syssw $sysnames $rumpcalls $rumpcallshdr $rumpsysmap
+echo $sysarghdr $sysnumhdr $syssw $sysnames $systrace $rumpcalls $rumpcallshdr $rumpsysmap
Index: kern/sys_syscall.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_syscall.c,v
retrieving revision 1.10
diff -u -u -r1.10 sys_syscall.c
--- kern/sys_syscall.c 5 May 2012 19:44:02 -0000 1.10
+++ kern/sys_syscall.c 7 Mar 2015 07:05:23 -0000
@@ -56,10 +56,9 @@
struct proc *p = l->l_proc;
int code;
int error;
- int narg;
#ifdef NETBSD32_SYSCALL
register_t args64[SYS_MAXSYSARGS];
- int i;
+ int i, narg;
#define TRACE_ARGS args64
#else
#define TRACE_ARGS &SCARG(uap, args[0])
@@ -77,17 +76,17 @@
if (__predict_true(!p->p_trace_enabled))
return sy_call(callp, l, &uap->args, rval);
- narg = callp->sy_narg;
#ifdef NETBSD32_SYSCALL
+ narg = callp->sy_narg;
for (i = 0; i < narg; i++)
args64[i] = SCARG(uap, args[i]);
#endif
- error = trace_enter(code, TRACE_ARGS, narg);
+ error = trace_enter(code, callp, TRACE_ARGS);
if (__predict_false(error != 0))
return error;
error = sy_call(callp, l, &uap->args, rval);
- trace_exit(code, rval, error);
+ trace_exit(code, callp, &uap->args, rval, error);
return error;
#undef TRACE_ARGS
Index: kern/syscalls.c
===================================================================
RCS file: /cvsroot/src/sys/kern/syscalls.c,v
retrieving revision 1.280
diff -u -u -r1.280 syscalls.c
--- kern/syscalls.c 22 Feb 2015 00:53:28 -0000 1.280
+++ kern/syscalls.c 7 Mar 2015 07:05:23 -0000
@@ -1,4 +1,4 @@
-/* $NetBSD: syscalls.c,v 1.280 2015/02/22 00:53:28 christos Exp $ */
+/* $NetBSD$ */
/*
* System call names.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: syscalls.c,v 1.280 2015/02/22 00:53:28 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD$");
#if defined(_KERNEL_OPT)
#include "opt_modular.h"
Index: kern/syscalls.conf
===================================================================
RCS file: /cvsroot/src/sys/kern/syscalls.conf,v
retrieving revision 1.21
diff -u -u -r1.21 syscalls.conf
--- kern/syscalls.conf 16 Aug 2014 17:24:29 -0000 1.21
+++ kern/syscalls.conf 7 Mar 2015 07:05:23 -0000
@@ -3,6 +3,7 @@
sysnames="syscalls.c"
sysnumhdr="../sys/syscall.h"
syssw="init_sysent.c"
+systrace="systrace_args.c"
sysarghdr="../sys/syscallargs.h"
sysarghdrextra='#include <sys/mount.h>\n#ifndef RUMP_CLIENT\n#include <sys/sched.h>\n#endif\n#include <sys/socket.h>\n\n'
sysalign=1
Index: sys/param.h
===================================================================
RCS file: /cvsroot/src/sys/sys/param.h,v
retrieving revision 1.465
diff -u -u -r1.465 param.h
--- sys/param.h 14 Feb 2015 12:59:02 -0000 1.465
+++ sys/param.h 7 Mar 2015 07:05:23 -0000
@@ -63,7 +63,7 @@
* 2.99.9 (299000900)
*/
-#define __NetBSD_Version__ 799000500 /* NetBSD 7.99.5 */
+#define __NetBSD_Version__ 799000600 /* NetBSD 7.99.6 */
#define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \
(m) * 1000000) + (p) * 100) <= __NetBSD_Version__)
Index: sys/proc.h
===================================================================
RCS file: /cvsroot/src/sys/sys/proc.h,v
retrieving revision 1.320
diff -u -u -r1.320 proc.h
--- sys/proc.h 21 Feb 2014 22:06:48 -0000 1.320
+++ sys/proc.h 7 Mar 2015 07:05:23 -0000
@@ -177,6 +177,9 @@
size_t e_ucsize; /* size of ucontext_t */
void (*e_startlwp)(void *);
+
+ /* Dtrace argument converter */
+ void (*e_dtrace_args)(int, void *, uint64_t *, int *);
};
/*
Index: sys/syscallvar.h
===================================================================
RCS file: /cvsroot/src/sys/sys/syscallvar.h,v
retrieving revision 1.9
diff -u -u -r1.9 syscallvar.h
--- sys/syscallvar.h 4 Mar 2014 03:24:03 -0000 1.9
+++ sys/syscallvar.h 7 Mar 2015 07:05:23 -0000
@@ -36,6 +36,10 @@
#error nothing of interest to userspace here
#endif
+#if defined(_KERNEL) && defined(_KERNEL_OPT)
+#include "opt_dtrace.h"
+#endif
+
#include <sys/systm.h>
#include <sys/proc.h>
@@ -72,8 +76,13 @@
(sy->sy_flags & SYCALL_INDIRECT) == 0;
int error;
- if (__predict_true(!do_trace)
- || (error = trace_enter(code, uap, sy->sy_narg)) == 0) {
+#ifdef KDTRACE_HOOKS
+#define KDTRACE_ENTRY(a) (a)
+#else
+#define KDTRACE_ENTRY(a) (0)
+#endif
+ if (__predict_true(!(do_trace || KDTRACE_ENTRY(sy->sy_entry)))
+ || (error = trace_enter(code, sy, uap)) == 0) {
rval[0] = 0;
#if !defined(__mips__) && !defined(__m68k__)
/*
@@ -85,8 +94,8 @@
error = sy_call(sy, l, uap, rval);
}
- if (__predict_false(do_trace)) {
- trace_exit(code, rval, error);
+ if (__predict_false(do_trace || KDTRACE_ENTRY(sy->sy_return))) {
+ trace_exit(code, sy, uap, rval, error);
}
return error;
}
Index: sys/systm.h
===================================================================
RCS file: /cvsroot/src/sys/sys/systm.h,v
retrieving revision 1.266
diff -u -u -r1.266 systm.h
--- sys/systm.h 3 Aug 2014 12:49:32 -0000 1.266
+++ sys/systm.h 7 Mar 2015 07:05:23 -0000
@@ -57,6 +57,7 @@
struct clockframe;
struct lwp;
struct proc;
+struct sysent;
struct timeval;
struct tty;
struct uio;
@@ -115,11 +116,21 @@
typedef int sy_call_t(struct lwp *, const void *, register_t *);
+/* Used by the machine dependent syscall() code. */
+typedef void (*systrace_probe_func_t)(uint32_t, int, const struct sysent *,
+ const void *, register_t);
+
+typedef void (*systrace_args_func_t)(int, void *, uint64_t *, int *);
+
+extern systrace_probe_func_t systrace_probe_func;
+
extern struct sysent { /* system call table */
short sy_narg; /* number of args */
short sy_argsize; /* total size of arguments */
int sy_flags; /* flags. see below */
sy_call_t *sy_call; /* implementing function */
+ uint32_t sy_entry; /* DTrace entry ID for systrace. */
+ uint32_t sy_return; /* DTrace return ID for systrace. */
} sysent[];
extern int nsysent;
#if BYTE_ORDER == BIG_ENDIAN
@@ -388,8 +399,9 @@
*/
#ifdef _KERNEL
bool trace_is_enabled(struct proc *);
-int trace_enter(register_t, const register_t *, int);
-void trace_exit(register_t, register_t [], int);
+int trace_enter(register_t, const struct sysent *, const void *);
+void trace_exit(register_t, const struct sysent *, const void *,
+ register_t [], int);
#endif
int uiomove(void *, size_t, struct uio *);
>
Home |
Main Index |
Thread Index |
Old Index