All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alan Maguire <alan.maguire@oracle.com>
To: Mingpei CAO <caomingpei@gmail.com>, bpf@vger.kernel.org
Cc: alexei.starovoitov@gmail.com, andrii@kernel.org, eddyz87@gmail.com
Subject: Re: [PATCH bpf 2/2] selftests/bpf: Test array element comparison in BTF dedup
Date: Mon, 7 Sep 2026 16:45:10 +0100	[thread overview]
Message-ID: <f22d3b93-65b5-4b06-9af8-99d0e65eb33b@oracle.com> (raw)
In-Reply-To: <20260907131021.34343-3-caomingpei@gmail.com>

On 07/09/2026 14:10, Mingpei CAO wrote:
> Exercise recursive array comparison with different and identical
> element definitions. Check that distinct containers remain separate
> and identical types are deduplicated, including their references.
> 
> The negative case fails before the fix and passes afterwards.
> The positive case passes both before and after the fix.
> 
> Assisted-by: LLM
> Signed-off-by: Mingpei CAO <caomingpei@gmail.com>

this test would be better placed in prog_tests/btf.c I think where there
are a number of other BTF dedup tests; something like the following
is roughly equivalent to what you have:

diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c
index 67b9015cbd98..1c4a46e2a64d 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf.c
@@ -7062,6 +7062,94 @@ static struct btf_dedup_test dedup_tests[] = {
                BTF_STR_SEC("\0int\0long int"),
        },
 },
+{
+       .descr = "dedup: array element comparison",
+       .input = {
+               .raw_types = {
+                       /* signed int */
+                       BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4),
 /* [1] */
+                       /* unsigned int */
+                       BTF_TYPE_INT_ENC(NAME_NTH(2), 0, 0, 32, 4),             
        /* [2] */
+                       /* signed int[1] */
+                       BTF_TYPE_ARRAY_ENC(1, 1, 1),                            
        /* [3] */
+                       /* duplicate signed int[1] */
+                       BTF_TYPE_ARRAY_ENC(1, 1, 1),                                    /* [4] */
+                       /* unsigned int[1] */
+                       BTF_TYPE_ARRAY_ENC(2, 2, 1),                                    /* [5] */
+                       /* struct s { signed int a[1]; signed int b[1]; } */
+                       BTF_STRUCT_ENC(NAME_NTH(3), 2, 8),                              /* [6] */
+                       BTF_MEMBER_ENC(NAME_NTH(4), 3, 0),
+                       BTF_MEMBER_ENC(NAME_NTH(5), 3, 32),
+                       /* struct s { signed int a[1]; unsigned int b[1]; } */
+                       BTF_STRUCT_ENC(NAME_NTH(3), 2, 8),                              /* [7] */
+                       BTF_MEMBER_ENC(NAME_NTH(4), 4, 0),
+                       BTF_MEMBER_ENC(NAME_NTH(5), 5, 32),
+                       BTF_END_RAW,
+               },
+               BTF_STR_SEC("\0int\0unsigned int\0s\0a\0b"),
+       },
+       .expect = {
+               .raw_types = {
+                       BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4), /* [1] */
+                       BTF_TYPE_INT_ENC(NAME_NTH(2), 0, 0, 32, 4),                     /* [2] */
+                       BTF_TYPE_ARRAY_ENC(1, 1, 1),                                    /* [3] */
+                       BTF_TYPE_ARRAY_ENC(2, 2, 1),                                    /* [4] */
+                       BTF_STRUCT_ENC(NAME_NTH(3), 2, 8),                              /* [5] */
+                       BTF_MEMBER_ENC(NAME_NTH(4), 3, 0),
+                       BTF_MEMBER_ENC(NAME_NTH(5), 3, 32),
+                       BTF_STRUCT_ENC(NAME_NTH(3), 2, 8),                              /* [6] */
+                       BTF_MEMBER_ENC(NAME_NTH(4), 3, 0),
+                       BTF_MEMBER_ENC(NAME_NTH(5), 4, 32),
+                       BTF_END_RAW,
+               },
+               BTF_STR_SEC("\0int\0unsigned int\0s\0a\0b"),
+       },
+},
+{
+       .descr = "dedup: identical array element comparison",
+       .input = {
+               .raw_types = {
+                       /* int */
+                       BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4), /* [1] */
+                       /* struct container { struct elem first[1]; struct elem second[1]; } */
+                       BTF_STRUCT_ENC(NAME_NTH(2), 2, 8),                              /* [2] */
+                       BTF_MEMBER_ENC(NAME_NTH(3), 3, 0),
+                       BTF_MEMBER_ENC(NAME_NTH(4), 3, 32),
+                       /* struct elem[1] */
+                       BTF_TYPE_ARRAY_ENC(4, 1, 1),                                    /* [3] */
+                       /* struct elem { int x; } */
+                       BTF_STRUCT_ENC(NAME_NTH(5), 1, 4),                              /* [4] */
+                       BTF_MEMBER_ENC(NAME_NTH(6), 1, 0),
+                       /* duplicate struct container */
+                       BTF_STRUCT_ENC(NAME_NTH(2), 2, 8),                              /* [5] */
+                       BTF_MEMBER_ENC(NAME_NTH(3), 6, 0),
+                       BTF_MEMBER_ENC(NAME_NTH(4), 7, 32),
+                       /* duplicate struct elem[1] */
+                       BTF_TYPE_ARRAY_ENC(8, 1, 1),                                    /* [6] */
+                       BTF_TYPE_ARRAY_ENC(9, 1, 1),                                    /* [7] */
+                       /* duplicate struct elem */
+                       BTF_STRUCT_ENC(NAME_NTH(5), 1, 4),                              /* [8] */
+                       BTF_MEMBER_ENC(NAME_NTH(6), 1, 0),
+                       BTF_STRUCT_ENC(NAME_NTH(5), 1, 4),                              /* [9] */
+                       BTF_MEMBER_ENC(NAME_NTH(6), 1, 0),
+                       BTF_END_RAW,
+               },
+               BTF_STR_SEC("\0int\0container\0first\0second\0elem\0x"),
+       },
+       .expect = {
+               .raw_types = {
+                       BTF_TYPE_INT_ENC(NAME_NTH(1), BTF_INT_SIGNED, 0, 32, 4), /* [1] */
+                       BTF_STRUCT_ENC(NAME_NTH(2), 2, 8),                              /* [2] */
+                       BTF_MEMBER_ENC(NAME_NTH(3), 3, 0),
+                       BTF_MEMBER_ENC(NAME_NTH(4), 3, 32),
+                       BTF_TYPE_ARRAY_ENC(4, 1, 1),                                    /* [3] */
+                       BTF_STRUCT_ENC(NAME_NTH(5), 1, 4),                              /* [4] */
+                       BTF_MEMBER_ENC(NAME_NTH(6), 1, 0),
+                       BTF_END_RAW,
+               },
+               BTF_STR_SEC("\0int\0container\0first\0second\0elem\0x"),
+       },
+},
 {
        .descr = "dedup: struct example #1",
        /*

> ---
>  .../selftests/bpf/prog_tests/btf_dedup.c      | 68 +++++++++++++++++++
>  1 file changed, 68 insertions(+)
>  create mode 100644 tools/testing/selftests/bpf/prog_tests/btf_dedup.c
> 
> diff --git a/tools/testing/selftests/bpf/prog_tests/btf_dedup.c b/tools/testing/selftests/bpf/prog_tests/btf_dedup.c
> new file mode 100644
> index 000000000000..3e889c0bed53
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/btf_dedup.c
> @@ -0,0 +1,68 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <test_progs.h>
> +#include <bpf/btf.h>
> +#include "btf_helpers.h"
> +
> +static void test_array_element_types(bool identical)
> +{
> +	struct btf *btf;
> +
> +	btf = btf__new_empty();
> +	if (!ASSERT_OK_PTR(btf, "btf_new"))
> +		return;
> +
> +	/*
> +	 * Comparing the first fields maps array [3] to [6]. The second
> +	 * fields reuse [3], requiring an identical-type check of [6]/[7].
> +	 * Place container [5] before its elements [8]/[9] so they still
> +	 * have distinct IDs when their definitions are compared.
> +	 */
> +	if (!ASSERT_EQ(btf__add_int(btf, "int", 4, BTF_INT_SIGNED), 1, "int") ||
> +	    !ASSERT_EQ(btf__add_struct(btf, "container", 8), 2, "container1") ||
> +	    !ASSERT_OK(btf__add_field(btf, "first", 3, 0, 0), "first1") ||
> +	    !ASSERT_OK(btf__add_field(btf, "second", 3, 32, 0), "second1") ||
> +	    !ASSERT_EQ(btf__add_array(btf, 1, 4, 1), 3, "array1") ||
> +	    !ASSERT_EQ(btf__add_struct(btf, "elem", 4), 4, "elem1") ||
> +	    !ASSERT_OK(btf__add_field(btf, "x", 1, 0, 0), "elem1_field") ||
> +	    !ASSERT_EQ(btf__add_struct(btf, "container", 8), 5, "container2") ||
> +	    !ASSERT_OK(btf__add_field(btf, "first", 6, 0, 0), "first2") ||
> +	    !ASSERT_OK(btf__add_field(btf, "second", 7, 32, 0), "second2") ||
> +	    !ASSERT_EQ(btf__add_array(btf, 1, 8, 1), 6, "array2") ||
> +	    !ASSERT_EQ(btf__add_array(btf, 1, 9, 1), 7, "array3") ||
> +	    !ASSERT_EQ(btf__add_struct(btf, "elem", 4), 8, "elem2") ||
> +	    !ASSERT_OK(btf__add_field(btf, "x", 1, 0, 0), "elem2_field") ||
> +	    !ASSERT_EQ(btf__add_struct(btf, "elem", 4), 9, "elem3") ||
> +	    !ASSERT_OK(btf__add_field(btf, identical ? "x" : "y", 1, 0, 0), "elem3_field"))
> +		goto out;
> +
> +	if (!ASSERT_OK(btf__dedup(btf, NULL), "dedup"))
> +		goto out;
> +
> +	/* Identical elements leave only the first four expected types. */
> +	btf_validate_raw(btf, identical ? 4 : 7, (const char *[]) {
> +		"[1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED",
> +		"[2] STRUCT 'container' size=8 vlen=2\n"
> +		"\t'first' type_id=3 bits_offset=0\n"
> +		"\t'second' type_id=3 bits_offset=32",
> +		"[3] ARRAY '(anon)' type_id=4 index_type_id=1 nr_elems=1",
> +		"[4] STRUCT 'elem' size=4 vlen=1\n"
> +		"\t'x' type_id=1 bits_offset=0",
> +		"[5] STRUCT 'container' size=8 vlen=2\n"
> +		"\t'first' type_id=3 bits_offset=0\n"
> +		"\t'second' type_id=6 bits_offset=32",
> +		"[6] ARRAY '(anon)' type_id=7 index_type_id=1 nr_elems=1",
> +		"[7] STRUCT 'elem' size=4 vlen=1\n"
> +		"\t'y' type_id=1 bits_offset=0",
> +	});
> +
> +out:
> +	btf__free(btf);
> +}
> +
> +void test_btf_dedup(void)
> +{
> +	if (test__start_subtest("array_different_element_types"))
> +		test_array_element_types(false);
> +	if (test__start_subtest("array_identical_element_types"))
> +		test_array_element_types(true);
> +}


  reply	other threads:[~2026-09-07 15:46 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-06 10:23 [BUG] libbpf: BTF dedup merges arrays with different element types Mingpei CAO
2026-09-06 21:27 ` Alexei Starovoitov
2026-09-07 13:10 ` [PATCH bpf 0/2] libbpf: Fix array comparison in BTF dedup Mingpei CAO
2026-09-07 13:10   ` [PATCH bpf 1/2] " Mingpei CAO
2026-09-07 13:10   ` [PATCH bpf 2/2] selftests/bpf: Test array element " Mingpei CAO
2026-09-07 15:45     ` Alan Maguire [this message]
2026-09-07 16:30       ` Mingpei CAO

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=f22d3b93-65b5-4b06-9af8-99d0e65eb33b@oracle.com \
    --to=alan.maguire@oracle.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=caomingpei@gmail.com \
    --cc=eddyz87@gmail.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.