public inbox for dtrace@lists.linux.dev
 help / color / mirror / Atom feed
* [PATCH 3/4] btf: add dt_btf_func_is_traceable()
@ 2026-04-14  6:27 Kris Van Hees
  2026-04-17 17:07 ` Nick Alcock
  0 siblings, 1 reply; 3+ messages in thread
From: Kris Van Hees @ 2026-04-14  6:27 UTC (permalink / raw)
  To: dtrace, dtrace-devel

Add a function to determine whether a function (given by BTF id) can be
traced using BPF fentry/fexit probes.  It implements checks inspired by
btf_distill_func_proto() in kernel/bpf/btf.c.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
---
 libdtrace/dt_btf.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++
 libdtrace/dt_btf.h |  2 ++
 2 files changed, 67 insertions(+)

diff --git a/libdtrace/dt_btf.c b/libdtrace/dt_btf.c
index 56eb96a4e..fbf377b4e 100644
--- a/libdtrace/dt_btf.c
+++ b/libdtrace/dt_btf.c
@@ -1020,3 +1020,68 @@ dt_btf_func_is_void(dtrace_hdl_t *dtp, const dt_btf_t *btf, uint32_t id)
 
 	return 0;
 }
+
+/*
+ * Return 1 if the function referenced by the BTF id can be traced using the
+ * fprobe/fexit facility.  Specifically, that the function is not variadic and
+ * that none of its arguments exceeds the acceptable value size (16 bytes).
+ * (See btf_distill_func_proto() in kernel/bpf/btf.c for reference.)
+ */
+#define MAX_BPF_FUNC_REG_REGS	5
+int
+dt_btf_func_is_traceable(dtrace_hdl_t *dtp, const dt_btf_t *btf, uint32_t id)
+{
+	btf_type_t	*type = dt_btf_real_type_by_id(dtp, btf, id);
+	int		argc;
+
+	/* If no prototype is found, BPF fprobes do not work. */
+	if (!type || BTF_INFO_KIND(type->info) != BTF_KIND_FUNC_PROTO)
+		return 0;
+
+	/* If the return type is a struct or union, BPF fprobes do not work. */
+	if (type->type != 0) {
+		btf_type_t	*rtype = dt_btf_real_type_by_id(dtp, btf, type->type);
+
+		if (rtype == NULL)
+			return 0;
+
+		switch (BTF_INFO_KIND(rtype->info)) {
+		case BTF_KIND_STRUCT:
+		case BTF_KIND_UNION:
+			return 0;
+		default:
+			/* fall-through */
+		}
+	}
+
+	/*
+	 * BPF fprobes do not support functions that are variadic or that have
+	 * any arguments passed by value that are a struct or union of size
+	 * greater than 16.
+	 */
+	argc = BTF_INFO_VLEN(type->info);
+	if (argc > 0) {
+		btf_param_t	*args = (btf_param_t *)(type + 1);
+		int		i;
+
+		if (args[argc - 1].type == 0)		/* variadic */
+			return 0;
+
+		for (i = 0; i < argc; i++) {
+			type = dt_btf_real_type_by_id(dtp, btf, args[i].type);
+			if (type == NULL)
+				return 0;
+
+			switch (BTF_INFO_KIND(type->info)) {
+			case BTF_KIND_STRUCT:
+			case BTF_KIND_UNION:
+				if (type->size > 16)	/* value size > 16 */
+					return 0;
+			default:
+				/* fall-through */
+			}
+		}
+	}
+
+	return 1;
+}
diff --git a/libdtrace/dt_btf.h b/libdtrace/dt_btf.h
index d956ad940..2c921a033 100644
--- a/libdtrace/dt_btf.h
+++ b/libdtrace/dt_btf.h
@@ -28,6 +28,8 @@ extern int dt_btf_func_argc(dtrace_hdl_t *dtp, const dt_btf_t *btf,
 			    uint32_t id);
 extern int dt_btf_func_is_void(dtrace_hdl_t *dtp, const dt_btf_t *btf,
 			       uint32_t id);
+extern int dt_btf_func_is_traceable(dtrace_hdl_t *dtp, const dt_btf_t *btf,
+				    uint32_t id);
 extern int dt_btf_get_module_ids(dtrace_hdl_t *);
 extern int dt_btf_module_fd(const dt_module_t *);
 
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-04-17 19:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-14  6:27 [PATCH 3/4] btf: add dt_btf_func_is_traceable() Kris Van Hees
2026-04-17 17:07 ` Nick Alcock
2026-04-17 19:04   ` Kris Van Hees

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox