[DTrace-devel] [PATCH 4/8] bpf: add feature checking for BPF program type / attach type

Kris Van Hees kris.van.hees at oracle.com
Wed Apr 3 15:26:50 UTC 2024


Newer provider implementations want to use program type / attach type
combinations that may not be supported in older kernels.  Support is
added for testing whether the runtime kernel supports the program type
and attach type combination.

This patch includes a test for TRACING / FENTRY (which also covers the
FEXIT attach type).

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/Build     |  1 +
 libdtrace/dt_bpf.c  | 48 ++++++++++++++++++++++++++++++++++++++++++++-
 libdtrace/dt_bpf.h  | 13 +++++++++++-
 libdtrace/dt_btf.h  |  3 +++
 libdtrace/dt_impl.h |  1 +
 libdtrace/dt_open.c |  2 +-
 6 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/libdtrace/Build b/libdtrace/Build
index 9733a17b..87152734 100644
--- a/libdtrace/Build
+++ b/libdtrace/Build
@@ -96,6 +96,7 @@ libdtrace_LIBS += -lopcodes
 endif
 
 # Disable certain warnings for these files
+dt_bpf.c_CFLAGS := -Wno-pedantic
 dt_btf.c_CFLAGS := -Wno-pedantic
 dt_consume.c_CFLAGS := -Wno-pedantic
 dt_debug.c_CFLAGS := -Wno-prio-ctor-dtor
diff --git a/libdtrace/dt_bpf.c b/libdtrace/dt_bpf.c
index 14ef12fc..a967335a 100644
--- a/libdtrace/dt_bpf.c
+++ b/libdtrace/dt_bpf.c
@@ -21,6 +21,8 @@
 #include <dt_strtab.h>
 #include <dt_bpf.h>
 #include <dt_bpf_maps.h>
+#include <linux/btf.h>
+#include <dt_btf.h>
 #include <port.h>
 
 static boolean_t	dt_gmap_done = 0;
@@ -378,7 +380,7 @@ have_helper(uint32_t func_id)
 	       strstr(ptr, "unknown func") == NULL;
 }
 
-void
+static void
 dt_bpf_init_helpers(dtrace_hdl_t *dtp)
 {
 	uint32_t	i;
@@ -401,6 +403,50 @@ dt_bpf_init_helpers(dtrace_hdl_t *dtp)
 #undef BPF_HELPER_MAP
 }
 
+static int
+have_attach_type(enum bpf_prog_type ptype, enum bpf_attach_type atype,
+		 uint32_t btf_id)
+{
+	struct bpf_insn	insns[] = {
+				BPF_MOV_IMM(BPF_REG_0, 0),
+				BPF_RETURN()
+			};
+	dtrace_difo_t	dp;
+	int		fd;
+
+	dp.dtdo_buf = insns;
+	dp.dtdo_len = ARRAY_SIZE(insns);
+
+	fd = dt_bpf_prog_attach(ptype, atype, btf_id, &dp, 0, NULL, 0);
+	/* If the program loads, we can use the attach type. */
+	if (fd > 0) {
+		close(fd);
+		return 1;
+	}
+
+	/* Failed -> attach type not available to us */
+	return 0;
+}
+
+static void
+dt_bpf_init_features(dtrace_hdl_t *dtp)
+{
+	uint32_t	btf_id;
+
+	btf_id = dt_btf_lookup_name_kind(dtp, dtp->dt_shared_btf, "bpf_check",
+					 BTF_KIND_FUNC);
+	if (btf_id >= 0 &&
+	    have_attach_type(BPF_PROG_TYPE_TRACING, BPF_TRACE_FENTRY, btf_id))
+		BPF_SET_FEATURE(dtp, BPF_FEAT_FENTRY);
+}
+
+void
+dt_bpf_init(dtrace_hdl_t *dtp)
+{
+	dt_bpf_init_helpers(dtp);
+	dt_bpf_init_features(dtp);
+}
+
 static int
 map_create_error(dtrace_hdl_t *dtp, const char *name, int err)
 {
diff --git a/libdtrace/dt_bpf.h b/libdtrace/dt_bpf.h
index 63df043a..b830d4af 100644
--- a/libdtrace/dt_bpf.h
+++ b/libdtrace/dt_bpf.h
@@ -20,6 +20,17 @@ struct dtrace_hdl;
 extern "C" {
 #endif
 
+/*
+ * BPF features.
+ */
+#define BPF_FEAT_FENTRY			0x1	/* fentry/fexit support */
+
+#define BPF_HAS(dtp, feat)	((dtp)->dt_bpffeatures & (feat))
+#define BPF_SET_FEATURE(dtp, feat) \
+				do { \
+					(dtp)->dt_bpffeatures |= (feat); \
+				} while (0)
+
 #define DT_CONST_EPID			1
 #define DT_CONST_PRID			2
 #define DT_CONST_CLID			3
@@ -74,7 +85,7 @@ extern int dt_bpf_prog_load(enum bpf_prog_type prog_type,
 extern int dt_bpf_raw_tracepoint_open(const void *tp, int fd);
 extern int dt_bpf_make_progs(struct dtrace_hdl *, uint_t);
 extern int dt_bpf_load_progs(struct dtrace_hdl *, uint_t);
-extern void dt_bpf_init_helpers(struct dtrace_hdl *dtp);
+extern void dt_bpf_init(struct dtrace_hdl *dtp);
 
 #ifdef	__cplusplus
 }
diff --git a/libdtrace/dt_btf.h b/libdtrace/dt_btf.h
index 85ae315e..85c8f1b4 100644
--- a/libdtrace/dt_btf.h
+++ b/libdtrace/dt_btf.h
@@ -8,6 +8,7 @@
 #ifndef	_DT_BTF_H
 #define	_DT_BTF_H
 
+/* #include <linux/btf.h> */
 #include <dt_impl.h>
 
 #ifdef	__cplusplus
@@ -20,6 +21,8 @@ extern const char *dt_btf_errmsg(int);
 extern dt_btf_t *dt_btf_load_module(dtrace_hdl_t *, dt_module_t *);
 extern ctf_dict_t *dt_btf_module_ctf(dtrace_hdl_t *, dt_module_t *);
 extern const char *dt_btf_get_string(dtrace_hdl_t *, dt_btf_t *, uint32_t);
+extern int32_t dt_btf_lookup_name_kind(dtrace_hdl_t *, dt_btf_t *,
+				       const char *, uint32_t);
 
 #ifdef	__cplusplus
 }
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 3f258376..7cf71060 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -422,6 +422,7 @@ struct dtrace_hdl {
 	uint_t dt_disasm;	/* dtrace disassembler bitmap (see below) */
 	uint64_t dt_options[DTRACEOPT_MAX]; /* dtrace run-time options */
 	uint32_t dt_bpfhelper[__BPF_FUNC_MAX_ID]; /* BPF helper mapping */
+	uint32_t dt_bpffeatures;/* BPF features */
 	int dt_version;		/* library version requested by client */
 	int dt_btferr;		/* error resulting from last BTF failure */
 	int dt_ctferr;		/* error resulting from last CTF failure */
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index 53db0d6d..06a932be 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -1153,7 +1153,7 @@ dt_vopen(int version, int flags, int *errp,
 	if (dtrace_setopt(dtp, "libdir", _dtrace_libdir) != 0)
 		return set_open_errno(dtp, errp, dtp->dt_errno);
 
-	dt_bpf_init_helpers(dtp);
+	dt_bpf_init(dtp);
 
 	return dtp;
 }
-- 
2.42.0




More information about the DTrace-devel mailing list