[DTrace-devel] [PATCH 3/4] btf: add dt_btf_func_is_traceable()

Kris Van Hees kris.van.hees at oracle.com
Fri Apr 17 19:04:11 UTC 2026


On Fri, Apr 17, 2026 at 06:07:12PM +0100, Nick Alcock wrote:
> On 14 Apr 2026, Kris Van Hees spake thusly:
> 
> > 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.
> 
> ... looks reasonable.
> 
> > Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
> 
> Reviewed-by: Nick Alcock <nick.alcock at oracle.com>
> 
> (though you might possibly want to implement the suggestion below, it's
> very much optional.)
> 
> > ---
> >  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
> 
> A shame we need to hardwire this. More of a shame that we need to
> hardwire it deep in a .c file where it'll almost certainly be overlooked
> when the time comes to change it. Stick it in a suitable header, maybe?

It is an internal (non-UAPI) aspect of BPF that is only relevant here, which is
why I chose to define it here.  I think it would be confusing to have it in a
more generic header file.

> > +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 *);
> 
> -- 
> NULL && (void)



More information about the DTrace-devel mailing list