Re: pahole and gcc-14 issues

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Apr 28, 2025 at 11:59 PM Andrii Nakryiko
<andrii.nakryiko@xxxxxxxxx> wrote:
>
> On Mon, Apr 28, 2025 at 5:33 PM Andrii Nakryiko
> <andrii.nakryiko@xxxxxxxxx> wrote:
> >
> > On Mon, Apr 28, 2025 at 3:12 PM Alexei Starovoitov
> > <alexei.starovoitov@xxxxxxxxx> wrote:
> > >
> > > On Mon, Apr 28, 2025 at 8:21 AM Alan Maguire <alan.maguire@xxxxxxxxxx> wrote:
> > > >
> > > >  <1><4bd05>: Abbrev Number: 58 (DW_TAG_pointer_type)
> > > >     <4bd06>   DW_AT_byte_size   : 8
> > > >     <4bd07>   DW_AT_address_class: 2
> > > >     <4bd08>   DW_AT_type        : <0x301cd>
> > > >
> > > > ...which points at an int
> > > >
> > > >  <1><301cd>: Abbrev Number: 214 (DW_TAG_base_type)
> > > >     <301cf>   DW_AT_byte_size   : 4
> > > >     <301d0>   DW_AT_encoding    : 5     (signed)
> > > >     <301d1>   DW_AT_name        : int
> > > >     <301d5>   DW_AT_name        : int
> > > >
> > > > ...but note the the DW_AT_address_class attribute in the latter case and
> > > > the two DW_AT_name values. We don't use that address attribute in pahole
> > > > as far as I can see, but it might be enough to cause problems.
> > >
> > > DW_AT_address_class is there because it's an actual address space
> > > qualifier in C. The dwarf is correct, but I thought pahole
> > > will ignore it while converting to BTF, so it shouldn't matter
> > > from dedup pov.
> > >
> > > And since dedup is working for vmlinux BTF, I doubt there are CUs
> > > where the same type is represented with different dwarf id-s.
> > > Otherwise dedup wouldn't have worked for vmlinux.
> > >
> > > DW_AT_name is concerning. Sounds like it's a gcc bug, but it
> > > shouldn't be causing dedup issues for modules.
> > >
> > > So what is the workaround?
> >
> > I'm thinking of generalizing Alan's proposed fix so that all our
> > existing special equality cases (arrays, identical structs, and now
> > pointers to identical types) are handled a bit more generically. I'll
> > try to get a patch out later tonight.
>
> So I ran out of time, but I'm thinking something like below. It
> results in identical bpf_testmod.ko compared to Alan's proposed fix,
> so perhaps we should just go with the simpler approach. But this one
> should stand the test of time a bit better.
>
> In any case, I'd like to be able to handle not just PTR -> TYPE chain,
> but also some PTR -> MODIFIER* -> TYPE chains at the very least.
> Because any const in the chain will throw off Alan's heuristic.
>

Ok, so sleeping on this a bit more, I'm hesitant to do this more
generic approach, as now we'll be running a risk of potentially
looping indefinitely (the max_depth check I added doesn't completely
prevent this).

So, Alan, do you mind sending your proposed patch for formal review
and BPF CI testing? Just please use btf_is_ptr() check instead of
explicit kind equality, thanks!

> I'll try to benchmark and polish the patch tomorrow and post it for
> proper review.
>
>
> diff --git a/src/btf.c b/src/btf.c
> index e9673c0ecbe7..e4a3e3183742 100644
> --- a/src/btf.c
> +++ b/src/btf.c
> @@ -4310,6 +4310,8 @@ static bool btf_dedup_identical_arrays(struct
> btf_dedup *d, __u32 id1, __u32 id2
>   return btf_equal_array(t1, t2);
>  }
>
> +static bool btf_dedup_identical_types(struct btf_dedup *d, __u32 id1,
> __u32 id2);
> +
>  /* Check if given two types are identical STRUCT/UNION definitions */
>  static bool btf_dedup_identical_structs(struct btf_dedup *d, __u32
> id1, __u32 id2)
>  {
> @@ -4329,14 +4331,93 @@ static bool btf_dedup_identical_structs(struct
> btf_dedup *d, __u32 id1, __u32 id
>   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 &&
> -     !btf_dedup_identical_arrays(d, m1->type, m2->type) &&
> -     !btf_dedup_identical_structs(d, m1->type, m2->type))
> + if (m1->type != m2->type && !btf_dedup_identical_types(d, m1->type, m2->type))
> + return false;
> + }
> + return true;
> +}
> +
> +static bool btf_dedup_identical_fnprotos(struct btf_dedup *d, __u32
> id1, __u32 id2)
> +{
> + const struct btf_param *p1, *p2;
> + 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_func_proto(t1) || !btf_is_func_proto(t2))
> + return false;
> +
> + if (!btf_compat_fnproto(t1, t2))
> + return false;
> +
> + if (!btf_dedup_identical_types(d, t1->type, t2->type))
> + return false;
> +
> + p1 = btf_params(t1);
> + p2 = btf_params(t2);
> + for (i = 0, n = btf_vlen(t1); i < n; i++, p1++, p2++) {
> + if (p1->type != p2->type && !btf_dedup_identical_types(d, p1->type, p2->type))
>   return false;
>   }
>   return true;
>  }
>
> +static bool btf_dedup_identical_types(struct btf_dedup *d, __u32 id1,
> __u32 id2)
> +{
> + int max_depth = 32;
> +
> + while (max_depth-- > 0) {
> + struct btf_type *t1, *t2;
> + int k1, k2;
> +
> + t1 = btf_type_by_id(d->btf, id1);
> + t2 = btf_type_by_id(d->btf, id2);
> +
> + k1 = btf_kind(t1);
> + k2 = btf_kind(t2);
> + if (k1 != k2)
> + return false;
> +
> + switch (k1) {
> + case BTF_KIND_UNKN: /* VOID */
> + return true;
> + case BTF_KIND_INT:
> + return btf_equal_int_tag(t1, t2);
> + case BTF_KIND_ENUM:
> + case BTF_KIND_ENUM64:
> + return btf_compat_enum(t1, t2);
> + case BTF_KIND_FWD:
> + case BTF_KIND_FLOAT:
> + return btf_equal_common(t1, t2);
> + case BTF_KIND_CONST:
> + case BTF_KIND_VOLATILE:
> + case BTF_KIND_RESTRICT:
> + case BTF_KIND_PTR:
> + case BTF_KIND_TYPEDEF:
> + case BTF_KIND_FUNC:
> + case BTF_KIND_TYPE_TAG:
> + if (t1->info != t2->info)
> + return 0;
> + id1 = t1->type;
> + id2 = t2->type;
> + continue;
> + case BTF_KIND_ARRAY:
> + return btf_equal_array(t1, t2);
> + case BTF_KIND_STRUCT:
> + case BTF_KIND_UNION:
> + return btf_dedup_identical_structs(d, id1, id2);
> + case BTF_KIND_FUNC_PROTO:
> + return btf_dedup_identical_fnprotos(d, id1, id2);
> + default:
> + return false;
> + }
> + }
> + return false;
> +}
> +
> +
>  /*
>   * 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
> @@ -4458,8 +4539,6 @@ 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.
>   */
> - 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
> @@ -4467,7 +4546,7 @@ static int btf_dedup_is_equiv(struct btf_dedup
> *d, __u32 cand_id,
>   * 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))
> + if (btf_dedup_identical_types(d, hypot_type_id, cand_id))
>   return 1;
>   return 0;
>   }
>
> >
> > >
> > > We need to find it asap. Since at present we cannot build
> > > kernels with gcc-14, since modules won't dedup BTF.
> > > Hence a bunch of selftests/bpf are failing.
> > > We want to upgrade BPF CI to gcc-14 to catch nginx-like issues,
> > > but we cannot until this pahole/dedup issue is resolved.





[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux