Skip to content

Commit efdd3eb

Browse files
anakryikoborkmann
authored andcommitted
libbpf: Accommodate DWARF/compiler bug with duplicated structs
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 6b6e6b1 ("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. 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 <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 7615209 commit efdd3eb

File tree

1 file changed

+41
-4
lines changed

1 file changed

+41
-4
lines changed

tools/lib/bpf/btf.c

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3477,8 +3477,8 @@ static long btf_hash_struct(struct btf_type *t)
34773477
}
34783478

34793479
/*
3480-
* Check structural compatibility of two FUNC_PROTOs, ignoring referenced type
3481-
* IDs. This check is performed during type graph equivalence check and
3480+
* Check structural compatibility of two STRUCTs/UNIONs, ignoring referenced
3481+
* type IDs. This check is performed during type graph equivalence check and
34823482
* referenced types equivalence is checked separately.
34833483
*/
34843484
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)
38513851
return btf_equal_array(t1, t2);
38523852
}
38533853

3854+
/* Check if given two types are identical STRUCT/UNION definitions */
3855+
static bool btf_dedup_identical_structs(struct btf_dedup *d, __u32 id1, __u32 id2)
3856+
{
3857+
const struct btf_member *m1, *m2;
3858+
struct btf_type *t1, *t2;
3859+
int n, i;
3860+
3861+
t1 = btf_type_by_id(d->btf, id1);
3862+
t2 = btf_type_by_id(d->btf, id2);
3863+
3864+
if (!btf_is_composite(t1) || btf_kind(t1) != btf_kind(t2))
3865+
return false;
3866+
3867+
if (!btf_shallow_equal_struct(t1, t2))
3868+
return false;
3869+
3870+
m1 = btf_members(t1);
3871+
m2 = btf_members(t2);
3872+
for (i = 0, n = btf_vlen(t1); i < n; i++, m1++, m2++) {
3873+
if (m1->type != m2->type)
3874+
return false;
3875+
}
3876+
return true;
3877+
}
3878+
38543879
/*
38553880
* Check equivalence of BTF type graph formed by candidate struct/union (we'll
38563881
* 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,
39623987

39633988
hypot_type_id = d->hypot_map[canon_id];
39643989
if (hypot_type_id <= BTF_MAX_NR_TYPES) {
3990+
if (hypot_type_id == cand_id)
3991+
return 1;
39653992
/* In some cases compiler will generate different DWARF types
39663993
* for *identical* array type definitions and use them for
39673994
* 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,
39703997
* types within a single CU. So work around that by explicitly
39713998
* allowing identical array types here.
39723999
*/
3973-
return hypot_type_id == cand_id ||
3974-
btf_dedup_identical_arrays(d, hypot_type_id, cand_id);
4000+
if (btf_dedup_identical_arrays(d, hypot_type_id, cand_id))
4001+
return 1;
4002+
/* It turns out that similar situation can happen with
4003+
* struct/union sometimes, sigh... Handle the case where
4004+
* structs/unions are exactly the same, down to the referenced
4005+
* type IDs. Anything more complicated (e.g., if referenced
4006+
* types are different, but equivalent) is *way more*
4007+
* complicated and requires a many-to-many equivalence mapping.
4008+
*/
4009+
if (btf_dedup_identical_structs(d, hypot_type_id, cand_id))
4010+
return 1;
4011+
return 0;
39754012
}
39764013

39774014
if (btf_dedup_hypot_map_add(d, canon_id, cand_id))

0 commit comments

Comments
 (0)