diff mbox series

[bpf-next,v3,10/18] libbpf: Add enum64 relocation support

Message ID 20220526185524.2550356-1-yhs@fb.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series bpf: Add 64bit enum value support | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR fail PR summary
netdev/tree_selection success Clearly marked for bpf-next, async
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count fail Series longer than 15 patches (and no cover letter)
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 2 this patch: 2
netdev/cc_maintainers warning 5 maintainers not CCed: netdev@vger.kernel.org songliubraving@fb.com john.fastabend@gmail.com kafai@fb.com kpsingh@kernel.org
netdev/build_clang success Errors and warnings before: 7 this patch: 7
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 2 this patch: 2
netdev/checkpatch warning WARNING: line length of 82 exceeds 80 columns WARNING: line length of 83 exceeds 80 columns WARNING: line length of 86 exceeds 80 columns WARNING: line length of 88 exceeds 80 columns WARNING: line length of 90 exceeds 80 columns WARNING: line length of 95 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 12 this patch: 12
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-1 fail Logs for Kernel LATEST on ubuntu-latest with gcc
bpf/vmtest-bpf-next-VM_Test-2 fail Logs for Kernel LATEST on ubuntu-latest with llvm-15
bpf/vmtest-bpf-next-VM_Test-3 fail Logs for Kernel LATEST on z15 with gcc

Commit Message

Yonghong Song May 26, 2022, 6:55 p.m. UTC
The enum64 relocation support is added. The bpf local type
could be either enum or enum64 and the remote type could be
either enum or enum64 too. The all combinations of local enum/enum64
and remote enum/enum64 are supported.

Signed-off-by: Yonghong Song <yhs@fb.com>
---
 tools/lib/bpf/btf.h       |  7 +++++
 tools/lib/bpf/libbpf.c    |  7 ++---
 tools/lib/bpf/relo_core.c | 54 +++++++++++++++++++++++++++------------
 3 files changed, 48 insertions(+), 20 deletions(-)

Comments

Andrii Nakryiko June 1, 2022, 12:07 a.m. UTC | #1
On Thu, May 26, 2022 at 11:55 AM Yonghong Song <yhs@fb.com> wrote:
>
> The enum64 relocation support is added. The bpf local type
> could be either enum or enum64 and the remote type could be
> either enum or enum64 too. The all combinations of local enum/enum64
> and remote enum/enum64 are supported.
>
> Signed-off-by: Yonghong Song <yhs@fb.com>
> ---
>  tools/lib/bpf/btf.h       |  7 +++++
>  tools/lib/bpf/libbpf.c    |  7 ++---
>  tools/lib/bpf/relo_core.c | 54 +++++++++++++++++++++++++++------------
>  3 files changed, 48 insertions(+), 20 deletions(-)
>

[...]

>                 local_essent_len = bpf_core_essential_name_len(local_acc->name);
>
> -               for (i = 0, e = btf_enum(targ_type); i < btf_vlen(targ_type); i++, e++) {
> -                       targ_name = btf__name_by_offset(targ_spec->btf, e->name_off);
> +               for (i = 0; i < btf_vlen(targ_type); i++) {
> +                       if (btf_is_enum(targ_type))
> +                               name_off = btf_enum(targ_type)[i].name_off;
> +                       else
> +                               name_off = btf_enum64(targ_type)[i].name_off;
> +
> +                       targ_name = btf__name_by_offset(targ_spec->btf, name_off);
>                         targ_essent_len = bpf_core_essential_name_len(targ_name);
>                         if (targ_essent_len != local_essent_len)
>                                 continue;
> @@ -680,8 +688,7 @@ static int bpf_core_calc_field_relo(const char *prog_name,
>                 *val = byte_sz;
>                 break;
>         case BPF_CORE_FIELD_SIGNED:
> -               /* enums will be assumed unsigned */
> -               *val = btf_is_enum(mt) ||
> +               *val = btf_type_is_any_enum(mt) ||

wouldn't this be more correct with kflag meaning "signed":

(btf_type_is_any_enum(mt) && btf_kflag(mt)) ||

?

>                        (btf_int_encoding(mt) & BTF_INT_SIGNED);
>                 if (validate)
>                         *validate = true; /* signedness is never ambiguous */
> @@ -754,7 +761,6 @@ static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
>                                       __u64 *val)
>  {
>         const struct btf_type *t;
> -       const struct btf_enum *e;
>
>         switch (relo->kind) {
>         case BPF_CORE_ENUMVAL_EXISTS:
> @@ -764,8 +770,10 @@ static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
>                 if (!spec)
>                         return -EUCLEAN; /* request instruction poisoning */
>                 t = btf_type_by_id(spec->btf, spec->spec[0].type_id);
> -               e = btf_enum(t) + spec->spec[0].idx;
> -               *val = e->val;
> +               if (btf_is_enum(t))
> +                       *val = btf_enum(t)[spec->spec[0].idx].val;
> +               else
> +                       *val = btf_enum64_value(btf_enum64(t) + spec->spec[0].idx);
>                 break;
>         default:
>                 return -EOPNOTSUPP;
> @@ -1060,7 +1068,6 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,
>  int bpf_core_format_spec(char *buf, size_t buf_sz, const struct bpf_core_spec *spec)
>  {
>         const struct btf_type *t;
> -       const struct btf_enum *e;
>         const char *s;
>         __u32 type_id;
>         int i, len = 0;
> @@ -1089,10 +1096,23 @@ int bpf_core_format_spec(char *buf, size_t buf_sz, const struct bpf_core_spec *s
>
>         if (core_relo_is_enumval_based(spec->relo_kind)) {
>                 t = skip_mods_and_typedefs(spec->btf, type_id, NULL);
> -               e = btf_enum(t) + spec->raw_spec[0];
> -               s = btf__name_by_offset(spec->btf, e->name_off);
> +               if (btf_is_enum(t)) {
> +                       const struct btf_enum *e;
> +                       const char *fmt_str;
> +
> +                       e = btf_enum(t) + spec->raw_spec[0];
> +                       s = btf__name_by_offset(spec->btf, e->name_off);
> +                       fmt_str = BTF_INFO_KFLAG(t->info) ? "::%s = %d" : "::%s = %u";

minor nit: btf_kflag(t) instead of BTF_INFO_KFLAGS(t->info)?



> +                       append_buf(fmt_str, s, e->val);
> +               } else {
> +                       const struct btf_enum64 *e;
> +                       const char *fmt_str;
>
> -               append_buf("::%s = %u", s, e->val);
> +                       e = btf_enum64(t) + spec->raw_spec[0];
> +                       s = btf__name_by_offset(spec->btf, e->name_off);
> +                       fmt_str = BTF_INFO_KFLAG(t->info) ? "::%s = %lld" : "::%s = %llu";
> +                       append_buf(fmt_str, s, (unsigned long long)btf_enum64_value(e));
> +               }
>                 return len;
>         }
>
> --
> 2.30.2
>
Yonghong Song June 1, 2022, 7:14 p.m. UTC | #2
On 5/31/22 5:07 PM, Andrii Nakryiko wrote:
> On Thu, May 26, 2022 at 11:55 AM Yonghong Song <yhs@fb.com> wrote:
>>
>> The enum64 relocation support is added. The bpf local type
>> could be either enum or enum64 and the remote type could be
>> either enum or enum64 too. The all combinations of local enum/enum64
>> and remote enum/enum64 are supported.
>>
>> Signed-off-by: Yonghong Song <yhs@fb.com>
>> ---
>>   tools/lib/bpf/btf.h       |  7 +++++
>>   tools/lib/bpf/libbpf.c    |  7 ++---
>>   tools/lib/bpf/relo_core.c | 54 +++++++++++++++++++++++++++------------
>>   3 files changed, 48 insertions(+), 20 deletions(-)
>>
> 
> [...]
> 
>>                  local_essent_len = bpf_core_essential_name_len(local_acc->name);
>>
>> -               for (i = 0, e = btf_enum(targ_type); i < btf_vlen(targ_type); i++, e++) {
>> -                       targ_name = btf__name_by_offset(targ_spec->btf, e->name_off);
>> +               for (i = 0; i < btf_vlen(targ_type); i++) {
>> +                       if (btf_is_enum(targ_type))
>> +                               name_off = btf_enum(targ_type)[i].name_off;
>> +                       else
>> +                               name_off = btf_enum64(targ_type)[i].name_off;
>> +
>> +                       targ_name = btf__name_by_offset(targ_spec->btf, name_off);
>>                          targ_essent_len = bpf_core_essential_name_len(targ_name);
>>                          if (targ_essent_len != local_essent_len)
>>                                  continue;
>> @@ -680,8 +688,7 @@ static int bpf_core_calc_field_relo(const char *prog_name,
>>                  *val = byte_sz;
>>                  break;
>>          case BPF_CORE_FIELD_SIGNED:
>> -               /* enums will be assumed unsigned */
>> -               *val = btf_is_enum(mt) ||
>> +               *val = btf_type_is_any_enum(mt) ||
> 
> wouldn't this be more correct with kflag meaning "signed":
> 
> (btf_type_is_any_enum(mt) && btf_kflag(mt)) ||

Will fix.

> 
> ?
> 
>>                         (btf_int_encoding(mt) & BTF_INT_SIGNED);
>>                  if (validate)
>>                          *validate = true; /* signedness is never ambiguous */
>> @@ -754,7 +761,6 @@ static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
>>                                        __u64 *val)
>>   {
>>          const struct btf_type *t;
>> -       const struct btf_enum *e;
>>
>>          switch (relo->kind) {
>>          case BPF_CORE_ENUMVAL_EXISTS:
>> @@ -764,8 +770,10 @@ static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
>>                  if (!spec)
>>                          return -EUCLEAN; /* request instruction poisoning */
>>                  t = btf_type_by_id(spec->btf, spec->spec[0].type_id);
>> -               e = btf_enum(t) + spec->spec[0].idx;
>> -               *val = e->val;
>> +               if (btf_is_enum(t))
>> +                       *val = btf_enum(t)[spec->spec[0].idx].val;
>> +               else
>> +                       *val = btf_enum64_value(btf_enum64(t) + spec->spec[0].idx);
>>                  break;
>>          default:
>>                  return -EOPNOTSUPP;
>> @@ -1060,7 +1068,6 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,
>>   int bpf_core_format_spec(char *buf, size_t buf_sz, const struct bpf_core_spec *spec)
>>   {
>>          const struct btf_type *t;
>> -       const struct btf_enum *e;
>>          const char *s;
>>          __u32 type_id;
>>          int i, len = 0;
>> @@ -1089,10 +1096,23 @@ int bpf_core_format_spec(char *buf, size_t buf_sz, const struct bpf_core_spec *s
>>
>>          if (core_relo_is_enumval_based(spec->relo_kind)) {
>>                  t = skip_mods_and_typedefs(spec->btf, type_id, NULL);
>> -               e = btf_enum(t) + spec->raw_spec[0];
>> -               s = btf__name_by_offset(spec->btf, e->name_off);
>> +               if (btf_is_enum(t)) {
>> +                       const struct btf_enum *e;
>> +                       const char *fmt_str;
>> +
>> +                       e = btf_enum(t) + spec->raw_spec[0];
>> +                       s = btf__name_by_offset(spec->btf, e->name_off);
>> +                       fmt_str = BTF_INFO_KFLAG(t->info) ? "::%s = %d" : "::%s = %u";
> 
> minor nit: btf_kflag(t) instead of BTF_INFO_KFLAGS(t->info)?

relo_core.c is used by both the kernel and libbpf. The btf_kflag
is not available in kernel. That is why I am using BTF_INFO_KFLAG.
I guess I can introduce btf_kflag in the kernel to avoid using
BTF_INFO_KFLAG.

> 
> 
> 
>> +                       append_buf(fmt_str, s, e->val);
>> +               } else {
>> +                       const struct btf_enum64 *e;
>> +                       const char *fmt_str;
>>
>> -               append_buf("::%s = %u", s, e->val);
>> +                       e = btf_enum64(t) + spec->raw_spec[0];
>> +                       s = btf__name_by_offset(spec->btf, e->name_off);
>> +                       fmt_str = BTF_INFO_KFLAG(t->info) ? "::%s = %lld" : "::%s = %llu";
>> +                       append_buf(fmt_str, s, (unsigned long long)btf_enum64_value(e));
>> +               }
>>                  return len;
>>          }
>>
>> --
>> 2.30.2
>>
Andrii Nakryiko June 1, 2022, 9:53 p.m. UTC | #3
On Wed, Jun 1, 2022 at 12:14 PM Yonghong Song <yhs@fb.com> wrote:
>
>
>
> On 5/31/22 5:07 PM, Andrii Nakryiko wrote:
> > On Thu, May 26, 2022 at 11:55 AM Yonghong Song <yhs@fb.com> wrote:
> >>
> >> The enum64 relocation support is added. The bpf local type
> >> could be either enum or enum64 and the remote type could be
> >> either enum or enum64 too. The all combinations of local enum/enum64
> >> and remote enum/enum64 are supported.
> >>
> >> Signed-off-by: Yonghong Song <yhs@fb.com>
> >> ---
> >>   tools/lib/bpf/btf.h       |  7 +++++
> >>   tools/lib/bpf/libbpf.c    |  7 ++---
> >>   tools/lib/bpf/relo_core.c | 54 +++++++++++++++++++++++++++------------
> >>   3 files changed, 48 insertions(+), 20 deletions(-)
> >>
> >
> > [...]
> >
> >>                  local_essent_len = bpf_core_essential_name_len(local_acc->name);
> >>
> >> -               for (i = 0, e = btf_enum(targ_type); i < btf_vlen(targ_type); i++, e++) {
> >> -                       targ_name = btf__name_by_offset(targ_spec->btf, e->name_off);
> >> +               for (i = 0; i < btf_vlen(targ_type); i++) {
> >> +                       if (btf_is_enum(targ_type))
> >> +                               name_off = btf_enum(targ_type)[i].name_off;
> >> +                       else
> >> +                               name_off = btf_enum64(targ_type)[i].name_off;
> >> +
> >> +                       targ_name = btf__name_by_offset(targ_spec->btf, name_off);
> >>                          targ_essent_len = bpf_core_essential_name_len(targ_name);
> >>                          if (targ_essent_len != local_essent_len)
> >>                                  continue;
> >> @@ -680,8 +688,7 @@ static int bpf_core_calc_field_relo(const char *prog_name,
> >>                  *val = byte_sz;
> >>                  break;
> >>          case BPF_CORE_FIELD_SIGNED:
> >> -               /* enums will be assumed unsigned */
> >> -               *val = btf_is_enum(mt) ||
> >> +               *val = btf_type_is_any_enum(mt) ||
> >
> > wouldn't this be more correct with kflag meaning "signed":
> >
> > (btf_type_is_any_enum(mt) && btf_kflag(mt)) ||
>
> Will fix.
>
> >
> > ?
> >
> >>                         (btf_int_encoding(mt) & BTF_INT_SIGNED);
> >>                  if (validate)
> >>                          *validate = true; /* signedness is never ambiguous */
> >> @@ -754,7 +761,6 @@ static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
> >>                                        __u64 *val)
> >>   {
> >>          const struct btf_type *t;
> >> -       const struct btf_enum *e;
> >>
> >>          switch (relo->kind) {
> >>          case BPF_CORE_ENUMVAL_EXISTS:
> >> @@ -764,8 +770,10 @@ static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
> >>                  if (!spec)
> >>                          return -EUCLEAN; /* request instruction poisoning */
> >>                  t = btf_type_by_id(spec->btf, spec->spec[0].type_id);
> >> -               e = btf_enum(t) + spec->spec[0].idx;
> >> -               *val = e->val;
> >> +               if (btf_is_enum(t))
> >> +                       *val = btf_enum(t)[spec->spec[0].idx].val;
> >> +               else
> >> +                       *val = btf_enum64_value(btf_enum64(t) + spec->spec[0].idx);
> >>                  break;
> >>          default:
> >>                  return -EOPNOTSUPP;
> >> @@ -1060,7 +1068,6 @@ int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,
> >>   int bpf_core_format_spec(char *buf, size_t buf_sz, const struct bpf_core_spec *spec)
> >>   {
> >>          const struct btf_type *t;
> >> -       const struct btf_enum *e;
> >>          const char *s;
> >>          __u32 type_id;
> >>          int i, len = 0;
> >> @@ -1089,10 +1096,23 @@ int bpf_core_format_spec(char *buf, size_t buf_sz, const struct bpf_core_spec *s
> >>
> >>          if (core_relo_is_enumval_based(spec->relo_kind)) {
> >>                  t = skip_mods_and_typedefs(spec->btf, type_id, NULL);
> >> -               e = btf_enum(t) + spec->raw_spec[0];
> >> -               s = btf__name_by_offset(spec->btf, e->name_off);
> >> +               if (btf_is_enum(t)) {
> >> +                       const struct btf_enum *e;
> >> +                       const char *fmt_str;
> >> +
> >> +                       e = btf_enum(t) + spec->raw_spec[0];
> >> +                       s = btf__name_by_offset(spec->btf, e->name_off);
> >> +                       fmt_str = BTF_INFO_KFLAG(t->info) ? "::%s = %d" : "::%s = %u";
> >
> > minor nit: btf_kflag(t) instead of BTF_INFO_KFLAGS(t->info)?
>
> relo_core.c is used by both the kernel and libbpf. The btf_kflag
> is not available in kernel. That is why I am using BTF_INFO_KFLAG.
> I guess I can introduce btf_kflag in the kernel to avoid using
> BTF_INFO_KFLAG.

ah, in that case it's fine, nothing wrong with it per se, if it was
purely libbpf code btf_kflag() is a bit cleaner, but given it's shared
it's fine to keep it as is.

>
> >
> >
> >
> >> +                       append_buf(fmt_str, s, e->val);
> >> +               } else {
> >> +                       const struct btf_enum64 *e;
> >> +                       const char *fmt_str;
> >>
> >> -               append_buf("::%s = %u", s, e->val);
> >> +                       e = btf_enum64(t) + spec->raw_spec[0];
> >> +                       s = btf__name_by_offset(spec->btf, e->name_off);
> >> +                       fmt_str = BTF_INFO_KFLAG(t->info) ? "::%s = %lld" : "::%s = %llu";
> >> +                       append_buf(fmt_str, s, (unsigned long long)btf_enum64_value(e));
> >> +               }
> >>                  return len;
> >>          }
> >>
> >> --
> >> 2.30.2
> >>
diff mbox series

Patch

diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index d4fe1300ed33..aa2b38abdd2c 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -537,6 +537,13 @@  static inline bool btf_type_is_any_enum(const struct btf_type *t)
 	return btf_is_enum(t) || btf_is_enum64(t);
 }
 
+static inline bool btf_kind_core_compat(const struct btf_type *t1,
+					const struct btf_type *t2)
+{
+	return btf_kind(t1) == btf_kind(t2) ||
+	       (btf_type_is_any_enum(t1) && btf_type_is_any_enum(t2));
+}
+
 static inline __u8 btf_int_encoding(const struct btf_type *t)
 {
 	return BTF_INT_ENCODING(*(__u32 *)(t + 1));
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a9667b49b838..4a234dce5e9f 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -5401,7 +5401,7 @@  int bpf_core_add_cands(struct bpf_core_cand *local_cand,
 	n = btf__type_cnt(targ_btf);
 	for (i = targ_start_id; i < n; i++) {
 		t = btf__type_by_id(targ_btf, i);
-		if (btf_kind(t) != btf_kind(local_t))
+		if (!btf_kind_core_compat(t, local_t))
 			continue;
 
 		targ_name = btf__name_by_offset(targ_btf, t->name_off);
@@ -5615,7 +5615,7 @@  int bpf_core_types_are_compat(const struct btf *local_btf, __u32 local_id,
 	/* caller made sure that names match (ignoring flavor suffix) */
 	local_type = btf__type_by_id(local_btf, local_id);
 	targ_type = btf__type_by_id(targ_btf, targ_id);
-	if (btf_kind(local_type) != btf_kind(targ_type))
+	if (!btf_kind_core_compat(local_type, targ_type))
 		return 0;
 
 recur:
@@ -5628,7 +5628,7 @@  int bpf_core_types_are_compat(const struct btf *local_btf, __u32 local_id,
 	if (!local_type || !targ_type)
 		return -EINVAL;
 
-	if (btf_kind(local_type) != btf_kind(targ_type))
+	if (!btf_kind_core_compat(local_type, targ_type))
 		return 0;
 
 	switch (btf_kind(local_type)) {
@@ -5636,6 +5636,7 @@  int bpf_core_types_are_compat(const struct btf *local_btf, __u32 local_id,
 	case BTF_KIND_STRUCT:
 	case BTF_KIND_UNION:
 	case BTF_KIND_ENUM:
+	case BTF_KIND_ENUM64:
 	case BTF_KIND_FWD:
 		return 1;
 	case BTF_KIND_INT:
diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c
index 78b16cda86fa..8c1d608c3adf 100644
--- a/tools/lib/bpf/relo_core.c
+++ b/tools/lib/bpf/relo_core.c
@@ -186,7 +186,7 @@  int bpf_core_parse_spec(const char *prog_name, const struct btf *btf,
 	struct bpf_core_accessor *acc;
 	const struct btf_type *t;
 	const char *name, *spec_str;
-	__u32 id;
+	__u32 id, name_off;
 	__s64 sz;
 
 	spec_str = btf__name_by_offset(btf, relo->access_str_off);
@@ -231,11 +231,13 @@  int bpf_core_parse_spec(const char *prog_name, const struct btf *btf,
 	spec->len++;
 
 	if (core_relo_is_enumval_based(relo->kind)) {
-		if (!btf_is_enum(t) || spec->raw_len > 1 || access_idx >= btf_vlen(t))
+		if (!btf_type_is_any_enum(t) || spec->raw_len > 1 || access_idx >= btf_vlen(t))
 			return -EINVAL;
 
 		/* record enumerator name in a first accessor */
-		acc->name = btf__name_by_offset(btf, btf_enum(t)[access_idx].name_off);
+		name_off = btf_is_enum(t) ? btf_enum(t)[access_idx].name_off
+					  : btf_enum64(t)[access_idx].name_off;
+		acc->name = btf__name_by_offset(btf, name_off);
 		return 0;
 	}
 
@@ -340,7 +342,7 @@  static int bpf_core_fields_are_compat(const struct btf *local_btf,
 
 	if (btf_is_composite(local_type) && btf_is_composite(targ_type))
 		return 1;
-	if (btf_kind(local_type) != btf_kind(targ_type))
+	if (!btf_kind_core_compat(local_type, targ_type))
 		return 0;
 
 	switch (btf_kind(local_type)) {
@@ -348,6 +350,7 @@  static int bpf_core_fields_are_compat(const struct btf *local_btf,
 	case BTF_KIND_FLOAT:
 		return 1;
 	case BTF_KIND_FWD:
+	case BTF_KIND_ENUM64:
 	case BTF_KIND_ENUM: {
 		const char *local_name, *targ_name;
 		size_t local_len, targ_len;
@@ -477,6 +480,7 @@  static int bpf_core_spec_match(struct bpf_core_spec *local_spec,
 	const struct bpf_core_accessor *local_acc;
 	struct bpf_core_accessor *targ_acc;
 	int i, sz, matched;
+	__u32 name_off;
 
 	memset(targ_spec, 0, sizeof(*targ_spec));
 	targ_spec->btf = targ_btf;
@@ -494,18 +498,22 @@  static int bpf_core_spec_match(struct bpf_core_spec *local_spec,
 
 	if (core_relo_is_enumval_based(local_spec->relo_kind)) {
 		size_t local_essent_len, targ_essent_len;
-		const struct btf_enum *e;
 		const char *targ_name;
 
 		/* has to resolve to an enum */
 		targ_type = skip_mods_and_typedefs(targ_spec->btf, targ_id, &targ_id);
-		if (!btf_is_enum(targ_type))
+		if (!btf_type_is_any_enum(targ_type))
 			return 0;
 
 		local_essent_len = bpf_core_essential_name_len(local_acc->name);
 
-		for (i = 0, e = btf_enum(targ_type); i < btf_vlen(targ_type); i++, e++) {
-			targ_name = btf__name_by_offset(targ_spec->btf, e->name_off);
+		for (i = 0; i < btf_vlen(targ_type); i++) {
+			if (btf_is_enum(targ_type))
+				name_off = btf_enum(targ_type)[i].name_off;
+			else
+				name_off = btf_enum64(targ_type)[i].name_off;
+
+			targ_name = btf__name_by_offset(targ_spec->btf, name_off);
 			targ_essent_len = bpf_core_essential_name_len(targ_name);
 			if (targ_essent_len != local_essent_len)
 				continue;
@@ -680,8 +688,7 @@  static int bpf_core_calc_field_relo(const char *prog_name,
 		*val = byte_sz;
 		break;
 	case BPF_CORE_FIELD_SIGNED:
-		/* enums will be assumed unsigned */
-		*val = btf_is_enum(mt) ||
+		*val = btf_type_is_any_enum(mt) ||
 		       (btf_int_encoding(mt) & BTF_INT_SIGNED);
 		if (validate)
 			*validate = true; /* signedness is never ambiguous */
@@ -754,7 +761,6 @@  static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
 				      __u64 *val)
 {
 	const struct btf_type *t;
-	const struct btf_enum *e;
 
 	switch (relo->kind) {
 	case BPF_CORE_ENUMVAL_EXISTS:
@@ -764,8 +770,10 @@  static int bpf_core_calc_enumval_relo(const struct bpf_core_relo *relo,
 		if (!spec)
 			return -EUCLEAN; /* request instruction poisoning */
 		t = btf_type_by_id(spec->btf, spec->spec[0].type_id);
-		e = btf_enum(t) + spec->spec[0].idx;
-		*val = e->val;
+		if (btf_is_enum(t))
+			*val = btf_enum(t)[spec->spec[0].idx].val;
+		else
+			*val = btf_enum64_value(btf_enum64(t) + spec->spec[0].idx);
 		break;
 	default:
 		return -EOPNOTSUPP;
@@ -1060,7 +1068,6 @@  int bpf_core_patch_insn(const char *prog_name, struct bpf_insn *insn,
 int bpf_core_format_spec(char *buf, size_t buf_sz, const struct bpf_core_spec *spec)
 {
 	const struct btf_type *t;
-	const struct btf_enum *e;
 	const char *s;
 	__u32 type_id;
 	int i, len = 0;
@@ -1089,10 +1096,23 @@  int bpf_core_format_spec(char *buf, size_t buf_sz, const struct bpf_core_spec *s
 
 	if (core_relo_is_enumval_based(spec->relo_kind)) {
 		t = skip_mods_and_typedefs(spec->btf, type_id, NULL);
-		e = btf_enum(t) + spec->raw_spec[0];
-		s = btf__name_by_offset(spec->btf, e->name_off);
+		if (btf_is_enum(t)) {
+			const struct btf_enum *e;
+			const char *fmt_str;
+
+			e = btf_enum(t) + spec->raw_spec[0];
+			s = btf__name_by_offset(spec->btf, e->name_off);
+			fmt_str = BTF_INFO_KFLAG(t->info) ? "::%s = %d" : "::%s = %u";
+			append_buf(fmt_str, s, e->val);
+		} else {
+			const struct btf_enum64 *e;
+			const char *fmt_str;
 
-		append_buf("::%s = %u", s, e->val);
+			e = btf_enum64(t) + spec->raw_spec[0];
+			s = btf__name_by_offset(spec->btf, e->name_off);
+			fmt_str = BTF_INFO_KFLAG(t->info) ? "::%s = %lld" : "::%s = %llu";
+			append_buf(fmt_str, s, (unsigned long long)btf_enum64_value(e));
+		}
 		return len;
 	}