[DTrace-devel] [PATCH 8/8] fbt, rawfbt: consolidate code to avoid duplication

Kris Van Hees kris.van.hees at oracle.com
Fri Mar 7 21:34:41 UTC 2025


After optimizing both fbt and rawfbt providers, the resulting code has
a significant amount of duplication.  The rawfbt provider can now be
defined in terms of the kprobe-based fbt provider functions.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/Build            |   1 -
 libdtrace/dt_prov_fbt.c    | 131 +++++++++----
 libdtrace/dt_prov_rawfbt.c | 393 -------------------------------------
 3 files changed, 96 insertions(+), 429 deletions(-)
 delete mode 100644 libdtrace/dt_prov_rawfbt.c

diff --git a/libdtrace/Build b/libdtrace/Build
index 51e0f078..7e6e8a38 100644
--- a/libdtrace/Build
+++ b/libdtrace/Build
@@ -55,7 +55,6 @@ libdtrace-build_SOURCES = dt_aggregate.c \
 			  dt_prov_lockstat.c \
 			  dt_prov_proc.c \
 			  dt_prov_profile.c \
-			  dt_prov_rawfbt.c \
 			  dt_prov_rawtp.c \
 			  dt_prov_sched.c \
 			  dt_prov_sdt.c \
diff --git a/libdtrace/dt_prov_fbt.c b/libdtrace/dt_prov_fbt.c
index d837e14d..93ed270e 100644
--- a/libdtrace/dt_prov_fbt.c
+++ b/libdtrace/dt_prov_fbt.c
@@ -6,17 +6,26 @@
  *
  * The Function Boundary Tracing (FBT) provider for DTrace.
  *
- * FBT probes are exposed by the kernel as kprobes.  They are listed in the
- * TRACEFS/available_filter_functions file.  Some kprobes are associated with
- * a specific kernel module, while most are in the core kernel.
+ * Kernnel functions can be traced through fentry/fexit probes (when available)
+ * and kprobes.  The FBT provider supports both implementations and will use
+ * fentry/fexit probes if the kernel supports them, and fallback to kprobes
+ * otherwise.  The FBT provider does not support tracing synthetic functions
+ * (i.e. compiler-generated functions with a . in their name).
+ *
+ * The rawfbt provider implements a variant of the FBT provider and always uses
+ * kprobes.  This provider allow tracing of synthetic function.
  *
  * Mapping from event name to DTrace probe name:
  *
  *	<name>					fbt:vmlinux:<name>:entry
  *						fbt:vmlinux:<name>:return
+ *						rawfbt:vmlinux:<name>:entry
+ *						rawfbt:vmlinux:<name>:return
  *   or
  *	<name> [<modname>]			fbt:<modname>:<name>:entry
  *						fbt:<modname>:<name>:return
+ *						rawfbt:<modname>:<name>:entry
+ *						rawfbt:<modname>:<name>:return
  */
 #include <assert.h>
 #include <errno.h>
@@ -57,18 +66,19 @@ static const dtrace_pattr_t	pattr = {
 
 dt_provimpl_t			dt_fbt_fprobe;
 dt_provimpl_t			dt_fbt_kprobe;
+dt_provimpl_t			dt_rawfbt;
 
 /*
- * Create the fbt provider.
+ * Create the fbt and rawfbt providers.
  */
 static int populate(dtrace_hdl_t *dtp)
 {
-	dt_provider_t		*prv;
-
 	dt_fbt = BPF_HAS(dtp, BPF_FEAT_FENTRY) ? dt_fbt_fprobe : dt_fbt_kprobe;
 
-	prv = dt_provider_create(dtp, prvname, &dt_fbt, &pattr, NULL);
-	if (prv == NULL)
+	if (dt_provider_create(dtp, dt_fbt.name, &dt_fbt, &pattr,
+			       NULL) == NULL ||
+	    dt_provider_create(dtp, dt_rawfbt.name, &dt_rawfbt, &pattr,
+			       NULL) == NULL)
 		return -1;			/* errno already set */
 
 	return 0;
@@ -107,8 +117,6 @@ static int provide(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
 	dt_htab_next_t		*it = NULL;
 	dtrace_probedesc_t	pd;
 
-	dt_modsym_mark_traceable(dtp);
-
 	/*
 	 * Nothing to do if a probe name is specified and cannot match 'entry'
 	 * or 'return'.
@@ -120,8 +128,11 @@ static int provide(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
 	if (prb == 0)
 		return 0;
 
-	/* Synthetic function names are not supported for FBT. */
-	if (strchr(pdp->fun, '.'))
+	/*
+	 * Unless we are dealing with a rawfbt probe, synthetic functions are
+	 * not supported.
+	 */
+	if (strcmp(pdp->prv, dt_rawfbt.name) != 0 && strchr(pdp->fun, '.'))
 		return 0;
 
 	/*
@@ -134,6 +145,14 @@ static int provide(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
 			return 0;
 	}
 
+	/*
+	 * Ensure that kernel symbols that are FBT-traceable are marked as
+	 * such.  We don't do this earlier in this function so that the
+	 * preceding tests have the greatest opportunity to avoid doing this
+	 * unnecessarily.
+	 */
+	dt_modsym_mark_traceable(dtp);
+
 	/*
 	 * If we have an explicit function name, we start with a basic symbol
 	 * name lookup.
@@ -396,12 +415,12 @@ static int fprobe_prog_load(dtrace_hdl_t *dtp, const dt_probe_t *prp,
 \*******************************/
 
 /*
- * Generate a BPF trampoline for a FBT probe.
+ * Generate a BPF trampoline for a FBT (or rawfbt) probe.
  *
  * The trampoline function is called when a FBT probe triggers, and it must
  * satisfy the following prototype:
  *
- *	int dt_fbt(dt_pt_regs *regs)
+ *	int dt_(raw)fbt(dt_pt_regs *regs)
  *
  * The trampoline will populate a dt_dctx_t struct and then call the function
  * that implements the compiled D clause.  It returns 0 to the caller.
@@ -422,7 +441,7 @@ static int kprobe_trampoline(dt_pcb_t *pcb, uint_t exitlbl)
 		dt_cg_tramp_copy_rval_from_regs(pcb);
 
 		/*
-		 * fbt:::return arg0 should be the function offset for
+		 * (raw)fbt:::return arg0 should be the function offset for
 		 * return instruction.  Since we use kretprobes, however,
 		 * which do not fire until the function has returned to
 		 * its caller, information about the returning instruction
@@ -441,11 +460,28 @@ static int kprobe_trampoline(dt_pcb_t *pcb, uint_t exitlbl)
 
 static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 {
+	const char	*fun = prp->desc->fun;
+	char		*tpn = (char *)fun;
+	int		rc = -1;
+
 	if (!dt_tp_probe_has_info(prp)) {
 		char	*fn;
 		FILE	*f;
-		size_t	len;
-		int	fd, rc = -1;
+		int	fd;
+
+		/*
+		 * For rawfbt probes, we need to apply a . -> _ conversion to
+		 * ensure the tracepoint name is valid.
+		 */
+		if (strcmp(prp->desc->prv, dt_rawfbt.name) == 0) {
+			char	*p;
+
+			tpn = strdup(fun);
+			for (p = tpn; *p; p++) {
+				if (*p == '.')
+					*p = '_';
+			}
+		}
 
 		/*
 		 * Register the kprobe with the tracing subsystem.  This will
@@ -453,41 +489,42 @@ static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
 		 */
 		fd = open(KPROBE_EVENTS, O_WRONLY | O_APPEND);
 		if (fd == -1)
-			return -ENOENT;
+			goto out;
 
 		rc = dprintf(fd, "%c:" FBT_GROUP_FMT "/%s %s\n",
 			     prp->desc->prb[0] == 'e' ? 'p' : 'r',
-			     FBT_GROUP_DATA, prp->desc->fun, prp->desc->fun);
+			     FBT_GROUP_DATA, tpn, fun);
 		close(fd);
 		if (rc == -1)
-			return -ENOENT;
+			goto out;
 
 		/* create format file name */
-		len = snprintf(NULL, 0, "%s" FBT_GROUP_FMT "/%s/format",
-			       EVENTSFS, FBT_GROUP_DATA, prp->desc->fun) + 1;
-		fn = dt_alloc(dtp, len);
-		if (fn == NULL)
-			return -ENOENT;
-
-		snprintf(fn, len, "%s" FBT_GROUP_FMT "/%s/format", EVENTSFS,
-			 FBT_GROUP_DATA, prp->desc->fun);
+		if (asprintf(&fn, "%s" FBT_GROUP_FMT "/%s/format", EVENTSFS,
+			     FBT_GROUP_DATA, tpn) == -1)
+			goto out;
 
 		/* open format file */
 		f = fopen(fn, "r");
-		dt_free(dtp, fn);
+		free(fn);
 		if (f == NULL)
-			return -ENOENT;
+			goto out;
 
 		/* read event id from format file */
 		rc = dt_tp_probe_info(dtp, f, 0, prp, NULL, NULL);
 		fclose(f);
 
 		if (rc < 0)
-			return -ENOENT;
+			goto out;
 	}
 
 	/* attach BPF program to the probe */
-	return dt_tp_probe_attach(dtp, prp, bpf_fd);
+	rc = dt_tp_probe_attach(dtp, prp, bpf_fd);
+
+out:
+	if (tpn != prp->desc->fun)
+		free(tpn);
+
+	return rc == -1 ? -ENOENT : rc;
 }
 
 /*
@@ -503,7 +540,8 @@ static int kprobe_attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
  */
 static void kprobe_detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
 {
-	int		fd;
+	int	fd;
+	char	*tpn = (char *)prp->desc->fun;
 
 	if (!dt_tp_probe_has_info(prp))
 		return;
@@ -514,9 +552,20 @@ static void kprobe_detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
 	if (fd == -1)
 		return;
 
-	dprintf(fd, "-:" FBT_GROUP_FMT "/%s\n", FBT_GROUP_DATA,
-		prp->desc->fun);
+	if (strcmp(prp->desc->prv, dt_rawfbt.name) == 0) {
+		char	*p;
+
+		for (p = tpn; *p; p++) {
+			if (*p == '.')
+				*p = '_';
+		}
+	}
+
+	dprintf(fd, "-:" FBT_GROUP_FMT "/%s\n", FBT_GROUP_DATA, tpn);
 	close(fd);
+
+	if (tpn != prp->desc->fun)
+		free(tpn);
 }
 
 dt_provimpl_t	dt_fbt_fprobe = {
@@ -549,3 +598,15 @@ dt_provimpl_t	dt_fbt = {
 	.name		= prvname,
 	.populate	= &populate,
 };
+
+dt_provimpl_t	dt_rawfbt = {
+	.name		= "rawfbt",
+	.prog_type	= BPF_PROG_TYPE_KPROBE,
+	.populate	= &populate,
+	.provide	= &provide,
+	.load_prog	= &dt_bpf_prog_load,
+	.trampoline	= &kprobe_trampoline,
+	.attach		= &kprobe_attach,
+	.detach		= &kprobe_detach,
+	.probe_destroy	= &dt_tp_probe_destroy,
+};
diff --git a/libdtrace/dt_prov_rawfbt.c b/libdtrace/dt_prov_rawfbt.c
deleted file mode 100644
index 52152655..00000000
--- a/libdtrace/dt_prov_rawfbt.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Oracle Linux DTrace.
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
- * Licensed under the Universal Permissive License v 1.0 as shown at
- * http://oss.oracle.com/licenses/upl.
- *
- * The Raw Function Boundary Tracing provider for DTrace.
- *
- * The kernel provides kprobes to trace specific symbols.  They are listed in
- * the TRACEFS/available_filter_functions file.  Kprobes may be associated with
- * a symbol in the core kernel or with a symbol in a specific kernel module.
- * Whereas the fbt provider supports tracing regular symbols only, the rawfbt
- * provider also provides access to synthetic symbols, i.e. symbols created by
- * compiler optimizations.
- *
- * Mapping from event name to DTrace probe name:
- *
- *	<name>					rawfbt:vmlinux:<name>:entry
- *						rawfbt:vmlinux:<name>:return
- *   or
- *	<name> [<modname>]			rawfbt:<modname>:<name>:entry
- *						rawfbt:<modname>:<name>:return
- */
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <linux/bpf.h>
-#include <linux/btf.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <bpf_asm.h>
-
-#include "dt_btf.h"
-#include "dt_dctx.h"
-#include "dt_cg.h"
-#include "dt_module.h"
-#include "dt_provider_tp.h"
-#include "dt_probe.h"
-#include "dt_pt_regs.h"
-
-static const char		prvname[] = "rawfbt";
-
-#define KPROBE_EVENTS		TRACEFS "kprobe_events"
-
-#define FBT_GROUP_FMT		GROUP_FMT "_%s"
-#define FBT_GROUP_DATA		GROUP_DATA, prp->desc->prb
-
-static const dtrace_pattr_t	pattr = {
-{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-};
-
-/*
- * Create the rawfbt provider.
- */
-static int populate(dtrace_hdl_t *dtp)
-{
-	dt_provider_t		*prv;
-
-	prv = dt_provider_create(dtp, prvname, &dt_rawfbt, &pattr, NULL);
-	if (prv == NULL)
-		return -1;			/* errno already set */
-
-	return 0;
-}
-
-/* Create a probe (if it does not exist yet). */
-static int provide_probe(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
-{
-	dt_provider_t	*prv = dt_provider_lookup(dtp, pdp->prv);
-
-	if (prv == NULL)
-		return 0;
-	if (dt_probe_lookup(dtp, pdp) != NULL)
-		return 0;
-#ifdef DEBUG_FBT
-	if (dt_tp_probe_insert(dtp, prv, pdp->prv, pdp->mod, pdp->fun, pdp->prb)) {
-		fprintf(stderr, "%s(..., PROVIDE %s:%s:%s:%s) - ...\n", __func__, pdp->prv, pdp->mod, pdp->fun, pdp->prb);
-		return 1;
-	}
-#else
-	if (dt_tp_probe_insert(dtp, prv, pdp->prv, pdp->mod, pdp->fun, pdp->prb))
-		return 1;
-#endif
-
-	return 0;
-}
-
-/*
- * Try to provide probes for the given probe description.  The caller ensures
- * that the provider name in probe desxcription (if any) is a match for this
- * provider.  When this is called, we already know that this provider matches
- * the provider component of the probe specification.
- */
-#define FBT_ENTRY	1
-#define FBT_RETURN	2
-
-static int provide(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp)
-{
-	int			n = 0;
-	int			prb = 0;
-	dt_module_t		*dmp = NULL;
-	dt_symbol_t		*sym = NULL;
-	dt_htab_next_t		*it = NULL;
-	dtrace_probedesc_t	pd;
-
-	dt_modsym_mark_traceable(dtp);
-
-	/*
-	 * Nothing to do if a probe name is specified and cannot match 'entry'
-	 * or 'return'.
-	 */
-	if (dt_gmatch("entry", pdp->prb))
-		prb |= FBT_ENTRY;
-	if (dt_gmatch("return", pdp->prb))
-		prb |= FBT_RETURN;
-	if (prb == 0)
-		return 0;
-
-	/*
-	 * If we have an explicit module name, check it.  If not found, we can
-	 * ignore this request.
-	 */
-	if (pdp->mod[0] != '\0' && strchr(pdp->mod, '*') == NULL) {
-		dmp = dt_module_lookup_by_name(dtp, pdp->mod);
-		if (dmp == NULL)
-			return 0;
-	}
-
-	/*
-	 * If we have an explicit function name, we start with a basic symbol
-	 * name lookup.
-	 */
-	if (pdp->fun[0] != '\0' && strchr(pdp->fun, '*') == NULL) {
-		/* If we have a module, use it. */
-		if (dmp != NULL) {
-			sym = dt_module_symbol_by_name(dtp, dmp, pdp->fun);
-			if (sym == NULL)
-				return 0;
-			if (!dt_symbol_traceable(sym))
-				return 0;
-
-			pd.id = DTRACE_IDNONE;
-			pd.prv = pdp->prv;
-			pd.mod = dmp->dm_name;
-			pd.fun = pdp->fun;
-
-			if (prb & FBT_ENTRY) {
-				pd.prb = "entry";
-				n += provide_probe(dtp, &pd);
-			}
-			if (prb & FBT_RETURN) {
-				pd.prb = "return";
-				n += provide_probe(dtp, &pd);
-			}
-
-			return n;
-		}
-
-		sym = dt_symbol_by_name(dtp, pdp->fun);
-		while (sym != NULL) {
-			const char	*mod = dt_symbol_module(sym)->dm_name;
-
-			if (dt_symbol_traceable(sym) &&
-			    dt_gmatch(mod, pdp->mod)) {
-				pd.id = DTRACE_IDNONE;
-				pd.prv = pdp->prv;
-				pd.mod = mod;
-				pd.fun = pdp->fun;
-
-				if (prb & FBT_ENTRY) {
-					pd.prb = "entry";
-					n += provide_probe(dtp, &pd);
-				}
-				if (prb & FBT_RETURN) {
-					pd.prb = "return";
-					n += provide_probe(dtp, &pd);
-				}
-
-			}
-			sym = dt_symbol_by_name_next(sym);
-		}
-
-		return n;
-	}
-
-	/*
-	 * No explicit function name.  We need to go through all possible
-	 * symbol names and see if they match.
-	 */
-	while ((sym = dt_htab_next(dtp->dt_kernsyms, &it)) != NULL) {
-		dt_module_t	*smp;
-		const char	*fun;
-
-		/* Ensure the symbol can be traced. */
-		if (!dt_symbol_traceable(sym))
-			continue;
-
-		/* Match the function name. */
-		fun = dt_symbol_name(sym);
-		if (!dt_gmatch(fun, pdp->fun))
-			continue;
-
-		/* Validate the module name. */
-		smp = dt_symbol_module(sym);
-		if (dmp) {
-			if (smp != dmp)
-				continue;
-		} else if (!dt_gmatch(smp->dm_name, pdp->mod))
-			continue;
-
-		pd.id = DTRACE_IDNONE;
-		pd.prv = pdp->prv;
-		pd.mod = smp->dm_name;
-		pd.fun = fun;
-
-		if (prb & FBT_ENTRY) {
-			pd.prb = "entry";
-			n += provide_probe(dtp, &pd);
-		}
-		if (prb & FBT_RETURN) {
-			pd.prb = "return";
-			n += provide_probe(dtp, &pd);
-		}
-	}
-
-	return n;
-}
-
-/*
- * Generate a BPF trampoline for a FBT probe.
- *
- * The trampoline function is called when a FBT probe triggers, and it must
- * satisfy the following prototype:
- *
- *	int dt_rawfbt(dt_pt_regs *regs)
- *
- * The trampoline will populate a dt_dctx_t struct and then call the function
- * that implements the compiled D clause.  It returns 0 to the caller.
- */
-static int trampoline(dt_pcb_t *pcb, uint_t exitlbl)
-{
-	dt_cg_tramp_prologue(pcb);
-
-	/*
-	 * After the dt_cg_tramp_prologue() call, we have:
-	 *				//     (%r7 = dctx->mst)
-	 *				//     (%r8 = dctx->ctx)
-	 */
-	dt_cg_tramp_copy_regs(pcb);
-	if (strcmp(pcb->pcb_probe->desc->prb, "return") == 0) {
-		dt_irlist_t	*dlp = &pcb->pcb_ir;
-
-		dt_cg_tramp_copy_rval_from_regs(pcb);
-
-		/*
-		 * fbt:::return arg0 should be the function offset for
-		 * return instruction.  Since we use kretprobes, however,
-		 * which do not fire until the function has returned to
-		 * its caller, information about the returning instruction
-		 * in the callee has been lost.
-		 *
-		 * Set arg0=-1 to indicate that we do not know the value.
-		 */
-		dt_cg_xsetx(dlp, NULL, DT_LBL_NONE, BPF_REG_0, -1);
-		emit(dlp,  BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(0), BPF_REG_0));
-	} else
-		dt_cg_tramp_copy_args_from_regs(pcb, 1);
-	dt_cg_tramp_epilogue(pcb);
-
-	return 0;
-}
-
-static int attach(dtrace_hdl_t *dtp, const dt_probe_t *prp, int bpf_fd)
-{
-	char	*prb = NULL;
-
-	if (!dt_tp_probe_has_info(prp)) {
-		char	*fn, *p;
-		FILE	*f;
-		int	fd, rc = -1;
-
-		/*
-		 * The tracepoint event we will be creating needs to have a
-		 * valid name.  We use a copy of the probe name, with . -> _
-		 * conversion.
-		 */
-		prb = strdup(prp->desc->fun);
-		for (p = prb; *p; p++) {
-			if (*p == '.')
-				*p = '_';
-		}
-
-		/*
-		 * Register the kprobe with the tracing subsystem.  This will
-		 * create a tracepoint event.
-		 */
-		fd = open(KPROBE_EVENTS, O_WRONLY | O_APPEND);
-		if (fd == -1)
-			goto fail;
-
-		rc = dprintf(fd, "%c:" FBT_GROUP_FMT "/%s %s\n",
-			     prp->desc->prb[0] == 'e' ? 'p' : 'r',
-			     FBT_GROUP_DATA, prb, prp->desc->fun);
-		close(fd);
-		if (rc == -1)
-			goto fail;
-
-		/* create format file name */
-		if (asprintf(&fn, "%s" FBT_GROUP_FMT "/%s/format", EVENTSFS,
-			     FBT_GROUP_DATA, prb) == -1)
-			goto fail;
-
-		/* open format file */
-		f = fopen(fn, "r");
-		free(fn);
-		if (f == NULL)
-			goto fail;
-
-		/* read event id from format file */
-		rc = dt_tp_probe_info(dtp, f, 0, prp, NULL, NULL);
-		fclose(f);
-
-		if (rc < 0)
-			goto fail;
-
-		free(prb);
-	}
-
-	/* attach BPF program to the probe */
-	return dt_tp_probe_attach(dtp, prp, bpf_fd);
-
-fail:
-	free(prb);
-	return -ENOENT;
-}
-
-/*
- * Try to clean up system resources that may have been allocated for this
- * probe.
- *
- * If there is an event FD, we close it.
- *
- * We also try to remove any kprobe that may have been created for the probe.
- * This is harmless for probes that didn't get created.  If the removal fails
- * for some reason we are out of luck - fortunately it is not harmful to the
- * system as a whole.
- */
-static void detach(dtrace_hdl_t *dtp, const dt_probe_t *prp)
-{
-	int	fd;
-	char	*prb, *p;
-
-	if (!dt_tp_probe_has_info(prp))
-		return;
-
-	dt_tp_probe_detach(dtp, prp);
-
-	fd = open(KPROBE_EVENTS, O_WRONLY | O_APPEND);
-	if (fd == -1)
-		return;
-
-	/* The tracepoint event is the probe nam, with . -> _ conversion. */
-	prb = strdup(prp->desc->fun);
-	for (p = prb; *p; p++) {
-		if (*p == '.')
-			*p = '_';
-	}
-
-	dprintf(fd, "-:" FBT_GROUP_FMT "/%s\n", FBT_GROUP_DATA, prb);
-	free(prb);
-	close(fd);
-}
-
-dt_provimpl_t	dt_rawfbt = {
-	.name		= prvname,
-	.prog_type	= BPF_PROG_TYPE_KPROBE,
-	.populate	= &populate,
-	.provide	= &provide,
-	.load_prog	= &dt_bpf_prog_load,
-	.trampoline	= &trampoline,
-	.attach		= &attach,
-	.detach		= &detach,
-	.probe_destroy	= &dt_tp_probe_destroy,
-};
-- 
2.45.2




More information about the DTrace-devel mailing list