Date: Mon, 15 Mar 2010 14:10:33 -0400 From: Jung-uk Kim <jkim@FreeBSD.org> To: freebsd-hackers@freebsd.org Cc: Kostik Belousov <kostikbel@gmail.com>, Marcel Moolenaar <xcllnt@mac.com> Subject: [RFC] DTrace SYSCALL provider (was Re: [RFC] Saving the latest errno from syscalls.) Message-ID: <201003151410.35959.jkim@FreeBSD.org> In-Reply-To: <201003121332.16979.jkim@FreeBSD.org> References: <201003111624.51018.jkim@FreeBSD.org> <20100312092932.GJ2489@deviant.kiev.zoral.com.ua> <201003121332.16979.jkim@FreeBSD.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--Boundary-00=_bgnnLsw6je1beqf Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline On Friday 12 March 2010 01:32 pm, Jung-uk Kim wrote: > On Friday 12 March 2010 04:29 am, Kostik Belousov wrote: > > On Thu, Mar 11, 2010 at 06:15:07PM -0500, Jung-uk Kim wrote: > > > On Thursday 11 March 2010 04:55 pm, Marcel Moolenaar wrote: > > > > On Mar 11, 2010, at 1:24 PM, Jung-uk Kim wrote: > > > > > While I was debugging syscalls, I found a very useful field > > > > > in struct thread, td_errno. It seems it was added for > > > > > dtrace but it is only populated on amd64 and i386. Is the > > > > > attached patch acceptable for maintainers of other > > > > > platforms? > > > > > > > > Isn't it better to do it in cpu_set_syscall_retval()? > > > > That way you catch all cases, plus you can save the > > > > translated error as well... > > > > > > I just took amd64/i386 as an example and I was not sure whether > > > it was meant to store translated error or not. Does anyone > > > with DTrace internal knowledge answer the question? > > > > I do not know that much about DTrace, but it seems that setting > > td_errno in cpu_set_syscall_retval() is too late. Dtrace has a > > probe after the syscall return, and it is called right before > > cpu_set_syscall_retval() can be reasonably called. The probe only > > issued for syscall that goes into sysent. > > Ah, I can see that now. So, if/when we implement DTrace SYSCALL > provider for other arches, this is the right place. :-) I went ahead and implemented DTrace SYSCALL providers for non-x86 arches. It passes 'make universe' test but I don't know if it works. Can maintainers of other arches test or review the attached patch? Thanks! Jung-uk Kim --Boundary-00=_bgnnLsw6je1beqf Content-Type: text/plain; charset="iso-8859-1"; name="dtrace_syscall.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="dtrace_syscall.diff" Index: sys/arm/arm/trap.c =================================================================== --- sys/arm/arm/trap.c (revision 205172) +++ sys/arm/arm/trap.c (working copy) @@ -122,7 +122,18 @@ __FBSDID("$FreeBSD$"); #include <sys/kdb.h> #endif +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + + void swi_handler(trapframe_t *); void undefinedinstruction(trapframe_t *); @@ -925,9 +936,36 @@ syscall(struct thread *td, trapframe_t *frame, u_i td->td_retval[1] = 0; STOPEVENT(p, S_SCE, callp->sy_narg); PTRACESTOP_SC(p, td, S_PT_SCE); + +#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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_entry != 0) + (*systrace_probe_func)(sa.callp->sy_entry, sa.code, + sa.callp, sa.args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, args); AUDIT_SYSCALL_EXIT(error, td); + + /* Save the latest error return value. */ + 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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_return != 0) + (*systrace_probe_func)(sa.callp->sy_return, sa.code, + sa.callp, sa.args); +#endif + KASSERT(td->td_ar == NULL, ("returning from syscall with td_ar set!")); } Index: sys/powerpc/booke/trap.c =================================================================== --- sys/powerpc/booke/trap.c (revision 205172) +++ sys/powerpc/booke/trap.c (working copy) @@ -75,6 +75,17 @@ __FBSDID("$FreeBSD$"); #include <machine/trap.h> #include <machine/spr.h> +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + #ifdef FPU_EMU #include <powerpc/fpu/fpu_extern.h> #endif @@ -409,10 +420,35 @@ syscall(struct trapframe *frame) PTRACESTOP_SC(p, td, S_PT_SCE); +#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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_entry != 0) + (*systrace_probe_func)(sa.callp->sy_entry, sa.code, + sa.callp, sa.args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, params); AUDIT_SYSCALL_EXIT(error, td); + /* Save the latest error return value. */ + 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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_return != 0) + (*systrace_probe_func)(sa.callp->sy_return, sa.code, + sa.callp, sa.args); +#endif + CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", p->p_comm, syscallnames[code], td->td_retval[0]); } Index: sys/powerpc/aim/trap.c =================================================================== --- sys/powerpc/aim/trap.c (revision 205172) +++ sys/powerpc/aim/trap.c (working copy) @@ -77,6 +77,17 @@ __FBSDID("$FreeBSD$"); #include <machine/spr.h> #include <machine/sr.h> +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + static void trap_fatal(struct trapframe *frame); static void printtrap(u_int vector, struct trapframe *frame, int isfatal, int user); @@ -405,10 +416,35 @@ syscall(struct trapframe *frame) PTRACESTOP_SC(p, td, S_PT_SCE); +#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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_entry != 0) + (*systrace_probe_func)(sa.callp->sy_entry, sa.code, + sa.callp, sa.args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, params); AUDIT_SYSCALL_EXIT(error, td); + /* Save the latest error return value. */ + 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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_return != 0) + (*systrace_probe_func)(sa.callp->sy_return, sa.code, + sa.callp, sa.args); +#endif + CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", td->td_name, syscallnames[code], td->td_retval[0]); } Index: sys/sparc64/sparc64/trap.c =================================================================== --- sys/sparc64/sparc64/trap.c (revision 205172) +++ sys/sparc64/sparc64/trap.c (working copy) @@ -94,6 +94,17 @@ __FBSDID("$FreeBSD$"); #include <machine/tsb.h> #include <machine/watch.h> +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + struct syscall_args { u_long code; struct sysent *callp; @@ -648,10 +659,35 @@ syscall(struct trapframe *tf) td->td_retval[1] = 0; } +#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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_entry != 0) + (*systrace_probe_func)(sa.callp->sy_entry, sa.code, + sa.callp, sa.args); +#endif + AUDIT_SYSCALL_ENTER(sa.code, td); error = (*sa.callp->sy_call)(td, sa.argp); AUDIT_SYSCALL_EXIT(error, td); + /* Save the latest error return value. */ + 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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_return != 0) + (*systrace_probe_func)(sa.callp->sy_return, sa.code, + sa.callp, sa.args); +#endif + CTR5(KTR_SYSC, "syscall: p=%p error=%d %s return %#lx %#lx", p, error, syscallnames[sa.code], td->td_retval[0], td->td_retval[1]); Index: sys/ia64/ia64/trap.c =================================================================== --- sys/ia64/ia64/trap.c (revision 205172) +++ sys/ia64/ia64/trap.c (working copy) @@ -76,6 +76,17 @@ __FBSDID("$FreeBSD$"); #include <ia64/disasm/disasm.h> +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + static int print_usertrap = 0; SYSCTL_INT(_machdep, OID_AUTO, print_usertrap, CTLFLAG_RW, &print_usertrap, 0, ""); @@ -970,10 +981,35 @@ syscall(struct trapframe *tf) PTRACESTOP_SC(p, td, S_PT_SCE); +#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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_entry != 0) + (*systrace_probe_func)(sa.callp->sy_entry, sa.code, + sa.callp, sa.args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, args); AUDIT_SYSCALL_EXIT(error, td); + /* Save the latest error return value. */ + 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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_return != 0) + (*systrace_probe_func)(sa.callp->sy_return, sa.code, + sa.callp, sa.args); +#endif + cpu_set_syscall_retval(td, error); td->td_syscalls++; Index: sys/ia64/ia32/ia32_trap.c =================================================================== --- sys/ia64/ia32/ia32_trap.c (revision 205172) +++ sys/ia64/ia32/ia32_trap.c (working copy) @@ -48,6 +48,17 @@ __FBSDID("$FreeBSD$"); #include <security/audit/audit.h> +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + extern char *syscallnames[]; static void @@ -124,9 +135,34 @@ ia32_syscall(struct trapframe *tf) PTRACESTOP_SC(p, td, S_PT_SCE); +#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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_entry != 0) + (*systrace_probe_func)(sa.callp->sy_entry, sa.code, + sa.callp, sa.args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, args64); AUDIT_SYSCALL_EXIT(error, td); + + /* Save the latest error return value. */ + 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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_return != 0) + (*systrace_probe_func)(sa.callp->sy_return, sa.code, + sa.callp, sa.args); +#endif } switch (error) { Index: sys/sun4v/sun4v/trap.c =================================================================== --- sys/sun4v/sun4v/trap.c (revision 205172) +++ sys/sun4v/sun4v/trap.c (working copy) @@ -96,6 +96,17 @@ #include <security/audit/audit.h> +#ifdef KDTRACE_HOOKS +#include <sys/dtrace_bsd.h> + +/* + * This is a hook which is initialised by the systrace module + * when it is loaded. This keeps the DTrace syscall provider + * implementation opaque. + */ +systrace_probe_func_t systrace_probe_func; +#endif + void trap(struct trapframe *tf, int64_t type, uint64_t data); void syscall(struct trapframe *tf); @@ -662,10 +673,35 @@ syscall(struct trapframe *tf) PTRACESTOP_SC(p, td, S_PT_SCE); +#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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_entry != 0) + (*systrace_probe_func)(sa.callp->sy_entry, sa.code, + sa.callp, sa.args); +#endif + AUDIT_SYSCALL_ENTER(code, td); error = (*callp->sy_call)(td, argp); AUDIT_SYSCALL_EXIT(error, td); + /* Save the latest error return value. */ + 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. + */ + if (systrace_probe_func != NULL && sa.callp->sy_return != 0) + (*systrace_probe_func)(sa.callp->sy_return, sa.code, + sa.callp, sa.args); +#endif + CTR5(KTR_SYSC, "syscall: p=%p error=%d %s return %#lx %#lx ", p, error, syscallnames[code], td->td_retval[0], td->td_retval[1]); --Boundary-00=_bgnnLsw6je1beqf--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201003151410.35959.jkim>