[DTrace-devel] [PATCH 3/4] btf: add dt_btf_func_is_traceable()
Kris Van Hees
kris.van.hees at oracle.com
Tue Apr 14 06:27:47 UTC 2026
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 at 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
More information about the DTrace-devel
mailing list