[PATCH] Fix types of arguments to dtrace syscall return probes
Ryan Stone
rysto32 at gmail.com
Sat Nov 5 20:30:50 UTC 2011
Currently if you try to use the args[] array passed to a syscall
return probe, you get variables with the wrong type. This is because
the systrace implementation is currently using the same function to
provide the same argument types for both the entry and return probes,
which is completely wrong. For example:
# dtrace -v -l -n syscall::mmap:return
ID PROVIDER MODULE FUNCTION NAME
32159 syscall mmap return
Probe Description Attributes
Identifier Names: Private
Data Semantics: Private
Dependency Class: ISA
Argument Attributes
Identifier Names: Private
Data Semantics: Private
Dependency Class: ISA
Argument Types
args[0]: caddr_t
args[1]: size_t
args[2]: int
args[3]: int
args[4]: int
args[5]: off_t
The following patch[1] fixes this and provides the correct type to all
return probes. For example,
# dtrace -l -v -n syscall::mmap:return
ID PROVIDER MODULE FUNCTION NAME
2000 syscall freebsd mmap return
Probe Description Attributes
Identifier Names: Private
Data Semantics: Private
Dependency Class: Unknown
Argument Attributes
Identifier Names: Private
Data Semantics: Private
Dependency Class: ISA
Argument Types
args[0]: caddr_t
args[1]: caddr_t
The patch:
diff --git a/sys/cddl/dev/systrace/systrace.c b/sys/cddl/dev/systrace/systrace.c
index cc48747..31c11c2 100644
--- a/sys/cddl/dev/systrace/systrace.c
+++ b/sys/cddl/dev/systrace/systrace.c
@@ -220,8 +220,12 @@ systrace_getargdesc(void *arg, dtrace_id_t id,
void *parg, dtrace_argdesc_t *des
{
int sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
- systrace_setargdesc(sysnum, desc->dtargd_ndx, desc->dtargd_native,
- sizeof(desc->dtargd_native));
+ if (SYSTRACE_ISENTRY((uintptr_t)parg))
+ systrace_entry_setargdesc(sysnum, desc->dtargd_ndx,
+ desc->dtargd_native, sizeof(desc->dtargd_native));
+ else
+ systrace_return_setargdesc(sysnum, desc->dtargd_ndx,
+ desc->dtargd_native, sizeof(desc->dtargd_native));
if (desc->dtargd_native[0] == '\0')
desc->dtargd_ndx = DTRACE_ARGNONE;
diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh
index d1162b5..1f081ce 100644
--- a/sys/kern/makesyscalls.sh
+++ b/sys/kern/makesyscalls.sh
@@ -38,6 +38,7 @@ sysinc="sysinc.switch.$$"
sysarg="sysarg.switch.$$"
sysprotoend="sysprotoend.$$"
systracetmp="systrace.$$"
+systraceret="systraceret.$$"
if [ -r capabilities.conf ]; then
capenabled=`cat capabilities.conf | grep -v "^#" | grep -v "^$"`
@@ -46,9 +47,9 @@ else
capenabled=""
fi
-trap "rm $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4
$syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl
$sysent $sysinc $sysarg $sysprotoend $systracetmp" 0
+trap "rm $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4
$syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl
$sysent $sysinc $sysarg $sysprotoend $systracetmp $systraceret" 0
-touch $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4
$syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl
$sysent $sysinc $sysarg $sysprotoend $systracetmp
+touch $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4
$syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl
$sysent $sysinc $sysarg $sysprotoend $systracetmp $systraceret
case $# in
0) echo "usage: $0 input-file <config-file>" 1>&2
@@ -96,6 +97,7 @@ s/\$//g
sysmk = \"$sysmk\"
systrace = \"$systrace\"
systracetmp = \"$systracetmp\"
+ systraceret = \"$systraceret\"
compat = \"$compat\"
compat4 = \"$compat4\"
compat6 = \"$compat6\"
@@ -179,9 +181,12 @@ s/\$//g
printf "\tint64_t *iarg = (int64_t *) uarg;\n" > systrace
printf "\tswitch (sysnum) {\n" > systrace
- printf "static void\nsystrace_setargdesc(int sysnum,
int ndx, char *desc, size_t descsz)\n{\n\tconst char *p = NULL;\n" >
systracetmp
+ 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
+
next
}
NF == 0 || $1 ~ /^;/ {
@@ -202,6 +207,7 @@ s/\$//g
print > sysnames
print > systrace
print > systracetmp
+ print > systraceret
savesyscall = syscall
next
}
@@ -216,6 +222,7 @@ s/\$//g
print > sysnames
print > systrace
print > systracetmp
+ print > systraceret
syscall = savesyscall
next
}
@@ -230,6 +237,7 @@ s/\$//g
print > sysnames
print > systrace
print > systracetmp
+ print > systraceret
next
}
syscall != $1 {
@@ -303,7 +311,8 @@ s/\$//g
parserr($end, ")")
end--
- f++ #function return type
+ syscallret=$f
+ f++
funcname=$f
@@ -387,6 +396,7 @@ s/\$//g
parseline()
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 *p = params;\n",
argalias) > systrace
@@ -406,6 +416,10 @@ s/\$//g
argname[i], argtype[i]) > 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", syscallret) > 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
@@ -623,6 +637,7 @@ s/\$//g
> syshdr
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 $sysinc $sysent >> $syssw
@@ -633,4 +648,5 @@ cat $sysarg $sysdcl \
$syscompat7 $syscompat7dcl \
$sysaue $sysprotoend > $sysproto
cat $systracetmp >> $systrace
+cat $systraceret >> $systrace
[1] Can also be found at
http://people.freebsd.org/~rstone/patches/dtrace_syscall_ret.diff
More information about the freebsd-current
mailing list