bpftool: Add btf enum64 support
Add BTF_KIND_ENUM64 support. For example, the following enum is defined in uapi bpf.h. $ cat core.c enum A { BPF_F_INDEX_MASK = 0xffffffffULL, BPF_F_CURRENT_CPU = BPF_F_INDEX_MASK, BPF_F_CTXLEN_MASK = (0xfffffULL << 32), } g; Compiled with clang -target bpf -O2 -g -c core.c Using bpftool to dump types and generate format C file: $ bpftool btf dump file core.o ... [1] ENUM64 'A' encoding=UNSIGNED size=8 vlen=3 'BPF_F_INDEX_MASK' val=4294967295ULL 'BPF_F_CURRENT_CPU' val=4294967295ULL 'BPF_F_CTXLEN_MASK' val=4503595332403200ULL $ bpftool btf dump file core.o format c ... enum A { BPF_F_INDEX_MASK = 4294967295ULL, BPF_F_CURRENT_CPU = 4294967295ULL, BPF_F_CTXLEN_MASK = 4503595332403200ULL, }; ... Note that for raw btf output, the encoding (UNSIGNED or SIGNED) is printed out as well. The 64bit value is also represented properly in BTF and C dump. Acked-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Yonghong Song <yhs@fb.com> Link: https://lore.kernel.org/r/20220607062652.3722649-1-yhs@fb.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Родитель
23b2a3a8f6
Коммит
58a53978fd
|
@ -40,6 +40,7 @@ static const char * const btf_kind_str[NR_BTF_KINDS] = {
|
|||
[BTF_KIND_FLOAT] = "FLOAT",
|
||||
[BTF_KIND_DECL_TAG] = "DECL_TAG",
|
||||
[BTF_KIND_TYPE_TAG] = "TYPE_TAG",
|
||||
[BTF_KIND_ENUM64] = "ENUM64",
|
||||
};
|
||||
|
||||
struct btf_attach_point {
|
||||
|
@ -212,15 +213,18 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
|
|||
case BTF_KIND_ENUM: {
|
||||
const struct btf_enum *v = (const void *)(t + 1);
|
||||
__u16 vlen = BTF_INFO_VLEN(t->info);
|
||||
const char *encoding;
|
||||
int i;
|
||||
|
||||
encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
|
||||
if (json_output) {
|
||||
jsonw_string_field(w, "encoding", encoding);
|
||||
jsonw_uint_field(w, "size", t->size);
|
||||
jsonw_uint_field(w, "vlen", vlen);
|
||||
jsonw_name(w, "values");
|
||||
jsonw_start_array(w);
|
||||
} else {
|
||||
printf(" size=%u vlen=%u", t->size, vlen);
|
||||
printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
|
||||
}
|
||||
for (i = 0; i < vlen; i++, v++) {
|
||||
const char *name = btf_str(btf, v->name_off);
|
||||
|
@ -228,10 +232,57 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
|
|||
if (json_output) {
|
||||
jsonw_start_object(w);
|
||||
jsonw_string_field(w, "name", name);
|
||||
jsonw_uint_field(w, "val", v->val);
|
||||
if (btf_kflag(t))
|
||||
jsonw_int_field(w, "val", v->val);
|
||||
else
|
||||
jsonw_uint_field(w, "val", v->val);
|
||||
jsonw_end_object(w);
|
||||
} else {
|
||||
printf("\n\t'%s' val=%u", name, v->val);
|
||||
if (btf_kflag(t))
|
||||
printf("\n\t'%s' val=%d", name, v->val);
|
||||
else
|
||||
printf("\n\t'%s' val=%u", name, v->val);
|
||||
}
|
||||
}
|
||||
if (json_output)
|
||||
jsonw_end_array(w);
|
||||
break;
|
||||
}
|
||||
case BTF_KIND_ENUM64: {
|
||||
const struct btf_enum64 *v = btf_enum64(t);
|
||||
__u16 vlen = btf_vlen(t);
|
||||
const char *encoding;
|
||||
int i;
|
||||
|
||||
encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
|
||||
if (json_output) {
|
||||
jsonw_string_field(w, "encoding", encoding);
|
||||
jsonw_uint_field(w, "size", t->size);
|
||||
jsonw_uint_field(w, "vlen", vlen);
|
||||
jsonw_name(w, "values");
|
||||
jsonw_start_array(w);
|
||||
} else {
|
||||
printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
|
||||
}
|
||||
for (i = 0; i < vlen; i++, v++) {
|
||||
const char *name = btf_str(btf, v->name_off);
|
||||
__u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32;
|
||||
|
||||
if (json_output) {
|
||||
jsonw_start_object(w);
|
||||
jsonw_string_field(w, "name", name);
|
||||
if (btf_kflag(t))
|
||||
jsonw_int_field(w, "val", val);
|
||||
else
|
||||
jsonw_uint_field(w, "val", val);
|
||||
jsonw_end_object(w);
|
||||
} else {
|
||||
if (btf_kflag(t))
|
||||
printf("\n\t'%s' val=%lldLL", name,
|
||||
(unsigned long long)val);
|
||||
else
|
||||
printf("\n\t'%s' val=%lluULL", name,
|
||||
(unsigned long long)val);
|
||||
}
|
||||
}
|
||||
if (json_output)
|
||||
|
|
|
@ -182,6 +182,32 @@ static int btf_dumper_enum(const struct btf_dumper *d,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int btf_dumper_enum64(const struct btf_dumper *d,
|
||||
const struct btf_type *t,
|
||||
const void *data)
|
||||
{
|
||||
const struct btf_enum64 *enums = btf_enum64(t);
|
||||
__u32 val_lo32, val_hi32;
|
||||
__u64 value;
|
||||
__u16 i;
|
||||
|
||||
value = *(__u64 *)data;
|
||||
val_lo32 = (__u32)value;
|
||||
val_hi32 = value >> 32;
|
||||
|
||||
for (i = 0; i < btf_vlen(t); i++) {
|
||||
if (val_lo32 == enums[i].val_lo32 && val_hi32 == enums[i].val_hi32) {
|
||||
jsonw_string(d->jw,
|
||||
btf__name_by_offset(d->btf,
|
||||
enums[i].name_off));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
jsonw_int(d->jw, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_str_array(const struct btf *btf, const struct btf_array *arr,
|
||||
const char *s)
|
||||
{
|
||||
|
@ -542,6 +568,8 @@ static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id,
|
|||
return btf_dumper_array(d, type_id, data);
|
||||
case BTF_KIND_ENUM:
|
||||
return btf_dumper_enum(d, t, data);
|
||||
case BTF_KIND_ENUM64:
|
||||
return btf_dumper_enum64(d, t, data);
|
||||
case BTF_KIND_PTR:
|
||||
btf_dumper_ptr(d, t, data);
|
||||
return 0;
|
||||
|
@ -618,6 +646,7 @@ static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id,
|
|||
btf__name_by_offset(btf, t->name_off));
|
||||
break;
|
||||
case BTF_KIND_ENUM:
|
||||
case BTF_KIND_ENUM64:
|
||||
BTF_PRINT_ARG("enum %s ",
|
||||
btf__name_by_offset(btf, t->name_off));
|
||||
break;
|
||||
|
|
|
@ -1750,6 +1750,7 @@ btfgen_mark_type(struct btfgen_info *info, unsigned int type_id, bool follow_poi
|
|||
case BTF_KIND_INT:
|
||||
case BTF_KIND_FLOAT:
|
||||
case BTF_KIND_ENUM:
|
||||
case BTF_KIND_ENUM64:
|
||||
case BTF_KIND_STRUCT:
|
||||
case BTF_KIND_UNION:
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче