aboutsummaryrefslogtreecommitdiff
path: root/tools/lib
diff options
context:
space:
mode:
authorGravatar Andrii Nakryiko <andrii@kernel.org> 2022-12-12 13:15:03 -0800
committerGravatar Daniel Borkmann <daniel@iogearbox.net> 2022-12-15 00:05:13 +0100
commit25a4481b4136af7794e1df2d6c90ed2f354d60ce (patch)
tree29a8b5a3f8c5d841aa2c1e3fb20addfb2de4b5a9 /tools/lib
parentselftests/bpf: Add non-standardly sized enum tests for btf_dump (diff)
downloadlinux-25a4481b4136af7794e1df2d6c90ed2f354d60ce.tar.gz
linux-25a4481b4136af7794e1df2d6c90ed2f354d60ce.tar.bz2
linux-25a4481b4136af7794e1df2d6c90ed2f354d60ce.zip
libbpf: Fix btf__align_of() by taking into account field offsets
btf__align_of() is supposed to be return alignment requirement of a requested BTF type. For STRUCT/UNION it doesn't always return correct value, because it calculates alignment only based on field types. But for packed structs this is not enough, we need to also check field offsets and struct size. If field offset isn't aligned according to field type's natural alignment, then struct must be packed. Similarly, if struct size is not a multiple of struct's natural alignment, then struct must be packed as well. This patch fixes this issue precisely by additionally checking these conditions. Fixes: 3d208f4ca111 ("libbpf: Expose btf__align_of() API") Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20221212211505.558851-5-andrii@kernel.org
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/bpf/btf.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 71e165b09ed5..8cbcef959456 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -688,8 +688,21 @@ int btf__align_of(const struct btf *btf, __u32 id)
if (align <= 0)
return libbpf_err(align);
max_align = max(max_align, align);
+
+ /* if field offset isn't aligned according to field
+ * type's alignment, then struct must be packed
+ */
+ if (btf_member_bitfield_size(t, i) == 0 &&
+ (m->offset % (8 * align)) != 0)
+ return 1;
}
+ /* if struct/union size isn't a multiple of its alignment,
+ * then struct must be packed
+ */
+ if ((t->size % max_align) != 0)
+ return 1;
+
return max_align;
}
default: