Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src DTrace: Add the Function Boundary Trace (FBT) provider modui...



details:   https://anonhg.NetBSD.org/src/rev/b94033362c53
branches:  trunk
changeset: 752952:b94033362c53
user:      darran <darran%NetBSD.org@localhost>
date:      Fri Mar 12 21:53:15 2010 +0000

description:
DTrace: Add the Function Boundary Trace (FBT) provider moduile.  This
module  instruments every function in the kernel with entry and exit
probes.  These probes are true zero-effect probes in that they don't
exist in the code until they are enabled.  The probes are enabled by
directly patching the function entry and exit points to make jumps into
the dtrace framework.
This gives us over 29,000 trace points in the kernel.

diffstat:

 distrib/sets/lists/modules/mi                       |    4 +-
 external/cddl/osnet/dev/fbt/fbt.c                   |  597 +++++++++++--------
 external/cddl/osnet/dist/uts/common/dtrace/dtrace.c |   17 +-
 sys/modules/dtrace/Makefile                         |    4 +-
 sys/modules/dtrace/fbt/Makefile                     |   12 +
 sys/sys/module.h                                    |    4 +-
 6 files changed, 392 insertions(+), 246 deletions(-)

diffs (truncated from 1167 to 300 lines):

diff -r 2da15793b3a9 -r b94033362c53 distrib/sets/lists/modules/mi
--- a/distrib/sets/lists/modules/mi     Fri Mar 12 21:43:10 2010 +0000
+++ b/distrib/sets/lists/modules/mi     Fri Mar 12 21:53:15 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.11 2010/03/03 16:13:42 tron Exp $
+# $NetBSD: mi,v 1.12 2010/03/12 21:53:16 darran Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -40,6 +40,8 @@
 ./@MODULEDIR@/exec_script/exec_script.kmod     base-kernel-modules     kmod
 ./@MODULEDIR@/ext2fs                           base-kernel-modules     kmod
 ./@MODULEDIR@/ext2fs/ext2fs.kmod               base-kernel-modules     kmod
+./@MODULEDIR@/fbt                              base-kernel-modules     kmod,dtrace
+./@MODULEDIR@/fbt/fbt.kmod                     base-kernel-modules     kmod,dtrace
 ./@MODULEDIR@/fdesc                            base-kernel-modules     kmod
 ./@MODULEDIR@/fdesc/fdesc.kmod                 base-kernel-modules     kmod
 ./@MODULEDIR@/ffs                              base-kernel-modules     kmod
diff -r 2da15793b3a9 -r b94033362c53 external/cddl/osnet/dev/fbt/fbt.c
--- a/external/cddl/osnet/dev/fbt/fbt.c Fri Mar 12 21:43:10 2010 +0000
+++ b/external/cddl/osnet/dev/fbt/fbt.c Fri Mar 12 21:53:15 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fbt.c,v 1.2 2010/02/21 01:46:33 darran Exp $   */
+/*     $NetBSD: fbt.c,v 1.3 2010/03/12 21:53:15 darran Exp $   */
 
 /*
  * CDDL HEADER START
@@ -21,6 +21,7 @@
  * CDDL HEADER END
  *
  * Portions Copyright 2006-2008 John Birrell jb%freebsd.org@localhost
+ * Portions Copyright 2010 Darran Hunt darran%NetBSD.org@localhost
  *
  * $FreeBSD: src/sys/cddl/dev/fbt/fbt.c,v 1.1.4.1 2009/08/03 08:13:06 kensmith Exp $
  *
@@ -38,9 +39,9 @@
 #include <sys/cpuvar.h>
 #include <sys/fcntl.h>
 #include <sys/filio.h>
-#include <sys/kdb.h>
 #include <sys/kernel.h>
 #include <sys/kmem.h>
+#include <sys/cpu.h>
 #include <sys/kthread.h>
 #include <sys/limits.h>
 #include <sys/linker.h>
@@ -48,20 +49,30 @@
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/mutex.h>
-#include <sys/pcpu.h>
 #include <sys/poll.h>
 #include <sys/proc.h>
 #include <sys/selinfo.h>
-#include <sys/smp.h>
 #include <sys/syscall.h>
-#include <sys/sysent.h>
-#include <sys/sysproto.h>
 #include <sys/uio.h>
 #include <sys/unistd.h>
 #include <machine/stdarg.h>
 
+#include <machine/cpu.h>
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+#if 0
+#include <x86/cpuvar.h>
+#endif
+#include <x86/cputypes.h>
+
+#define ELFSIZE ARCH_ELFSIZE
+#include <sys/exec_elf.h>
+
 #include <sys/dtrace.h>
 #include <sys/dtrace_bsd.h>
+#include <sys/kern_ctf.h>
+
+mod_ctf_t *modptr;
 
 MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing");
 
@@ -83,14 +94,14 @@
 #define        FBT_PATCHVAL            0xf0
 #endif
 
-static d_open_t        fbt_open;
+static dev_type_open(fbt_open);
 static int     fbt_unload(void);
 static void    fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
-static void    fbt_provide_module(void *, modctl_t *);
+static void    fbt_provide_module(void *, dtrace_modctl_t *);
 static void    fbt_destroy(void *, dtrace_id_t, void *);
-static void    fbt_enable(void *, dtrace_id_t, void *);
+static int     fbt_enable(void *, dtrace_id_t, void *);
 static void    fbt_disable(void *, dtrace_id_t, void *);
-static void    fbt_load(void *);
+static void    fbt_load(void);
 static void    fbt_suspend(void *, dtrace_id_t, void *);
 static void    fbt_resume(void *, dtrace_id_t, void *);
 
@@ -99,10 +110,10 @@
 #define        FBT_ADDR2NDX(addr)      ((((uintptr_t)(addr)) >> 4) & fbt_probetab_mask)
 #define        FBT_PROBETAB_SIZE       0x8000          /* 32k entries -- 128K total */
 
-static struct cdevsw fbt_cdevsw = {
-       .d_version      = D_VERSION,
-       .d_open         = fbt_open,
-       .d_name         = "fbt",
+static const struct cdevsw fbt_cdevsw = {
+       fbt_open, noclose, noread, nowrite, noioctl,
+       nostop, notty, nopoll, nommap, nokqfilter,
+       D_OTHER
 };
 
 static dtrace_pattr_t fbt_attr = {
@@ -135,7 +146,7 @@
        uintptr_t       fbtp_roffset;
        dtrace_id_t     fbtp_id;
        const char      *fbtp_name;
-       modctl_t        *fbtp_ctl;
+       dtrace_modctl_t *fbtp_ctl;
        int             fbtp_loadcnt;
        int             fbtp_primary;
        int             fbtp_invop_cnt;
@@ -164,10 +175,11 @@
        }
 }
 
+
 static int
 fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
 {
-       solaris_cpu_t *cpu = &solaris_cpu[curcpu];
+       solaris_cpu_t *cpu = &solaris_cpu[cpu_number()];
        uintptr_t stack0, stack1, stack2, stack3, stack4;
        fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
 
@@ -224,15 +236,20 @@
 }
 
 static int
-fbt_provide_module_function(linker_file_t lf, int symindx,
-    linker_symval_t *symval, void *opaque)
+fbt_provide_module_cb(const char *name, int symindx, void *value,
+       uint32_t size, int type, void *opaque)
 {
-       char *modname = opaque;
-       const char *name = symval->name;
        fbt_probe_t *fbt, *retfbt;
+       u_int8_t *instr, *limit;
+       dtrace_modctl_t *mod = opaque;
+       const char *modname = mod->mod_info->mi_name;
        int j;
-       int size;
-       u_int8_t *instr, *limit;
+       int ind;
+
+       /* got a function? */
+       if (ELF_ST_TYPE(type) != STT_FUNC) {
+           return 0;
+       }
 
        if (strncmp(name, "dtrace_", 7) == 0 &&
            strncmp(name, "dtrace_safe_", 12) != 0) {
@@ -248,10 +265,8 @@
        if (name[0] == '_' && name[1] == '_')
                return (0);
 
-       size = symval->size;
-
-       instr = (u_int8_t *) symval->value;
-       limit = (u_int8_t *) symval->value + symval->size;
+       instr = (u_int8_t *) value;
+       limit = (u_int8_t *) value + size;
 
 #ifdef __amd64__
        while (instr < limit) {
@@ -273,23 +288,24 @@
                return (0);
        }
 #else
-       if (instr[0] != FBT_PUSHL_EBP)
+       if (instr[0] != FBT_PUSHL_EBP) {
                return (0);
+       }
 
        if (!(instr[1] == FBT_MOVL_ESP_EBP0_V0 &&
            instr[2] == FBT_MOVL_ESP_EBP1_V0) &&
            !(instr[1] == FBT_MOVL_ESP_EBP0_V1 &&
-           instr[2] == FBT_MOVL_ESP_EBP1_V1))
+           instr[2] == FBT_MOVL_ESP_EBP1_V1)) {
                return (0);
+       }
 #endif
-
        fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
        fbt->fbtp_name = name;
        fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
            name, FBT_ENTRY, 3, fbt);
        fbt->fbtp_patchpoint = instr;
-       fbt->fbtp_ctl = lf;
-       fbt->fbtp_loadcnt = lf->loadcnt;
+       fbt->fbtp_ctl = mod;
+       /* fbt->fbtp_loadcnt = lf->loadcnt; */
        fbt->fbtp_rval = DTRACE_INVOP_PUSHL_EBP;
        fbt->fbtp_savedval = *instr;
        fbt->fbtp_patchval = FBT_PATCHVAL;
@@ -297,130 +313,132 @@
 
        fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
        fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
-
-       lf->fbt_nentries++;
+       mod->mod_fbtentries++;
 
        retfbt = NULL;
-again:
-       if (instr >= limit)
-               return (0);
+
+       while (instr < limit) {
+               if (instr >= limit)
+                       return (0);
 
-       /*
-        * If this disassembly fails, then we've likely walked off into
-        * a jump table or some other unsuitable area.  Bail out of the
-        * disassembly now.
-        */
-       if ((size = dtrace_instr_size(instr)) <= 0)
-               return (0);
+               /*
+                * If this disassembly fails, then we've likely walked off into
+                * a jump table or some other unsuitable area.  Bail out of the
+                * disassembly now.
+                */
+               if ((size = dtrace_instr_size(instr)) <= 0)
+                       return (0);
 
 #ifdef __amd64__
-       /*
-        * We only instrument "ret" on amd64 -- we don't yet instrument
-        * ret imm16, largely because the compiler doesn't seem to
-        * (yet) emit them in the kernel...
-        */
-       if (*instr != FBT_RET) {
-               instr += size;
-               goto again;
-       }
+               /*
+                * We only instrument "ret" on amd64 -- we don't yet instrument
+                * ret imm16, largely because the compiler doesn't seem to
+                * (yet) emit them in the kernel...
+                */
+               if (*instr != FBT_RET) {
+                       instr += size;
+                       continue;
+               }
 #else
-       if (!(size == 1 &&
-           (*instr == FBT_POPL_EBP || *instr == FBT_LEAVE) &&
-           (*(instr + 1) == FBT_RET ||
-           *(instr + 1) == FBT_RET_IMM16))) {
-               instr += size;
-               goto again;
-       }
+               if (!(size == 1 &&
+                   (*instr == FBT_POPL_EBP || *instr == FBT_LEAVE) &&
+                   (*(instr + 1) == FBT_RET ||
+                   *(instr + 1) == FBT_RET_IMM16))) {
+                       instr += size;
+                       continue;
+               }
 #endif
 
-       /*
-        * We (desperately) want to avoid erroneously instrumenting a
-        * jump table, especially given that our markers are pretty
-        * short:  two bytes on x86, and just one byte on amd64.  To
-        * determine if we're looking at a true instruction sequence
-        * or an inline jump table that happens to contain the same
-        * byte sequences, we resort to some heuristic sleeze:  we
-        * treat this instruction as being contained within a pointer,
-        * and see if that pointer points to within the body of the
-        * function.  If it does, we refuse to instrument it.
-        */
-       for (j = 0; j < sizeof (uintptr_t); j++) {
-               caddr_t check = (caddr_t) instr - j;
-               uint8_t *ptr;
+               /*
+                * We (desperately) want to avoid erroneously instrumenting a
+                * jump table, especially given that our markers are pretty
+                * short:  two bytes on x86, and just one byte on amd64.  To
+                * determine if we're looking at a true instruction sequence
+                * or an inline jump table that happens to contain the same
+                * byte sequences, we resort to some heuristic sleeze:  we
+                * treat this instruction as being contained within a pointer,
+                * and see if that pointer points to within the body of the
+                * function.  If it does, we refuse to instrument it.
+                */



Home | Main Index | Thread Index | Old Index