On Wed, Jun 15, 2022 at 4:03 PM Yonghong Song <yhs@xxxxxx> wrote: > > BTF_KIND_ENUM64 is supported with latest libbpf, which > supports 64-bit enum values. Latest libbpf also supports > signedness for enum values. Add enum64 support in > dwarf-to-btf conversion. > > The following is an example of new encoding which covers > signed/unsigned enum64/enum variations. > > $cat t.c > enum { /* signed, enum64 */ > A = -1, > B = 0xffffffff, > } g1; > enum { /* unsigned, enum64 */ > C = 1, > D = 0xfffffffff, > } g2; > enum { /* signed, enum */ > E = -1, > F = 0xfffffff, > } g3; > enum { /* unsigned, enum */ > G = 1, > H = 0xfffffff, > } g4; > $ clang -g -c t.c > $ pahole -JV t.o > btf_encoder__new: 't.o' doesn't have '.data..percpu' section > Found 0 per-CPU variables! > File t.o: > [1] ENUM64 (anon) size=8 > A val=-1 > B val=4294967295 > [2] INT long size=8 nr_bits=64 encoding=SIGNED > [3] ENUM64 (anon) size=8 > C val=1 > D val=68719476735 > [4] INT unsigned long size=8 nr_bits=64 encoding=(none) > [5] ENUM (anon) size=4 > E val=-1 > F val=268435455 > [6] INT int size=4 nr_bits=32 encoding=SIGNED > [7] ENUM (anon) size=4 > G val=1 > H val=268435455 > [8] INT unsigned int size=4 nr_bits=32 encoding=(none) > > With the flag to skip enum64 encoding, > > $ pahole -JV t.o --skip_encoding_btf_enum64 > btf_encoder__new: 't.o' doesn't have '.data..percpu' section > Found 0 per-CPU variables! > File t.o: > [1] ENUM (anon) size=8 > A val=4294967295 > B val=4294967295 > [2] INT long size=8 nr_bits=64 encoding=SIGNED > [3] ENUM (anon) size=8 > C val=1 > D val=4294967295 > [4] INT unsigned long size=8 nr_bits=64 encoding=(none) > [5] ENUM (anon) size=4 > E val=4294967295 > F val=268435455 > [6] INT int size=4 nr_bits=32 encoding=SIGNED > [7] ENUM (anon) size=4 > G val=1 > H val=268435455 > [8] INT unsigned int size=4 nr_bits=32 encoding=(none) > > In the above btf encoding without enum64, all enum types > with the same type size as the corresponding enum64. All these > enum types have unsigned type (kflag = 0) which is required > before kernel enum64 support. > > Signed-off-by: Yonghong Song <yhs@xxxxxx> > --- > btf_encoder.c | 65 +++++++++++++++++++++++++++++++++++------------ > btf_encoder.h | 2 +- > dwarf_loader.c | 12 +++++++++ > dwarves.h | 4 ++- > dwarves_fprintf.c | 6 ++++- > pahole.c | 10 +++++++- > 6 files changed, 79 insertions(+), 20 deletions(-) > Sorry for late review, I don't always catch up on emails from older emails first :( [...] > size = BITS_ROUNDUP_BYTES(bit_size); > - id = btf__add_enum(btf, name, size); > + is_enum32 = size <= 4 || no_enum64; > + if (is_enum32) > + id = btf__add_enum(btf, name, size); > + else > + id = btf__add_enum64(btf, name, size, is_signed); > if (id > 0) { > t = btf__type_by_id(btf, id); > btf_encoder__log_type(encoder, t, false, true, "size=%u", t->size); > } else { > - btf__log_err(btf, BTF_KIND_ENUM, name, true, > + btf__log_err(btf, is_enum32 ? BTF_KIND_ENUM : BTF_KIND_ENUM64, name, true, > "size=%u Error emitting BTF type", size); > } > return id; > } > > -static int btf_encoder__add_enum_val(struct btf_encoder *encoder, const char *name, int32_t value) > +static int btf_encoder__add_enum_val(struct btf_encoder *encoder, const char *name, int64_t value, > + bool is_signed, bool is_enum64, bool no_enum64) It was quite confusing to see "is_enum64" and "no_enum64" as arguments to the same function :) I'll let Arnaldo decide for himself, but I think it would be cleaner to pass such configuration switches as fields in struct btf_encoder itself and just check such flags from relevant btf_encoder__add_xxx() functions. Such flags are global by nature, so it seems fitting. But other than that looks good to me. Acked-by: Andrii Nakryiko <andrii@xxxxxxxxxx> > { > - int err = btf__add_enum_value(encoder->btf, name, value); > + const char *fmt_str; > + int err; > + > + /* If enum64 is not allowed, generate enum32 with unsigned int value. In enum64-supported > + * libbpf library, btf__add_enum_value() will set the kflag (sign bit) in common_type > + * if the value is negative. > + */ > + if (no_enum64) > + err = btf__add_enum_value(encoder->btf, name, (uint32_t)value); > + else if (is_enum64) > + err = btf__add_enum64_value(encoder->btf, name, value); > + else > + err = btf__add_enum_value(encoder->btf, name, value); [...]