Merge https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[linux-2.6-microblaze.git] / tools / lib / bpf / btf_dump.c
index 6b1bc1f..627edb5 100644 (file)
@@ -144,15 +144,17 @@ static void btf_dump_printf(const struct btf_dump *d, const char *fmt, ...)
 static int btf_dump_mark_referenced(struct btf_dump *d);
 static int btf_dump_resize(struct btf_dump *d);
 
-DEFAULT_VERSION(btf_dump__new_v0_6_0, btf_dump__new, LIBBPF_0.6.0)
-struct btf_dump *btf_dump__new_v0_6_0(const struct btf *btf,
-                                     btf_dump_printf_fn_t printf_fn,
-                                     void *ctx,
-                                     const struct btf_dump_opts *opts)
+struct btf_dump *btf_dump__new(const struct btf *btf,
+                              btf_dump_printf_fn_t printf_fn,
+                              void *ctx,
+                              const struct btf_dump_opts *opts)
 {
        struct btf_dump *d;
        int err;
 
+       if (!OPTS_VALID(opts, btf_dump_opts))
+               return libbpf_err_ptr(-EINVAL);
+
        if (!printf_fn)
                return libbpf_err_ptr(-EINVAL);
 
@@ -188,17 +190,6 @@ err:
        return libbpf_err_ptr(err);
 }
 
-COMPAT_VERSION(btf_dump__new_deprecated, btf_dump__new, LIBBPF_0.0.4)
-struct btf_dump *btf_dump__new_deprecated(const struct btf *btf,
-                                         const struct btf_ext *btf_ext,
-                                         const struct btf_dump_opts *opts,
-                                         btf_dump_printf_fn_t printf_fn)
-{
-       if (!printf_fn)
-               return libbpf_err_ptr(-EINVAL);
-       return btf_dump__new_v0_6_0(btf, printf_fn, opts ? opts->ctx : NULL, opts);
-}
-
 static int btf_dump_resize(struct btf_dump *d)
 {
        int err, last_id = btf__type_cnt(d->btf) - 1;
@@ -318,6 +309,7 @@ static int btf_dump_mark_referenced(struct btf_dump *d)
                switch (btf_kind(t)) {
                case BTF_KIND_INT:
                case BTF_KIND_ENUM:
+               case BTF_KIND_ENUM64:
                case BTF_KIND_FWD:
                case BTF_KIND_FLOAT:
                        break;
@@ -538,6 +530,7 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr)
                return 1;
        }
        case BTF_KIND_ENUM:
+       case BTF_KIND_ENUM64:
        case BTF_KIND_FWD:
                /*
                 * non-anonymous or non-referenced enums are top-level
@@ -739,6 +732,7 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id)
                tstate->emit_state = EMITTED;
                break;
        case BTF_KIND_ENUM:
+       case BTF_KIND_ENUM64:
                if (top_level_def) {
                        btf_dump_emit_enum_def(d, id, t, 0);
                        btf_dump_printf(d, ";\n\n");
@@ -989,38 +983,81 @@ static void btf_dump_emit_enum_fwd(struct btf_dump *d, __u32 id,
        btf_dump_printf(d, "enum %s", btf_dump_type_name(d, id));
 }
 
-static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
-                                  const struct btf_type *t,
-                                  int lvl)
+static void btf_dump_emit_enum32_val(struct btf_dump *d,
+                                    const struct btf_type *t,
+                                    int lvl, __u16 vlen)
 {
        const struct btf_enum *v = btf_enum(t);
-       __u16 vlen = btf_vlen(t);
+       bool is_signed = btf_kflag(t);
+       const char *fmt_str;
        const char *name;
        size_t dup_cnt;
        int i;
 
+       for (i = 0; i < vlen; i++, v++) {
+               name = btf_name_of(d, v->name_off);
+               /* enumerators share namespace with typedef idents */
+               dup_cnt = btf_dump_name_dups(d, d->ident_names, name);
+               if (dup_cnt > 1) {
+                       fmt_str = is_signed ? "\n%s%s___%zd = %d," : "\n%s%s___%zd = %u,";
+                       btf_dump_printf(d, fmt_str, pfx(lvl + 1), name, dup_cnt, v->val);
+               } else {
+                       fmt_str = is_signed ? "\n%s%s = %d," : "\n%s%s = %u,";
+                       btf_dump_printf(d, fmt_str, pfx(lvl + 1), name, v->val);
+               }
+       }
+}
+
+static void btf_dump_emit_enum64_val(struct btf_dump *d,
+                                    const struct btf_type *t,
+                                    int lvl, __u16 vlen)
+{
+       const struct btf_enum64 *v = btf_enum64(t);
+       bool is_signed = btf_kflag(t);
+       const char *fmt_str;
+       const char *name;
+       size_t dup_cnt;
+       __u64 val;
+       int i;
+
+       for (i = 0; i < vlen; i++, v++) {
+               name = btf_name_of(d, v->name_off);
+               dup_cnt = btf_dump_name_dups(d, d->ident_names, name);
+               val = btf_enum64_value(v);
+               if (dup_cnt > 1) {
+                       fmt_str = is_signed ? "\n%s%s___%zd = %lldLL,"
+                                           : "\n%s%s___%zd = %lluULL,";
+                       btf_dump_printf(d, fmt_str,
+                                       pfx(lvl + 1), name, dup_cnt,
+                                       (unsigned long long)val);
+               } else {
+                       fmt_str = is_signed ? "\n%s%s = %lldLL,"
+                                           : "\n%s%s = %lluULL,";
+                       btf_dump_printf(d, fmt_str,
+                                       pfx(lvl + 1), name,
+                                       (unsigned long long)val);
+               }
+       }
+}
+static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
+                                  const struct btf_type *t,
+                                  int lvl)
+{
+       __u16 vlen = btf_vlen(t);
+
        btf_dump_printf(d, "enum%s%s",
                        t->name_off ? " " : "",
                        btf_dump_type_name(d, id));
 
-       if (vlen) {
-               btf_dump_printf(d, " {");
-               for (i = 0; i < vlen; i++, v++) {
-                       name = btf_name_of(d, v->name_off);
-                       /* enumerators share namespace with typedef idents */
-                       dup_cnt = btf_dump_name_dups(d, d->ident_names, name);
-                       if (dup_cnt > 1) {
-                               btf_dump_printf(d, "\n%s%s___%zu = %u,",
-                                               pfx(lvl + 1), name, dup_cnt,
-                                               (__u32)v->val);
-                       } else {
-                               btf_dump_printf(d, "\n%s%s = %u,",
-                                               pfx(lvl + 1), name,
-                                               (__u32)v->val);
-                       }
-               }
-               btf_dump_printf(d, "\n%s}", pfx(lvl));
-       }
+       if (!vlen)
+               return;
+
+       btf_dump_printf(d, " {");
+       if (btf_is_enum(t))
+               btf_dump_emit_enum32_val(d, t, lvl, vlen);
+       else
+               btf_dump_emit_enum64_val(d, t, lvl, vlen);
+       btf_dump_printf(d, "\n%s}", pfx(lvl));
 }
 
 static void btf_dump_emit_fwd_def(struct btf_dump *d, __u32 id,
@@ -1178,6 +1215,7 @@ skip_mod:
                        break;
                case BTF_KIND_INT:
                case BTF_KIND_ENUM:
+               case BTF_KIND_ENUM64:
                case BTF_KIND_FWD:
                case BTF_KIND_STRUCT:
                case BTF_KIND_UNION:
@@ -1312,6 +1350,7 @@ static void btf_dump_emit_type_chain(struct btf_dump *d,
                                btf_dump_emit_struct_fwd(d, id, t);
                        break;
                case BTF_KIND_ENUM:
+               case BTF_KIND_ENUM64:
                        btf_dump_emit_mods(d, decls);
                        /* inline anonymous enum */
                        if (t->name_off == 0 && !d->skip_anon_defs)
@@ -1988,7 +2027,8 @@ static int btf_dump_get_enum_value(struct btf_dump *d,
                                   __u32 id,
                                   __s64 *value)
 {
-       /* handle unaligned enum value */
+       bool is_signed = btf_kflag(t);
+
        if (!ptr_is_aligned(d->btf, id, data)) {
                __u64 val;
                int err;
@@ -2005,13 +2045,13 @@ static int btf_dump_get_enum_value(struct btf_dump *d,
                *value = *(__s64 *)data;
                return 0;
        case 4:
-               *value = *(__s32 *)data;
+               *value = is_signed ? (__s64)*(__s32 *)data : *(__u32 *)data;
                return 0;
        case 2:
-               *value = *(__s16 *)data;
+               *value = is_signed ? *(__s16 *)data : *(__u16 *)data;
                return 0;
        case 1:
-               *value = *(__s8 *)data;
+               *value = is_signed ? *(__s8 *)data : *(__u8 *)data;
                return 0;
        default:
                pr_warn("unexpected size %d for enum, id:[%u]\n", t->size, id);
@@ -2024,7 +2064,7 @@ static int btf_dump_enum_data(struct btf_dump *d,
                              __u32 id,
                              const void *data)
 {
-       const struct btf_enum *e;
+       bool is_signed;
        __s64 value;
        int i, err;
 
@@ -2032,14 +2072,31 @@ static int btf_dump_enum_data(struct btf_dump *d,
        if (err)
                return err;
 
-       for (i = 0, e = btf_enum(t); i < btf_vlen(t); i++, e++) {
-               if (value != e->val)
-                       continue;
-               btf_dump_type_values(d, "%s", btf_name_of(d, e->name_off));
-               return 0;
-       }
+       is_signed = btf_kflag(t);
+       if (btf_is_enum(t)) {
+               const struct btf_enum *e;
+
+               for (i = 0, e = btf_enum(t); i < btf_vlen(t); i++, e++) {
+                       if (value != e->val)
+                               continue;
+                       btf_dump_type_values(d, "%s", btf_name_of(d, e->name_off));
+                       return 0;
+               }
 
-       btf_dump_type_values(d, "%d", value);
+               btf_dump_type_values(d, is_signed ? "%d" : "%u", value);
+       } else {
+               const struct btf_enum64 *e;
+
+               for (i = 0, e = btf_enum64(t); i < btf_vlen(t); i++, e++) {
+                       if (value != btf_enum64_value(e))
+                               continue;
+                       btf_dump_type_values(d, "%s", btf_name_of(d, e->name_off));
+                       return 0;
+               }
+
+               btf_dump_type_values(d, is_signed ? "%lldLL" : "%lluULL",
+                                    (unsigned long long)value);
+       }
        return 0;
 }
 
@@ -2099,6 +2156,7 @@ static int btf_dump_type_data_check_overflow(struct btf_dump *d,
        case BTF_KIND_FLOAT:
        case BTF_KIND_PTR:
        case BTF_KIND_ENUM:
+       case BTF_KIND_ENUM64:
                if (data + bits_offset / 8 + size > d->typed_dump->data_end)
                        return -E2BIG;
                break;
@@ -2203,6 +2261,7 @@ static int btf_dump_type_data_check_zero(struct btf_dump *d,
                return -ENODATA;
        }
        case BTF_KIND_ENUM:
+       case BTF_KIND_ENUM64:
                err = btf_dump_get_enum_value(d, t, data, id, &value);
                if (err)
                        return err;
@@ -2275,6 +2334,7 @@ static int btf_dump_dump_type_data(struct btf_dump *d,
                err = btf_dump_struct_data(d, t, id, data);
                break;
        case BTF_KIND_ENUM:
+       case BTF_KIND_ENUM64:
                /* handle bitfield and int enum values */
                if (bit_sz) {
                        __u64 print_num;