From: Alan Maguire <alan.maguire@oracle.com>
To: andrii@kernel.org, jolsa@kernel.org, acme@redhat.com,
quentin@isovalent.com
Cc: eddyz87@gmail.com, mykolal@fb.com, ast@kernel.org,
daniel@iogearbox.net, martin.lau@linux.dev, song@kernel.org,
yonghong.song@linux.dev, john.fastabend@gmail.com,
kpsingh@kernel.org, sdf@google.com, haoluo@google.com,
houtao1@huawei.com, bpf@vger.kernel.org, masahiroy@kernel.org,
mcgrof@kernel.org, nathan@kernel.org,
Alan Maguire <alan.maguire@oracle.com>
Subject: [RFC bpf-next 03/13] selftests/bpf: test split base reference BTF generation
Date: Fri, 22 Mar 2024 10:24:45 +0000 [thread overview]
Message-ID: <20240322102455.98558-5-alan.maguire@oracle.com> (raw)
In-Reply-To: <20240322102455.98558-1-alan.maguire@oracle.com>
Test generation of split "base reference" BTF, ensuring that
- FWDs are used in place of full named struct/union declarations
- FWDs are used in place of full named enum declarations
- anonymous struct/unions are represented in full
- anonymous enums are represented in full
- types unreferenced from split BTF are not present in base reference
BTF
Also test that with vmlinux BTF and split BTF based upon it,
we only represent needed base types referenced from split BTF.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
.../bpf/prog_tests/btf_split_base_ref.c | 219 ++++++++++++++++++
1 file changed, 219 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_split_base_ref.c
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_split_base_ref.c b/tools/testing/selftests/bpf/prog_tests/btf_split_base_ref.c
new file mode 100644
index 000000000000..d611167fa4b2
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/btf_split_base_ref.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024, Oracle and/or its affiliates. */
+
+#include <test_progs.h>
+#include <bpf/btf.h>
+#include "btf_helpers.h"
+
+/* Fabricate base, split BTF with references to base types needed; then create
+ * split BTF with reference base BTF and ensure expectations are met:
+ * - only referenced base types from split BTF are present
+ * - struct/union/enum are represented as FWDs unless anonymous, when they
+ * are represented in full
+ */
+static void test_split_base_ref(void)
+{
+ struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL;
+
+ btf1 = btf__new_empty();
+ if (!ASSERT_OK_PTR(btf1, "empty_main_btf"))
+ return;
+
+ btf__add_int(btf1, "int", 4, BTF_INT_SIGNED); /* [1] int */
+ btf__add_ptr(btf1, 1); /* [2] ptr to int */
+ btf__add_struct(btf1, "s1", 8); /* [3] struct s1 { */
+ btf__add_field(btf1, "f1", 2, 0, 0); /* int *f1; */
+ /* } */
+ btf__add_struct(btf1, "", 12); /* [4] struct { */
+ btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
+ btf__add_field(btf1, "f2", 3, 32, 0); /* struct s1 f2; */
+ /* } */
+ btf__add_int(btf1, "unsigned int", 4, 0); /* [5] unsigned int */
+ btf__add_union(btf1, "u1", 12); /* [6] union u1 { */
+ btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
+ btf__add_field(btf1, "f2", 2, 0, 0); /* int *f2; */
+ /* } */
+ btf__add_union(btf1, "", 4); /* [7] union { */
+ btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
+ /* } */
+ btf__add_enum(btf1, "e1", 4); /* [8] enum e1 { */
+ btf__add_enum_value(btf1, "v1", 1); /* v1 = 1; */
+ /* } */
+ btf__add_enum(btf1, "", 4); /* [9] enum { */
+ btf__add_enum_value(btf1, "av1", 2); /* av1 = 2; */
+ /* } */
+ btf__add_enum64(btf1, "e641", 8, true); /* [10] enum64 { */
+ btf__add_enum64_value(btf1, "v1", 1024); /* v1 = 1024; */
+ /* } */
+ btf__add_enum64(btf1, "", 8, true); /* [11] enum64 { */
+ btf__add_enum64_value(btf1, "v1", 1025); /* v1 = 1025; */
+ /* } */
+ btf__add_struct(btf1, "unneeded", 4); /* struct unneeded { */
+ btf__add_field(btf1, "f1", 1, 0, 0); /* int f1; */
+ /* } */
+ VALIDATE_RAW_BTF(
+ btf1,
+ "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
+ "[2] PTR '(anon)' type_id=1",
+ "[3] STRUCT 's1' size=8 vlen=1\n"
+ "\t'f1' type_id=2 bits_offset=0",
+ "[4] STRUCT '(anon)' size=12 vlen=2\n"
+ "\t'f1' type_id=1 bits_offset=0\n"
+ "\t'f2' type_id=3 bits_offset=32",
+ "[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",
+ "[6] UNION 'u1' size=12 vlen=2\n"
+ "\t'f1' type_id=1 bits_offset=0\n"
+ "\t'f2' type_id=2 bits_offset=0",
+ "[7] UNION '(anon)' size=4 vlen=1\n"
+ "\t'f1' type_id=1 bits_offset=0",
+ "[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"
+ "\t'v1' val=1",
+ "[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
+ "\t'av1' val=2",
+ "[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"
+ "\t'v1' val=1024",
+ "[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
+ "\t'v1' val=1025",
+ "[12] STRUCT 'unneeded' size=4 vlen=1\n"
+ "\t'f1' type_id=1 bits_offset=0");
+
+ btf2 = btf__new_empty_split(btf1);
+ if (!ASSERT_OK_PTR(btf2, "empty_split_btf"))
+ goto cleanup;
+
+ btf__add_ptr(btf2, 3); /* [9] ptr to struct s1 */
+ /* add ptr to struct anon */
+ btf__add_ptr(btf2, 4); /* [10] ptr to struct (anon) */
+ btf__add_const(btf2, 6); /* [11] const union u1 */
+ btf__add_restrict(btf2, 7); /* [12] restrict union (anon) */
+ btf__add_volatile(btf2, 8); /* [13] volatile enum e1 */
+ btf__add_typedef(btf2, "et", 9); /* [14] typedef enum (anon) */
+ btf__add_const(btf2, 10); /* [15] const enum64 e641 */
+ btf__add_ptr(btf2, 11); /* [16] restrict enum64 (anon) */
+
+ VALIDATE_RAW_BTF(
+ btf2,
+ "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
+ "[2] PTR '(anon)' type_id=1",
+ "[3] STRUCT 's1' size=8 vlen=1\n"
+ "\t'f1' type_id=2 bits_offset=0",
+ "[4] STRUCT '(anon)' size=12 vlen=2\n"
+ "\t'f1' type_id=1 bits_offset=0\n"
+ "\t'f2' type_id=3 bits_offset=32",
+ "[5] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)",
+ "[6] UNION 'u1' size=12 vlen=2\n"
+ "\t'f1' type_id=1 bits_offset=0\n"
+ "\t'f2' type_id=2 bits_offset=0",
+ "[7] UNION '(anon)' size=4 vlen=1\n"
+ "\t'f1' type_id=1 bits_offset=0",
+ "[8] ENUM 'e1' encoding=UNSIGNED size=4 vlen=1\n"
+ "\t'v1' val=1",
+ "[9] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
+ "\t'av1' val=2",
+ "[10] ENUM64 'e641' encoding=SIGNED size=8 vlen=1\n"
+ "\t'v1' val=1024",
+ "[11] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
+ "\t'v1' val=1025",
+ "[12] STRUCT 'unneeded' size=4 vlen=1\n"
+ "\t'f1' type_id=1 bits_offset=0",
+ "[13] PTR '(anon)' type_id=3",
+ "[14] PTR '(anon)' type_id=4",
+ "[15] CONST '(anon)' type_id=6",
+ "[16] RESTRICT '(anon)' type_id=7",
+ "[17] VOLATILE '(anon)' type_id=8",
+ "[18] TYPEDEF 'et' type_id=9",
+ "[19] CONST '(anon)' type_id=10",
+ "[20] PTR '(anon)' type_id=11");
+
+ btf3 = btf__new_split_base_ref(btf2);
+ if (!ASSERT_OK_PTR(btf1, "new_split_base_ref"))
+ goto cleanup;
+
+ btf4 = (struct btf *)btf__base_btf(btf3);
+ if (!ASSERT_OK_PTR(btf4, "base_ref_btf"))
+ goto cleanup;
+
+ VALIDATE_RAW_BTF(
+ btf3,
+ "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
+ "[2] FWD 's1' fwd_kind=struct",
+ "[3] STRUCT '(anon)' size=12 vlen=2\n"
+ "\t'f1' type_id=1 bits_offset=0\n"
+ "\t'f2' type_id=2 bits_offset=32",
+ "[4] FWD 'u1' fwd_kind=union",
+ "[5] UNION '(anon)' size=4 vlen=1\n"
+ "\t'f1' type_id=1 bits_offset=0",
+ "[6] ENUM 'e1' encoding=UNSIGNED size=4 vlen=0",
+ "[7] ENUM '(anon)' encoding=UNSIGNED size=4 vlen=1\n"
+ "\t'av1' val=2",
+ "[8] ENUM64 'e641' encoding=SIGNED size=8 vlen=0",
+ "[9] ENUM64 '(anon)' encoding=SIGNED size=8 vlen=1\n"
+ "\t'v1' val=1025",
+ "[10] PTR '(anon)' type_id=2",
+ "[11] PTR '(anon)' type_id=3",
+ "[12] CONST '(anon)' type_id=4",
+ "[13] RESTRICT '(anon)' type_id=5",
+ "[14] VOLATILE '(anon)' type_id=6",
+ "[15] TYPEDEF 'et' type_id=7",
+ "[16] CONST '(anon)' type_id=8",
+ "[17] PTR '(anon)' type_id=9");
+
+cleanup:
+ btf__free(btf4);
+ btf__free(btf3);
+ btf__free(btf2);
+ btf__free(btf1);
+}
+
+/* create split reference BTF from vmlinux + split BTF with a few type references;
+ * ensure the resultant split reference BTF is as expected, containing only types
+ * needed to disambiguate references from split BTF.
+ */
+static void test_split_base_ref_vmlinux(void)
+{
+ struct btf *split_btf = NULL, *vmlinux_btf = btf__load_vmlinux_btf();
+ struct btf *split_ref = NULL, *base_ref = NULL;
+ __s32 int_id, sk_buff_id;
+
+ if (!ASSERT_OK_PTR(vmlinux_btf, "load_vmlinux"))
+ return;
+ int_id = btf__find_by_name_kind(vmlinux_btf, "int", BTF_KIND_INT);
+ if (!ASSERT_GT(int_id, 0, "find_int"))
+ goto cleanup;
+ sk_buff_id = btf__find_by_name_kind(vmlinux_btf, "sk_buff", BTF_KIND_STRUCT);
+ if (!ASSERT_GT(sk_buff_id, 0, "find_sk_buff_id"))
+ goto cleanup;
+ split_btf = btf__new_empty_split(vmlinux_btf);
+ if (!ASSERT_OK_PTR(split_btf, "new_split"))
+ goto cleanup;
+ btf__add_typedef(split_btf, "myint", int_id);
+ btf__add_ptr(split_btf, sk_buff_id);
+
+ split_ref = btf__new_split_base_ref(split_btf);
+ if (!ASSERT_OK_PTR(split_ref, "new_split_base_ref"))
+ goto cleanup;
+
+ base_ref = (struct btf *)btf__base_btf(split_ref);
+ if (!ASSERT_OK_PTR(split_ref, "base_ref_btf"))
+ goto cleanup;
+ VALIDATE_RAW_BTF(
+ split_ref,
+ "[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
+ "[2] FWD 'sk_buff' fwd_kind=struct",
+ "[3] TYPEDEF 'myint' type_id=1",
+ "[4] PTR '(anon)' type_id=2");
+
+cleanup:
+ btf__free(split_ref);
+ btf__free(base_ref);
+ btf__free(split_btf);
+ btf__free(vmlinux_btf);
+}
+
+void test_btf_split_base_ref(void)
+{
+ if (test__start_subtest("split_base_ref"))
+ test_split_base_ref();
+ if (test__start_subtest("split_base_ref_vmlinux"))
+ test_split_base_ref_vmlinux();
+}
--
2.39.3
next prev parent reply other threads:[~2024-03-22 10:25 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-03-22 10:24 [RFC bpf-next 00/13] bpf: support resilient split BTF Alan Maguire
2024-03-22 10:24 ` [RFC dwarves] btf_encoder: add base_ref BTF feature to generate split BTF with base refs Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 01/13] libbpf: add support to btf__add_fwd() for ENUM64 Alan Maguire
2024-03-29 21:59 ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 02/13] libbpf: add btf__new_split_base_ref() creating split BTF with reference base BTF Alan Maguire
2024-03-29 22:00 ` Andrii Nakryiko
2024-04-04 15:21 ` Alan Maguire
2024-04-04 22:49 ` Andrii Nakryiko
2024-03-22 10:24 ` Alan Maguire [this message]
2024-03-22 10:24 ` [RFC bpf-next 04/13] libbpf: add btf__parse_opts() API for flexible BTF parsing Alan Maguire
2024-03-29 22:00 ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 05/13] bpftool: support displaying raw split BTF using base reference BTF as base Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 06/13] kbuild,bpf: switch to using --btf_features for pahole v1.26 and later Alan Maguire
2024-03-29 22:01 ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 07/13] resolve_btfids: use .BTF.base_ref BTF as base BTF if -r option is used Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 08/13] kbuild, bpf: add module-specific pahole/resolve_btfids flags for base reference BTF Alan Maguire
2024-03-23 2:50 ` Alexei Starovoitov
2024-03-25 9:51 ` Alan Maguire
2024-03-25 16:41 ` Alexei Starovoitov
2024-03-22 10:24 ` [RFC bpf-next 09/13] libbpf: split BTF reconciliation Alan Maguire
2024-03-29 22:01 ` Andrii Nakryiko
2024-04-05 10:06 ` Alan Maguire
2024-04-05 19:58 ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 10/13] module, bpf: store BTF base reference pointer in struct module Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 11/13] libbpf,bpf: share BTF reconcile-related code with kernel Alan Maguire
2024-03-29 22:04 ` Andrii Nakryiko
2024-04-01 15:58 ` Andrii Nakryiko
2024-03-22 10:24 ` [RFC bpf-next 12/13] selftests/bpf: extend base reference tests cover BTF reconciliation Alan Maguire
2024-03-22 10:24 ` [RFC bpf-next 13/13] bpftool: support displaying reconciled-with-base split BTF Alan Maguire
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240322102455.98558-5-alan.maguire@oracle.com \
--to=alan.maguire@oracle.com \
--cc=acme@redhat.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=haoluo@google.com \
--cc=houtao1@huawei.com \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kpsingh@kernel.org \
--cc=martin.lau@linux.dev \
--cc=masahiroy@kernel.org \
--cc=mcgrof@kernel.org \
--cc=mykolal@fb.com \
--cc=nathan@kernel.org \
--cc=quentin@isovalent.com \
--cc=sdf@google.com \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox