Thread (58 messages) flat view 58 messages, 7 authors, 9d ago

Re: [PATCH v2 bpf-next 02/18] libbpf: Add support for BTF kinds LOC[_PARAM|_PROTO|SEC]

From: Eduard Zingerman <eddyz87@gmail.com>
Date: 2026-09-09 22:27:02
Also in: bpf

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 <redacted>
---
Acked-by: Eduard Zingerman <eddyz87@gmail.com>

(Please see a few nits below)

...
quoted hunk ↗ jump to hunk
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
...
quoted hunk ↗ jump to hunk
@@ -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.
quoted hunk ↗ jump to hunk
+	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;
...
quoted hunk ↗ jump to hunk
@@ -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;
 	}
...
quoted hunk ↗ jump to hunk
--- a/tools/lib/bpf/btf_iter.c
+++ b/tools/lib/bpf/btf_iter.c
...
quoted hunk ↗ jump to hunk
@@ -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?

...
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help