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