From: Jiri Olsa <jolsa@redhat.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Andrii Nakryiko <andrii@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
bpf <bpf@vger.kernel.org>, Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Kernel Team <kernel-team@fb.com>
Subject: Re: [PATCH bpf-next 1/2] libbpf: accommodate DWARF/compiler bug with duplicated structs
Date: Thu, 18 Nov 2021 15:27:14 +0100 [thread overview]
Message-ID: <YZZiwnWReYnthtzH@krava> (raw)
In-Reply-To: <CAEf4Bza2NSV8MBb0jSokmUcrzy0SpLvY2uqu4mG9ObxnT-jQLw@mail.gmail.com>
On Wed, Nov 17, 2021 at 11:42:58AM -0800, Andrii Nakryiko wrote:
> On Wed, Nov 17, 2021 at 11:41 AM Andrii Nakryiko <andrii@kernel.org> wrote:
> >
> > According to [0], compilers sometimes might produce duplicate DWARF
> > definitions for exactly the same struct/union within the same
> > compilation unit (CU). We've had similar issues with identical arrays
> > and handled them with a similar workaround in 6b6e6b1d09aa ("libbpf:
> > Accomodate DWARF/compiler bug with duplicated identical arrays"). Do the
> > same for struct/union by ensuring that two structs/unions are exactly
> > the same, down to the integer values of field referenced type IDs.
>
> Jiri, can you please try this in your setup and see if that handles
> all situations or there are more complicated ones still. We'll need a
> test for more complicated ones in that case :( Thanks.
it seems to help largely, but I still see few modules (67 out of 780)
that keep 'struct module' for some reason.. their struct module looks
completely the same as is in vmlinux
I uploaded one of the module with vmlinux in here:
http://people.redhat.com/~jolsa/kmodbtf/2/
I will do some debugging and find out why it did not work in this module
and try to come up with another test
thanks,
jirka
>
> >
> > Solving this more generically (allowing referenced types to be
> > equivalent, but using different type IDs, all within a single CU)
> > requires a huge complexity increase to handle many-to-many mappings
> > between canonidal and candidate type graphs. Before we invest in that,
> > let's see if this approach handles all the instances of this issue in
> > practice. Thankfully it's pretty rare, it seems.
> >
> > [0] https://lore.kernel.org/bpf/YXr2NFlJTAhHdZqq@krava/
> >
> > Reported-by: Jiri Olsa <jolsa@kernel.org>
> > Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
> > ---
> > tools/lib/bpf/btf.c | 45 +++++++++++++++++++++++++++++++++++++++++----
> > 1 file changed, 41 insertions(+), 4 deletions(-)
> >
> > diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> > index b6be579e0dc6..e97217a77196 100644
> > --- a/tools/lib/bpf/btf.c
> > +++ b/tools/lib/bpf/btf.c
> > @@ -3477,8 +3477,8 @@ static long btf_hash_struct(struct btf_type *t)
> > }
> >
> > /*
> > - * Check structural compatibility of two FUNC_PROTOs, ignoring referenced type
> > - * IDs. This check is performed during type graph equivalence check and
> > + * Check structural compatibility of two STRUCTs/UNIONs, ignoring referenced
> > + * type IDs. This check is performed during type graph equivalence check and
> > * referenced types equivalence is checked separately.
> > */
> > static bool btf_shallow_equal_struct(struct btf_type *t1, struct btf_type *t2)
> > @@ -3851,6 +3851,31 @@ static int btf_dedup_identical_arrays(struct btf_dedup *d, __u32 id1, __u32 id2)
> > return btf_equal_array(t1, t2);
> > }
> >
> > +/* Check if given two types are identical STRUCT/UNION definitions */
> > +static bool btf_dedup_identical_structs(struct btf_dedup *d, __u32 id1, __u32 id2)
> > +{
> > + const struct btf_member *m1, *m2;
> > + struct btf_type *t1, *t2;
> > + int n, i;
> > +
> > + t1 = btf_type_by_id(d->btf, id1);
> > + t2 = btf_type_by_id(d->btf, id2);
> > +
> > + if (!btf_is_composite(t1) || btf_kind(t1) != btf_kind(t2))
> > + return false;
> > +
> > + if (!btf_shallow_equal_struct(t1, t2))
> > + return false;
> > +
> > + m1 = btf_members(t1);
> > + m2 = btf_members(t2);
> > + for (i = 0, n = btf_vlen(t1); i < n; i++, m1++, m2++) {
> > + if (m1->type != m2->type)
> > + return false;
> > + }
> > + return true;
> > +}
> > +
> > /*
> > * Check equivalence of BTF type graph formed by candidate struct/union (we'll
> > * call it "candidate graph" in this description for brevity) to a type graph
> > @@ -3962,6 +3987,8 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
> >
> > hypot_type_id = d->hypot_map[canon_id];
> > if (hypot_type_id <= BTF_MAX_NR_TYPES) {
> > + if (hypot_type_id == cand_id)
> > + return 1;
> > /* In some cases compiler will generate different DWARF types
> > * for *identical* array type definitions and use them for
> > * different fields within the *same* struct. This breaks type
> > @@ -3970,8 +3997,18 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
> > * types within a single CU. So work around that by explicitly
> > * allowing identical array types here.
> > */
> > - return hypot_type_id == cand_id ||
> > - btf_dedup_identical_arrays(d, hypot_type_id, cand_id);
> > + if (btf_dedup_identical_arrays(d, hypot_type_id, cand_id))
> > + return 1;
> > + /* It turns out that similar situation can happen with
> > + * struct/union sometimes, sigh... Handle the case where
> > + * structs/unions are exactly the same, down to the referenced
> > + * type IDs. Anything more complicated (e.g., if referenced
> > + * types are different, but equivalent) is *way more*
> > + * complicated and requires a many-to-many equivalence mapping.
> > + */
> > + if (btf_dedup_identical_structs(d, hypot_type_id, cand_id))
> > + return 1;
> > + return 0;
> > }
> >
> > if (btf_dedup_hypot_map_add(d, canon_id, cand_id))
> > --
> > 2.30.2
> >
>
next prev parent reply other threads:[~2021-11-18 14:27 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-17 19:41 [PATCH bpf-next 1/2] libbpf: accommodate DWARF/compiler bug with duplicated structs Andrii Nakryiko
2021-11-17 19:41 ` [PATCH bpf-next 2/2] selftests/bpf: add btf_dedup case with duplicated structs within CU Andrii Nakryiko
2021-11-17 19:42 ` [PATCH bpf-next 1/2] libbpf: accommodate DWARF/compiler bug with duplicated structs Andrii Nakryiko
2021-11-18 14:27 ` Jiri Olsa [this message]
2021-11-18 22:49 ` Andrii Nakryiko
2021-11-24 11:38 ` Jiri Olsa
2021-11-24 15:02 ` Jiri Olsa
2021-11-24 19:20 ` Andrii Nakryiko
2021-11-24 20:21 ` Jiri Olsa
2021-11-24 20:42 ` Andrii Nakryiko
2021-11-19 16:10 ` patchwork-bot+netdevbpf
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=YZZiwnWReYnthtzH@krava \
--to=jolsa@redhat.com \
--cc=andrii.nakryiko@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=jolsa@kernel.org \
--cc=kernel-team@fb.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox