Skip to content

Commit f225ee2

Browse files
jetlimeKernel Patches Daemon
authored andcommitted
libbpf: fix BTF dedup to support recursive typedef definitions
Handle recursive typedefs in BTF deduplication Pahole fails to encode BTF for some Go projects (e.g. Kubernetes and Podman) due to recursive type definitions that create reference loops not representable in C. These recursive typedefs trigger a failure in the BTF deduplication algorithm. This patch extends btf_dedup_ref_type() to properly handle potential recursion for BTF_KIND_TYPEDEF, similar to how recursion is already handled for BTF_KIND_STRUCT. This allows pahole to successfully generate BTF for Go binaries using recursive types without impacting existing C-based workflows. Co-developed-by: Martin Horth <[email protected]> Signed-off-by: Martin Horth <[email protected]> Co-developed-by: Ouail Derghal <[email protected]> Signed-off-by: Ouail Derghal <[email protected]> Co-developed-by: Guilhem Jazeron <[email protected]> Signed-off-by: Guilhem Jazeron <[email protected]> Co-developed-by: Ludovic Paillat <[email protected]> Signed-off-by: Ludovic Paillat <[email protected]> Co-developed-by: Robin Theveniaut <[email protected]> Signed-off-by: Robin Theveniaut <[email protected]> Suggested-by: Tristan d'Audibert <[email protected]> Signed-off-by: Paul Houssel <[email protected]>
1 parent 4eb9670 commit f225ee2

File tree

1 file changed

+95
-2
lines changed

1 file changed

+95
-2
lines changed

tools/lib/bpf/btf.c

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3408,6 +3408,7 @@ static int btf_dedup_prep(struct btf_dedup *d);
34083408
static int btf_dedup_strings(struct btf_dedup *d);
34093409
static int btf_dedup_prim_types(struct btf_dedup *d);
34103410
static int btf_dedup_struct_types(struct btf_dedup *d);
3411+
static int btf_dedup_typedef_types(struct btf_dedup *d);
34113412
static int btf_dedup_ref_types(struct btf_dedup *d);
34123413
static int btf_dedup_resolve_fwds(struct btf_dedup *d);
34133414
static int btf_dedup_compact_types(struct btf_dedup *d);
@@ -3590,6 +3591,11 @@ int btf__dedup(struct btf *btf, const struct btf_dedup_opts *opts)
35903591
pr_debug("btf_dedup_struct_types failed: %s\n", errstr(err));
35913592
goto done;
35923593
}
3594+
err = btf_dedup_typedef_types(d);
3595+
if (err < 0) {
3596+
pr_debug("btf_dedup_typedef_types failed: %s\n", errstr(err));
3597+
goto done;
3598+
}
35933599
err = btf_dedup_resolve_fwds(d);
35943600
if (err < 0) {
35953601
pr_debug("btf_dedup_resolve_fwds failed: %s\n", errstr(err));
@@ -3901,6 +3907,20 @@ static int btf_dedup_strings(struct btf_dedup *d)
39013907
return err;
39023908
}
39033909

3910+
/*
3911+
* Calculate type signature hash of TYPEDEF, ignoring referenced type IDs,
3912+
* as referenced type IDs equivalence is established separately during type
3913+
* graph equivalence check algorithm.
3914+
*/
3915+
static long btf_hash_typedef(struct btf_type *t)
3916+
{
3917+
long h;
3918+
3919+
h = hash_combine(0, t->name_off);
3920+
h = hash_combine(h, t->info);
3921+
return h;
3922+
}
3923+
39043924
static long btf_hash_common(struct btf_type *t)
39053925
{
39063926
long h;
@@ -3918,6 +3938,13 @@ static bool btf_equal_common(struct btf_type *t1, struct btf_type *t2)
39183938
t1->size == t2->size;
39193939
}
39203940

3941+
/* Check structural compatibility of two TYPEDEF. */
3942+
static bool btf_equal_typedef(struct btf_type *t1, struct btf_type *t2)
3943+
{
3944+
return t1->name_off == t2->name_off &&
3945+
t1->info == t2->info;
3946+
}
3947+
39213948
/* Calculate type signature hash of INT or TAG. */
39223949
static long btf_hash_int_decl_tag(struct btf_type *t)
39233950
{
@@ -4936,10 +4963,77 @@ static int btf_dedup_struct_types(struct btf_dedup *d)
49364963
return 0;
49374964
}
49384965

4966+
/*
4967+
* Deduplicate typedef types.
4968+
*
4969+
* Similar as for struct/union types, for each typedef type its type
4970+
* signature hash is calculated, taking into account type's name
4971+
* and its size, but ignoring type ID's referenced from fields,
4972+
* because they might not be deduped completely until after
4973+
* reference types deduplication phase.
4974+
*/
4975+
static int btf_dedup_typedef_type(struct btf_dedup *d, __u32 type_id)
4976+
{
4977+
struct btf_type *cand_type, *t;
4978+
struct hashmap_entry *hash_entry;
4979+
/* if we don't find equivalent type, then we are canonical */
4980+
__u32 new_id = type_id;
4981+
__u16 kind;
4982+
long h;
4983+
4984+
if (d->map[type_id] <= BTF_MAX_NR_TYPES)
4985+
return 0;
4986+
4987+
t = btf_type_by_id(d->btf, type_id);
4988+
kind = btf_kind(t);
4989+
4990+
if (kind != BTF_KIND_TYPEDEF)
4991+
return 0;
4992+
h = btf_hash_typedef(t);
4993+
for_each_dedup_cand(d, hash_entry, h) {
4994+
__u32 cand_id = hash_entry->value;
4995+
int eq;
4996+
4997+
cand_type = btf_type_by_id(d->btf, cand_id);
4998+
if (!btf_equal_typedef(t, cand_type))
4999+
continue;
5000+
5001+
btf_dedup_clear_hypot_map(d);
5002+
eq = btf_dedup_is_equiv(d, type_id, cand_id);
5003+
if (eq < 0)
5004+
return eq;
5005+
if (!eq)
5006+
continue;
5007+
btf_dedup_merge_hypot_map(d);
5008+
if (d->hypot_adjust_canon) /* not really equivalent */
5009+
continue;
5010+
new_id = cand_id;
5011+
break;
5012+
}
5013+
5014+
d->map[type_id] = new_id;
5015+
if (type_id == new_id && btf_dedup_table_add(d, h, type_id))
5016+
return -ENOMEM;
5017+
5018+
return 0;
5019+
}
5020+
5021+
static int btf_dedup_typedef_types(struct btf_dedup *d)
5022+
{
5023+
int i, err;
5024+
5025+
for (i = 0; i < d->btf->nr_types; i++) {
5026+
err = btf_dedup_typedef_type(d, d->btf->start_id + i);
5027+
if (err)
5028+
return err;
5029+
}
5030+
return 0;
5031+
}
5032+
49395033
/*
49405034
* Deduplicate reference type.
49415035
*
4942-
* Once all primitive and struct/union types got deduplicated, we can easily
5036+
* Once all primitive, struct/union and typedef types got deduplicated, we can easily
49435037
* deduplicate all other (reference) BTF types. This is done in two steps:
49445038
*
49455039
* 1. Resolve all referenced type IDs into their canonical type IDs. This
@@ -4982,7 +5076,6 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
49825076
case BTF_KIND_VOLATILE:
49835077
case BTF_KIND_RESTRICT:
49845078
case BTF_KIND_PTR:
4985-
case BTF_KIND_TYPEDEF:
49865079
case BTF_KIND_FUNC:
49875080
case BTF_KIND_TYPE_TAG:
49885081
ref_type_id = btf_dedup_ref_type(d, t->type);

0 commit comments

Comments
 (0)