Re: [PATCH 1/2] libtraceevent: Add loading of BTF to the tep handle

Steven Rostedt <[email protected]> Mon, 4 Aug 2025 08:43:22 -0400
Newsgroups org.kernel.vger.linux-trace-devel
Message-ID <[email protected]>
On Mon, 4 Aug 2025 12:47:31 +0100
Douglas Raillard <[email protected]> wrote:

> > +int tep_btf_print_args(struct tep_handle *tep, struct trace_seq *s, void *args,
> > +		       int nmem, int size, const char *func)
> > +{
> > +	struct tep_btf *btf = tep->btf;
> > +	struct btf_type *type = tep_btf_find_func(btf, func);
> > +	struct btf_param *param;
> > +	unsigned long long arg;
> > +	unsigned int encode;
> > +	const char *param_name;
> > +	int a, p, x, nr;
> > +
> > +	if (size != 4 && size != 8)
> > +		return -1;
> > +
> > +	if (!type) {
> > +		for (int i = 0; i < nmem; i++) {
> > +			assign_arg(&arg, args, size, i);
> > +			trace_seq_printf(s, "%llx", arg);
> > +			if (i + 1 < nmem)
> > +				trace_seq_puts(s, ", ");
> > +		}
> > +		return 0;
> > +	}
> > +
> > +	if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC) {
> > +		printf("Invalid func type %d %s\n", BTF_INFO_KIND(type->info),
> > +		       btf_type_str(type));
> > +		return -1;
> > +	}
> > +
> > +	/* Get the function proto */
> > +	type = btf_get_type(btf, type->type);
> > +
> > +	/* No proto means "()" ? */
> > +	if (!type)
> > +		return 0;
> > +
> > +	if (BTF_INFO_KIND(type->info) != BTF_KIND_FUNC_PROTO) {
> > +		printf("Invalid func proto type %d %s\n", BTF_INFO_KIND(type->info),
> > +		       btf_type_str(type));
> > +		return -1;
> > +	}
> > +
> > +	/* Get the number of parameters */
> > +	nr = BTF_INFO_VLEN(type->info);
> > +
> > +	/* The parameters are right after the FUNC_PROTO type */
> > +	param = ((void *)type) + sizeof(*type);
> > +
> > +	for (a = 0, p = 0; p < nr; a++, p++) {
> > +		struct btf_type *t;
> > +
> > +		if (p)
> > +			trace_seq_puts(s, ", ");
> > +
> > +		if (a == nmem) {
> > +			trace_seq_puts(s, "...");
> > +			break;
> > +		}
> > +
> > +		assign_arg(&arg, args, size, a);
> > +
> > +		param_name = btf_name(btf, param[p].name_off);
> > +		if (param_name)
> > +			trace_seq_printf(s, "%s=", param_name);
> > +
> > +		t = btf_skip_modifiers(btf, param[p].type);
> > +
> > +		switch (t ? BTF_INFO_KIND(t->info) : BTF_KIND_UNKN) {
> > +		case BTF_KIND_UNKN:
> > +			trace_seq_putc(s, '?');
> > +			/* Still print unknown type values */
> > +			/* fallthough */
> > +		case BTF_KIND_PTR:
> > +			trace_seq_printf(s, "0x%llx", arg);
> > +			break;
> > +		case BTF_KIND_INT:
> > +			encode = *(int *)((void *)t + sizeof(*t));
> > +			/* Print unsigned ints as hex */
> > +			if (BTF_INT_ENCODING(encode) & BTF_INT_SIGNED)  
> 
> BTF_INT_OFFSET() and BTF_INT_VAL() values should also be used to shift and mask
> appropriately.

You meant to the "arg" passed in?

> 
> I assume that regardless of BTF_INT_CHAR and BTF_INT_BOOL value, BTF_INT_SIGNED is
> set appropriately.
> 
> > +				trace_seq_printf(s, "%lld", arg);
> > +			else
> > +				trace_seq_printf(s, "0x%llx", arg);
> > +			break;
> > +		case BTF_KIND_ENUM:  
> 
> Could add as well: case BTF_KIND_ENUM64:

Of course then we would need to check if this is a 32 bit infrastructure.
I'm assuming it would be treated differently. More like a struct?

> 
> > +			trace_seq_printf(s, "%lld", arg);  
> 
> This could probably be improved to display the enum variant name, with the caveats that:

If btf has it, sure! But that can come later.

Thanks,

-- Steve


> 
> 1. C allows values that are not that of any enumerator AFAIR, so you'd need the
>     raw int display fallback.
> 2. GNU C allows enum forward declaration. This is not ISO C and BTF has no specific
>     representation for that. As a result, last time I checked you end up with
>     BTF_KIND_ENUM and info.vlen == 0. Another entry with info.vlen != 0 should
>     also exist and give the actual enumerators list. Those forward decl provide an
>     incomplete type though, so you should not encounter it directly in function
>     parameters.
> 
> > +			break;  
> 
> > +		default:
> > +			/* This does not handle complex arguments */
> > +			trace_seq_printf(s, "(%s)[0x%llx", btf_type_str(t), arg);
> > +			for (x = sizeof(long); x < t->size; x += sizeof(long)) {
> > +				trace_seq_putc(s, ':');
> > +				if (++a == nmem) {
> > +					trace_seq_puts(s, "...]");
> > +					return 0;
> > +				}
> > +				assign_arg(&arg, args, size, a);
> > +				trace_seq_printf(s, "0x%llx", arg);
> > +			}
> > +			trace_seq_putc(s, ']');
> > +			break;
> > +		}
> > +	}
> > +	return 0;
> > +}