Merge tag 'powerpc-5.9-3' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[linux-2.6-microblaze.git] / tools / lib / bpf / btf_dump.c
index cf71116..57c00fa 100644 (file)
@@ -13,6 +13,7 @@
 #include <errno.h>
 #include <linux/err.h>
 #include <linux/btf.h>
+#include <linux/kernel.h>
 #include "btf.h"
 #include "hashmap.h"
 #include "libbpf.h"
@@ -60,6 +61,7 @@ struct btf_dump {
        const struct btf_ext *btf_ext;
        btf_dump_printf_fn_t printf_fn;
        struct btf_dump_opts opts;
+       int ptr_sz;
        bool strip_mods;
 
        /* per-type auxiliary state */
@@ -138,6 +140,7 @@ struct btf_dump *btf_dump__new(const struct btf *btf,
        d->btf_ext = btf_ext;
        d->printf_fn = printf_fn;
        d->opts.ctx = opts ? opts->ctx : NULL;
+       d->ptr_sz = btf__pointer_size(btf) ? : sizeof(void *);
 
        d->type_names = hashmap__new(str_hash_fn, str_equal_fn, NULL);
        if (IS_ERR(d->type_names)) {
@@ -549,6 +552,9 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr)
        }
 }
 
+static void btf_dump_emit_missing_aliases(struct btf_dump *d, __u32 id,
+                                         const struct btf_type *t);
+
 static void btf_dump_emit_struct_fwd(struct btf_dump *d, __u32 id,
                                     const struct btf_type *t);
 static void btf_dump_emit_struct_def(struct btf_dump *d, __u32 id,
@@ -671,6 +677,9 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id)
 
        switch (kind) {
        case BTF_KIND_INT:
+               /* Emit type alias definitions if necessary */
+               btf_dump_emit_missing_aliases(d, id, t);
+
                tstate->emit_state = EMITTED;
                break;
        case BTF_KIND_ENUM:
@@ -797,7 +806,7 @@ static void btf_dump_emit_bit_padding(const struct btf_dump *d,
                                      int align, int lvl)
 {
        int off_diff = m_off - cur_off;
-       int ptr_bits = sizeof(void *) * 8;
+       int ptr_bits = d->ptr_sz * 8;
 
        if (off_diff <= 0)
                /* no gap */
@@ -870,7 +879,7 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
                        btf_dump_printf(d, ": %d", m_sz);
                        off = m_off + m_sz;
                } else {
-                       m_sz = max(0, btf__resolve_size(d->btf, m->type));
+                       m_sz = max((__s64)0, btf__resolve_size(d->btf, m->type));
                        off = m_off + m_sz * 8;
                }
                btf_dump_printf(d, ";");
@@ -890,6 +899,32 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
                btf_dump_printf(d, " __attribute__((packed))");
 }
 
+static const char *missing_base_types[][2] = {
+       /*
+        * GCC emits typedefs to its internal __PolyX_t types when compiling Arm
+        * SIMD intrinsics. Alias them to standard base types.
+        */
+       { "__Poly8_t",          "unsigned char" },
+       { "__Poly16_t",         "unsigned short" },
+       { "__Poly64_t",         "unsigned long long" },
+       { "__Poly128_t",        "unsigned __int128" },
+};
+
+static void btf_dump_emit_missing_aliases(struct btf_dump *d, __u32 id,
+                                         const struct btf_type *t)
+{
+       const char *name = btf_dump_type_name(d, id);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(missing_base_types); i++) {
+               if (strcmp(name, missing_base_types[i][0]) == 0) {
+                       btf_dump_printf(d, "typedef %s %s;\n\n",
+                                       missing_base_types[i][1], name);
+                       break;
+               }
+       }
+}
+
 static void btf_dump_emit_enum_fwd(struct btf_dump *d, __u32 id,
                                   const struct btf_type *t)
 {