[DTrace-devel] [PATCH v2 04/04] rawtp: retrieve probe arguments from CTF data

Nick Alcock nick.alcock at oracle.com
Thu Nov 30 20:26:33 UTC 2023


On 30 Nov 2023, Kris Van Hees via DTrace-devel verbalised:

> We were determining the number of arguments using a trial-and-error
> approach with minimal BPF programs.  If there is CTF type data for
> the raw tracepoints (in the form of a function prototype), we use
> that because it also gives us the types of the arguments.

Nice!

> Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>

Reviewed-by: Nick Alcock <nick.alcock at oracle.com>

with one memory leak fixed (see below).

> -static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
> -		      int *argcp, dt_argdesc_t **argvp)
> +/*
> + * If there is no btf_trace_* prototype available in CTF, we can still probe
> + * the number of available argument for a raw tracepoint by means of a trial
> + * and error loop to see what the highest argument index is that the BPF
> + * verifier allows us to load from.

Ew! :) but it's what we did before and it's a useful fallback in the
absence of enough type info (OL7, right? dwarf2ctf doesn't emit function
prototypes at all...)

> +static int probe_info(dtrace_hdl_t *dtp, const dt_probe_t *prp,
> +		      int *argcp, dt_argdesc_t **argvp)
> +{
> +#ifdef HAVE_LIBCTF

... yeah, OL7 :) it amazes me that Solaris libctf had CTF_K_FUNCTION but
no way to get any actual *info* on CTF_K_FUNCTIONs...

> +	int			rc, i;
> +	char			*str;
> +	ctf_dict_t		*ctfp;
> +	ctf_id_t		type;
> +	int			argc = 0;
> +	dt_argdesc_t		*argv = NULL;
> +	ctf_funcinfo_t		fi;
> +	dtrace_typeinfo_t	sym;
> +	ctf_id_t		*argt;
> +
> +	if (asprintf(&str, "btf_trace_%s", prp->desc->prb) == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
> +	rc = dtrace_lookup_by_type(dtp, DTRACE_OBJ_EVERY, str, &sym);
> +	free(str);
> +	if (rc ||
> +	    ctf_type_kind(sym.dtt_ctfp, sym.dtt_type) != CTF_K_TYPEDEF)
> +		goto use_alt;
> +	ctfp = sym.dtt_ctfp;
> +	type = ctf_type_reference(ctfp, sym.dtt_type);
> +	if (ctf_type_kind(ctfp, type) != CTF_K_POINTER)
> +		goto use_alt;
> +	type = ctf_type_reference(ctfp, type);
> +	if (ctf_type_kind(ctfp, type) != CTF_K_FUNCTION)
> +		goto use_alt;

... I guess that handles -1 just as well, and no matter what the error
(or if it's just not a pointer) you want to switch to the other
resolution method :)

> +	if (ctf_func_type_info(ctfp, type, &fi) == -1)
> +		goto use_alt;
> +
> +	/*
> +	 * Raw tracepoints have an extra first argument for the context, so we
> +	 * need to skip that.  (We also handle the case where fi.ctc_argc is 0
> +	 * even though that is not supposed to happen.)
> +	 */

It could perfectly well happen if there is some *other* function pointer
called btf_trace_foobar that isn't actually a tracepoint (unlikely,
sure, but no more unlikely than non-function-pointer-typedef
btf_trace_*s, I'd say.)

I agree that there's no point handling the case where it's a function
pointer and the first arg is something else -- you could in theory
verify that the first arg is a context, but if this gets common enough
that we actually hit that case it'll be pretty obvious and we can add
suitable code then.

> +	argc = fi.ctc_argc;
> +	argt = dt_calloc(dtp, argc, sizeof(ctf_id_t));
> +	ctf_func_type_args(ctfp, type, argc, argt);
> +
> +	argc--;
> +	argv = dt_zalloc(dtp, argc * sizeof(dt_argdesc_t));

I guess if there's an allocation failure we just crash? dt_[cz]alloc
return NULL on failure... (I know we don't handle this very well
anywhere, so I'm happy to ignore this.)

> +	for (i = 0; i < argc; i++) {
> +		char	n[DT_TYPE_NAMELEN];

#define        DT_TYPE_NAMELEN        128

ugh. I'm adding extirpating *that* to my todo list. :)

(for now it's all you can do though.)

> +		ctf_type_name(ctfp, argt[i + 1], n, sizeof(n));
> +		argv[i].mapping = i;
> +		argv[i].native = strdup(n);

Hm. So this is assigned to the dt_probe_t's argv element, which is freed
in dt_probe_destroy() -- but unless it's done in an earlier patch in
this series, nothing frees dt_probe_t.argv[i].native, only the argv
array itself...

... with that caveat, this looks good.

-- 
NULL && (void)



More information about the DTrace-devel mailing list