Commit 556a3994 authored by Pu Lehui's avatar Pu Lehui Committed by Andrii Nakryiko
Browse files

selftests/bpf: Add distilled BTF test about marking BTF_IS_EMBEDDED



When redirecting the split BTF to the vmlinux base BTF, we need to mark
the distilled base struct/union members of split BTF structs/unions in
id_map with BTF_IS_EMBEDDED. This indicates that these types must match
both name and size later. So if a needed composite type, which is the
member of composite type in the split BTF, has a different size in the
base BTF we wish to relocate with, btf__relocate() should error out.

Signed-off-by: default avatarPu Lehui <pulehui@huawei.com>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20250115100241.4171581-4-pulehui@huaweicloud.com
parent 5ca681a8
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -601,6 +601,76 @@ static void test_distilled_endianness(void)
	btf__free(base);
}

/* If a needed composite type, which is the member of composite type
 * in the split BTF, has a different size in the base BTF we wish to
 * relocate with, btf__relocate() should error out.
 */
static void test_distilled_base_embedded_err(void)
{
	struct btf *btf1 = NULL, *btf2 = NULL, *btf3 = NULL, *btf4 = NULL, *btf5 = 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_struct(btf1, "s1", 4);                 /* [2] struct s1 { */
	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] STRUCT 's1' 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_struct(btf2, "with_embedded", 8);      /* [3] struct with_embedded { */
	btf__add_field(btf2, "e1", 2, 0, 0);		/*      struct s1 e1; */
							/* } */

	VALIDATE_RAW_BTF(
		btf2,
		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
		"[2] STRUCT 's1' size=4 vlen=1\n"
		"\t'f1' type_id=1 bits_offset=0",
		"[3] STRUCT 'with_embedded' size=8 vlen=1\n"
		"\t'e1' type_id=2 bits_offset=0");

	if (!ASSERT_EQ(0, btf__distill_base(btf2, &btf3, &btf4),
		       "distilled_base") ||
	    !ASSERT_OK_PTR(btf3, "distilled_base") ||
	    !ASSERT_OK_PTR(btf4, "distilled_split") ||
	    !ASSERT_EQ(2, btf__type_cnt(btf3), "distilled_base_type_cnt"))
		goto cleanup;

	VALIDATE_RAW_BTF(
		btf4,
		"[1] STRUCT 's1' size=4 vlen=0",
		"[2] STRUCT 'with_embedded' size=8 vlen=1\n"
		"\t'e1' type_id=1 bits_offset=0");

	btf5 = btf__new_empty();
	if (!ASSERT_OK_PTR(btf5, "empty_reloc_btf"))
		goto cleanup;

	btf__add_int(btf5, "int", 4, BTF_INT_SIGNED);   /* [1] int */
	/* struct with the same name but different size */
	btf__add_struct(btf5, "s1", 8);                 /* [2] struct s1 { */
	btf__add_field(btf5, "f1", 1, 0, 0);            /*      int f1; */
							/* } */

	ASSERT_EQ(btf__relocate(btf4, btf5), -EINVAL, "relocate_split");
cleanup:
	btf__free(btf5);
	btf__free(btf4);
	btf__free(btf3);
	btf__free(btf2);
	btf__free(btf1);
}

void test_btf_distill(void)
{
	if (test__start_subtest("distilled_base"))
@@ -613,6 +683,8 @@ void test_btf_distill(void)
		test_distilled_base_multi_err();
	if (test__start_subtest("distilled_base_multi_err2"))
		test_distilled_base_multi_err2();
	if (test__start_subtest("distilled_base_embedded_err"))
		test_distilled_base_embedded_err();
	if (test__start_subtest("distilled_base_vmlinux"))
		test_distilled_base_vmlinux();
	if (test__start_subtest("distilled_endianness"))