[RFC] DTrace SYSCALL provider (was Re: [RFC] Saving the latest
errno from syscalls.)
Jung-uk Kim
jkim at FreeBSD.org
Mon Mar 15 18:10:54 UTC 2010
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
-------------- next part --------------
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]);
More information about the freebsd-hackers
mailing list