We see identical type problems in [1] as a result of an occasionally applied volatile modifier to kernel data structures. Such things can result from different header include patterns, explicit Makefile rules etc. As a result consider types with modifiers const, volatile and restrict as equivalent for dedup equivalence testing purposes. Type tag is excluded from modifier equivalence as it would be possible we would end up with the type without the type tag annotations in the final BTF, which could potentially lead to information loss. [1] https://lore.kernel.org/bpf/42a1b4b0-83d0-4dda-b1df-15a1b7c7638d@linux.ibm.com/ Reported-by: Nilay Shroff Signed-off-by: Alan Maguire --- tools/lib/bpf/btf.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index b136572e889a..89fbeed948a8 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -4677,12 +4677,10 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, cand_kind = btf_kind(cand_type); canon_kind = btf_kind(canon_type); - if (cand_type->name_off != canon_type->name_off) - return 0; - /* FWD <--> STRUCT/UNION equivalence check, if enabled */ - if ((cand_kind == BTF_KIND_FWD || canon_kind == BTF_KIND_FWD) - && cand_kind != canon_kind) { + if ((cand_kind == BTF_KIND_FWD || canon_kind == BTF_KIND_FWD) && + cand_type->name_off == canon_type->name_off && + cand_kind != canon_kind) { __u16 real_kind; __u16 fwd_kind; @@ -4699,7 +4697,24 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id, return fwd_kind == real_kind; } - if (cand_kind != canon_kind) + /* + * Types are considered equivalent if modifiers (const, volatile, + * restrict) are present for one but not the other. + */ + if (cand_kind != canon_kind) { + __u32 next_cand_id = cand_id; + __u32 next_canon_id = canon_id; + + if (btf_is_mod(cand_type) && !btf_is_type_tag(cand_type)) + next_cand_id = cand_type->type; + if (btf_is_mod(canon_type) && !btf_is_type_tag(canon_type)) + next_canon_id = canon_type->type; + if (cand_id == next_cand_id && canon_id == next_canon_id) + return 0; + return btf_dedup_is_equiv(d, next_cand_id, next_canon_id); + } + + if (cand_type->name_off != canon_type->name_off) return 0; switch (cand_kind) { -- 2.39.3