Re: [PATCH 1/2] libtraceevent: Add loading of BTF to the tep handle
Douglas Raillard <[email protected]> Mon, 4 Aug 2025 16:01:15 +0100
| Newsgroups | org.kernel.vger.linux-trace-devel |
|---|---|
| Message-ID | <[email protected]> |
On 04-08-2025 15:41, Steven Rostedt wrote: > On Mon, 4 Aug 2025 15:18:41 +0100 > Douglas Raillard <[email protected]> wrote: > >>>>> + 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? >> >> Yes, something like that: >> >> unsigned long long mask = (1 << BTF_INT_BITS(encode)) - 1; >> unsigned long long shift = BTF_INT_OFFSET(encode); >> arg = (arg >> shift) & mask; >> >> I suppose that how BTF_INT_OFFSET() is to be used depends on endianness, and I'm not >> sure what is the endianness of the arg value. t->size would probably be involved as >> well in the big endian case: https://docs.kernel.org/bpf/btf.html#btf-kind-int > > Hmm, I guess I'll need to update that. The endianness is stored in the > tep_handle descriptor and will need to be used. Note, this needs to handle > big endian machine reading little endian machine data and vice versa. As > well as little and big reading their own endianness. > > Too bad my big endian machine died. I used that to test all the combinations. > >> >>> >>>> >>>> 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? >> >> AFAIR the only point of BTF_KIND_ENUM64 is to represent enum with enumerator values that are >> larger than 32 bits, since BTF_KIND_ENUM can only represent 32 bit values: >> >> struct btf_enum { >> __u32 name_off; >> __s32 val; >> }; >> >> In contrast, BTF_KIND_ENUM64 encodes the enumerators with this: >> >> struct btf_enum64 { >> __u32 name_off; >> __u32 val_lo32; >> __u32 val_hi32; >> }; >> >> So each value can have 64bits, split over 2 fields. I assume this quirk is >> just to have alignof(struct btf_enum64) == 4 so that the BTF wire format >> can be mapped on that C struct easily. >> >> AFAIR BTF_KIND_ENUM encoding was simply an oversight in the initial BTF spec, so they corrected it >> by adding another BTF_KIND_*. >> >> Since you make no use of the enumerators array for now, I think the handling is identical. >> >> >> Wrt to 32 vs 64 bits, in ISO C, the enum size does not depend on the ABI: >> https://port70.net/~nsz/c/c11/n1570.html#6.7.2.2p4 > > When I brought up 64 bit, I meant with the parameters being passed in. As > this is for parsing function parameters. On 32bit an enum64 would require > two registers whereas on 64bit it would only require one. Ah yes hadn't thought of that. From a godbolt experiment, both C and Rust seem to just use 2 registers in the arm 32 bits case, like a struct. > -- Steve