On Tue, 2026-09-01 at 17:57 +0100, Alan Maguire wrote: > Add support for new kinds to libbpf. BTF_KIND_LOC_PARAM and > BTF_KIND_LOC_PROTO are dedup-able so add support for their > deduplication, whereas since BTF_KIND_LOCSEC contains a unique > offset it is not. LOC_PARAM is considered a primary type > since it contains no external references; LOC_PROTO is a > reference type consisting of LOC_PARAM references so they > are handled in the primary and reference dedup phases > respectively. > > For BTF field iteration, BTF_KIND_LOCSEC needs 2 m_offs[] values > for the associated KIND_FUNC and KIND_LOC_PROTO type ids in > each LOCSEC entry. > > Add APIs to add location param, location prototypes and location > sections and btf_is_* tests, data accessors for each. > > For BTF distillation we add location info to split BTF. > > Signed-off-by: Alan Maguire <[email protected]> > ---
Acked-by: Eduard Zingerman <[email protected]> (Please see a few nits below) ... > diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c ... > @@ -4395,6 +4653,45 @@ static bool btf_compat_enum(struct btf_type *t1, > struct btf_type *t2) ... > +static long btf_hash_loc_param(struct btf_type *t) > +{ > + long h = btf_hash_common(t); > + __u32 *v = (__u32 *)btf_loc_param(t); > + int i, vlen = btf_vlen(t); > + > + for (i = 0; i <= vlen; i++, v++) > + h = hash_combine(h, *v); > + return h; > +} should v->flags be hashed as well? > +static bool btf_equal_loc_param(struct btf_type *t1, struct btf_type *t2) > +{ > + struct btf_loc_param *p1 = btf_loc_param(t1); > + struct btf_loc_param *p2 = btf_loc_param(t2); > + __u32 *v1 = (__u32 *)(p1 + 1); > + __u32 *v2 = (__u32 *)(p2 + 1); > + int i, vlen = btf_vlen(t1); > + llm is right, the p{1,2}->flags comparison is missing. > + if (!btf_equal_common(t1, t2)) > + return false; > + for (i = 0; i < vlen; i++, v1++, v2++) { > + if (*v1 != *v2) > + return false; > + } > + return true; > +} > + > /* > * Calculate type signature hash of STRUCT/UNION, ignoring referenced type > IDs, > * as referenced type IDs equivalence is established separately during type > @@ -4622,6 +4919,12 @@ static int btf_dedup_prep(struct btf_dedup *d) > case BTF_KIND_FUNC_PROTO: > h = btf_hash_fnproto(t); > break; > + case BTF_KIND_LOC_PARAM: > + h = btf_hash_loc_param(t); > + break; > + case BTF_KIND_LOC_PROTO: > + h = btf_hash_loc_proto(t); > + break; Maybe add LOCSEC as an empty case, same as for VAR and DATASEC above? Otherwise if someone ever tries to dedup a non-module BTF with a LOCSEC the operation would return -EINVAL. > default: > pr_debug("unknown kind %d for type [%d]\n", > btf_kind(t), type_id); > return -EINVAL; ... > @@ -5489,6 +5813,41 @@ static int btf_dedup_ref_type(struct btf_dedup *d, > __u32 type_id) > break; > } > > + case BTF_KIND_LOC_PROTO: { > + __u32 *p1, *p2; > + __u32 i, vlen; > + > + p1 = btf_loc_proto_params(t); > + vlen = btf_vlen(t); > + > + for (i = 0; i < vlen; i++, p1++) { > + ref_type_id = btf_dedup_ref_type(d, *p1); > + if (ref_type_id < 0) > + return ref_type_id; > + *p1 = ref_type_id; > + } > + > + h = btf_hash_loc_proto(t); > + for_each_dedup_cand(d, hash_entry, h) { > + cand_id = hash_entry->value; > + cand = btf_type_by_id(d->btf, cand_id); > + if (!btf_equal_common(t, cand)) > + continue; > + vlen = btf_vlen(cand); Nit: btf_equal_common() checks vlen for equivalence, so it appears that the above line is redundant. > + p1 = btf_loc_proto_params(t); > + p2 = btf_loc_proto_params(cand); > + if (vlen == 0) { > + new_id = cand_id; > + break; > + } Nit: It appears that special case for `vlen == 0` is not necessary, wouldn't memcmp(..., 0) be 0? > + if (memcmp(p1, p2, vlen * sizeof(__u32)) == 0) { > + new_id = cand_id; > + break; > + } > + } > + break; > + } > + > default: > return -EINVAL; > } ... > --- a/tools/lib/bpf/btf_iter.c > +++ b/tools/lib/bpf/btf_iter.c ... > @@ -94,6 +109,8 @@ int btf_field_iter_init(struct btf_field_iter *it, struct > btf_type *t, > case BTF_KIND_DECL_TAG: > case BTF_KIND_TYPE_TAG: > case BTF_KIND_DATASEC: > + case BTF_KIND_LOC_PARAM: > + case BTF_KIND_LOC_PROTO: > it->desc = (struct btf_field_desc) { > 1, {offsetof(struct btf_type, name_off)} > }; > @@ -127,6 +144,11 @@ int btf_field_iter_init(struct btf_field_iter *it, > struct btf_type *t, > 1, {offsetof(struct btf_param, name_off)} > }; > break; > + case BTF_KIND_LOCSEC: > + it->desc = (struct btf_field_desc) { > + 1, {offsetof(struct btf_type, name_off)} > + }; > + break; Nit: can this be grouped wit the _PARAM and _PROTO cases? ...
