libbpf: Expose btf__align_of() API
authorAndrii Nakryiko <andriin@fb.com>
Sat, 14 Dec 2019 01:43:30 +0000 (17:43 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Sun, 15 Dec 2019 23:58:05 +0000 (15:58 -0800)
Expose BTF API that calculates type alignment requirements.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20191214014341.3442258-7-andriin@fb.com
tools/lib/bpf/btf.c
tools/lib/bpf/btf.h
tools/lib/bpf/btf_dump.c
tools/lib/bpf/libbpf.map

index 88efa2b..84fe82f 100644 (file)
@@ -278,6 +278,45 @@ done:
        return nelems * size;
 }
 
+int btf__align_of(const struct btf *btf, __u32 id)
+{
+       const struct btf_type *t = btf__type_by_id(btf, id);
+       __u16 kind = btf_kind(t);
+
+       switch (kind) {
+       case BTF_KIND_INT:
+       case BTF_KIND_ENUM:
+               return min(sizeof(void *), t->size);
+       case BTF_KIND_PTR:
+               return sizeof(void *);
+       case BTF_KIND_TYPEDEF:
+       case BTF_KIND_VOLATILE:
+       case BTF_KIND_CONST:
+       case BTF_KIND_RESTRICT:
+               return btf__align_of(btf, t->type);
+       case BTF_KIND_ARRAY:
+               return btf__align_of(btf, btf_array(t)->type);
+       case BTF_KIND_STRUCT:
+       case BTF_KIND_UNION: {
+               const struct btf_member *m = btf_members(t);
+               __u16 vlen = btf_vlen(t);
+               int i, align = 1, t;
+
+               for (i = 0; i < vlen; i++, m++) {
+                       t = btf__align_of(btf, m->type);
+                       if (t <= 0)
+                               return t;
+                       align = max(align, t);
+               }
+
+               return align;
+       }
+       default:
+               pr_warn("unsupported BTF_KIND:%u\n", btf_kind(t));
+               return 0;
+       }
+}
+
 int btf__resolve_type(const struct btf *btf, __u32 type_id)
 {
        const struct btf_type *t;
index 5fc23b9..a114c8e 100644 (file)
@@ -77,6 +77,7 @@ LIBBPF_API const struct btf_type *btf__type_by_id(const struct btf *btf,
                                                  __u32 id);
 LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
 LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
+LIBBPF_API int btf__align_of(const struct btf *btf, __u32 id);
 LIBBPF_API int btf__fd(const struct btf *btf);
 LIBBPF_API const void *btf__get_raw_data(const struct btf *btf, __u32 *size);
 LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
index cb126d8..5339302 100644 (file)
@@ -752,41 +752,6 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id)
        }
 }
 
-static int btf_align_of(const struct btf *btf, __u32 id)
-{
-       const struct btf_type *t = btf__type_by_id(btf, id);
-       __u16 kind = btf_kind(t);
-
-       switch (kind) {
-       case BTF_KIND_INT:
-       case BTF_KIND_ENUM:
-               return min(sizeof(void *), t->size);
-       case BTF_KIND_PTR:
-               return sizeof(void *);
-       case BTF_KIND_TYPEDEF:
-       case BTF_KIND_VOLATILE:
-       case BTF_KIND_CONST:
-       case BTF_KIND_RESTRICT:
-               return btf_align_of(btf, t->type);
-       case BTF_KIND_ARRAY:
-               return btf_align_of(btf, btf_array(t)->type);
-       case BTF_KIND_STRUCT:
-       case BTF_KIND_UNION: {
-               const struct btf_member *m = btf_members(t);
-               __u16 vlen = btf_vlen(t);
-               int i, align = 1;
-
-               for (i = 0; i < vlen; i++, m++)
-                       align = max(align, btf_align_of(btf, m->type));
-
-               return align;
-       }
-       default:
-               pr_warn("unsupported BTF_KIND:%u\n", btf_kind(t));
-               return 1;
-       }
-}
-
 static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
                                 const struct btf_type *t)
 {
@@ -794,18 +759,18 @@ static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
        int align, i, bit_sz;
        __u16 vlen;
 
-       align = btf_align_of(btf, id);
+       align = btf__align_of(btf, id);
        /* size of a non-packed struct has to be a multiple of its alignment*/
-       if (t->size % align)
+       if (align && t->size % align)
                return true;
 
        m = btf_members(t);
        vlen = btf_vlen(t);
        /* all non-bitfield fields have to be naturally aligned */
        for (i = 0; i < vlen; i++, m++) {
-               align = btf_align_of(btf, m->type);
+               align = btf__align_of(btf, m->type);
                bit_sz = btf_member_bitfield_size(t, i);
-               if (bit_sz == 0 && m->offset % (8 * align) != 0)
+               if (align && bit_sz == 0 && m->offset % (8 * align) != 0)
                        return true;
        }
 
@@ -889,7 +854,7 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
                fname = btf_name_of(d, m->name_off);
                m_sz = btf_member_bitfield_size(t, i);
                m_off = btf_member_bit_offset(t, i);
-               align = packed ? 1 : btf_align_of(d->btf, m->type);
+               align = packed ? 1 : btf__align_of(d->btf, m->type);
 
                btf_dump_emit_bit_padding(d, off, m_off, m_sz, align, lvl + 1);
                btf_dump_printf(d, "\n%s", pfx(lvl + 1));
@@ -907,7 +872,7 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
 
        /* pad at the end, if necessary */
        if (is_struct) {
-               align = packed ? 1 : btf_align_of(d->btf, id);
+               align = packed ? 1 : btf__align_of(d->btf, id);
                btf_dump_emit_bit_padding(d, off, t->size * 8, 0, align,
                                          lvl + 1);
        }
index 757a88f..e7fcca3 100644 (file)
@@ -212,4 +212,5 @@ LIBBPF_0.0.6 {
 LIBBPF_0.0.7 {
        global:
                bpf_program__attach;
+               btf__align_of;
 } LIBBPF_0.0.6;