From: Alan Maguire <alan.maguire@oracle.com>
To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org
Cc: martin.lau@linux.dev, acme@kernel.org, ttreyer@meta.com,
yonghong.song@linux.dev, song@kernel.org,
john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me,
haoluo@google.com, jolsa@kernel.org, qmo@kernel.org,
ihor.solodrai@linux.dev, david.faust@oracle.com,
jose.marchesi@oracle.com, bpf@vger.kernel.org,
Alan Maguire <alan.maguire@oracle.com>
Subject: [RFC bpf-next 02/15] libbpf: Add support for BTF kinds LOC_PARAM, LOC_PROTO and LOCSEC
Date: Wed, 8 Oct 2025 18:34:58 +0100 [thread overview]
Message-ID: <20251008173512.731801-3-alan.maguire@oracle.com> (raw)
In-Reply-To: <20251008173512.731801-1-alan.maguire@oracle.com>
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.
Other considerations: because BTF_KIND_LOCSEC has multiple
member type ids we need to increase the number of member elements
to 2 in the field iterator.
Add APIs to add location param, location prototypes and location
sections.
For BTF relocation we add location info to split BTF.
One small thing noticed during testing; the test for adding_to_base
relies on the split BTF start id being > 1; however it is possible
to have empty distilled base BTF, so this test should be generalized
to check for the base BTF pointer (it will be non-NULL for split
BTF even if the base BTF is empty).
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
tools/lib/bpf/btf.c | 339 +++++++++++++++++++++++++++++++-
tools/lib/bpf/btf.h | 90 +++++++++
tools/lib/bpf/btf_dump.c | 10 +-
tools/lib/bpf/btf_iter.c | 23 +++
tools/lib/bpf/libbpf.map | 5 +
tools/lib/bpf/libbpf_internal.h | 4 +-
6 files changed, 464 insertions(+), 7 deletions(-)
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 18907f0fcf9f..0abd7831d6b4 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -327,6 +327,12 @@ static int btf_type_size(const struct btf_type *t)
return base_size + vlen * sizeof(struct btf_var_secinfo);
case BTF_KIND_DECL_TAG:
return base_size + sizeof(struct btf_decl_tag);
+ case BTF_KIND_LOC_PARAM:
+ return base_size + sizeof(__u64);
+ case BTF_KIND_LOC_PROTO:
+ return base_size + vlen * sizeof(__u32);
+ case BTF_KIND_LOCSEC:
+ return base_size + vlen * sizeof(struct btf_loc);
default:
pr_debug("Unsupported BTF_KIND:%u\n", btf_kind(t));
return -EINVAL;
@@ -343,12 +349,15 @@ static void btf_bswap_type_base(struct btf_type *t)
static int btf_bswap_type_rest(struct btf_type *t)
{
struct btf_var_secinfo *v;
+ struct btf_loc_param *lp;
struct btf_enum64 *e64;
struct btf_member *m;
struct btf_array *a;
struct btf_param *p;
struct btf_enum *e;
+ struct btf_loc *l;
__u16 vlen = btf_vlen(t);
+ __u32 *ids;
int i;
switch (btf_kind(t)) {
@@ -411,6 +420,30 @@ static int btf_bswap_type_rest(struct btf_type *t)
case BTF_KIND_DECL_TAG:
btf_decl_tag(t)->component_idx = bswap_32(btf_decl_tag(t)->component_idx);
return 0;
+ case BTF_KIND_LOC_PARAM:
+ lp = btf_loc_param(t);
+ if (btf_kflag(t)) {
+ lp->val_lo32 = bswap_32(lp->val_lo32);
+ lp->val_hi32 = bswap_32(lp->val_hi32);
+ } else {
+ lp->reg = bswap_16(lp->reg);
+ lp->flags = bswap_16(lp->flags);
+ lp->offset = bswap_32(lp->offset);
+ }
+ return 0;
+ case BTF_KIND_LOC_PROTO:
+ for (i = 0, ids = btf_loc_proto_params(t); i < vlen; i++, ids++)
+ *ids = bswap_32(*ids);
+ return 0;
+ case BTF_KIND_LOCSEC:
+ for (i = 0, l = btf_locsec_locs(t); i < vlen; i++, l++) {
+ l->name_off = bswap_32(l->name_off);
+ l->func_proto = bswap_32(l->func_proto);
+ l->loc_proto = bswap_32(l->loc_proto);
+ l->offset = bswap_32(l->offset);
+ }
+ return 0;
+
default:
pr_debug("Unsupported BTF_KIND:%u\n", btf_kind(t));
return -EINVAL;
@@ -588,6 +621,34 @@ static int btf_validate_type(const struct btf *btf, const struct btf_type *t, __
}
break;
}
+ case BTF_KIND_LOC_PARAM:
+ break;
+ case BTF_KIND_LOC_PROTO: {
+ __u32 *p = btf_loc_proto_params(t);
+
+ n = btf_vlen(t);
+ for (i = 0; i < n; i++, p++) {
+ err = btf_validate_id(btf, *p, id);
+ if (err)
+ return err;
+ }
+ break;
+ }
+ case BTF_KIND_LOCSEC: {
+ const struct btf_loc *l = btf_locsec_locs(t);
+
+ n = btf_vlen(t);
+ for (i = 0; i < n; i++, l++) {
+ err = btf_validate_str(btf, l->name_off, "loc name", id);
+ if (!err)
+ err = btf_validate_id(btf, l->func_proto, id);
+ if (!err)
+ btf_validate_id(btf, l->loc_proto, id);
+ if (err)
+ return err;
+ }
+ break;
+ }
default:
pr_warn("btf: type [%u]: unrecognized kind %u\n", id, kind);
return -EINVAL;
@@ -2993,6 +3054,183 @@ int btf__add_decl_attr(struct btf *btf, const char *value, int ref_type_id,
return btf_add_decl_tag(btf, value, ref_type_id, component_idx, 1);
}
+/*
+ * Append new BTF_KIND_LOC_PARAM with either
+ * - *value* set as __u64 value following btf_type, with info->kflag set to 1
+ * if *is_value* is true; or
+ * - *reg* number, *flags* and *offset* set if *is_value* is set to 0, and
+ * info->kflag set to 0.
+ * Returns:
+ * - >0, type ID of newly added BTF type;
+ * - <0, on error.
+ */
+int btf__add_loc_param(struct btf *btf, __s32 size, bool is_value, __u64 value,
+ __u16 reg, __u16 flags, __s32 offset)
+{
+ struct btf_loc_param *p;
+ struct btf_type *t;
+ int sz;
+
+ if (btf_ensure_modifiable(btf))
+ return libbpf_err(-ENOMEM);
+
+ sz = sizeof(struct btf_type) + sizeof(__u64);
+ t = btf_add_type_mem(btf, sz);
+ if (!t)
+ return libbpf_err(-ENOMEM);
+
+ t->name_off = 0;
+ t->info = btf_type_info(BTF_KIND_LOC_PARAM, 0, is_value);
+ t->size = size;
+
+ p = btf_loc_param(t);
+
+ if (is_value) {
+ p->val_lo32 = value & 0xffffffff;
+ p->val_hi32 = value >> 32;
+ } else {
+ p->reg = reg;
+ p->flags = flags;
+ p->offset = offset;
+ }
+ return btf_commit_type(btf, sz);
+}
+
+/*
+ * Append new BTF_KIND_LOC_PROTO
+ *
+ * The prototype is then populated with 0 or more BTF_KIND_LOC_PARAMs via
+ * btf__add_loc_proto_param(); similar to how btf__add_func_param() adds
+ * parameters to a FUNC_PROTO.
+ *
+ * Returns:
+ * - >0, type ID of newly added BTF type;
+ * - <0, on error.
+ */
+int btf__add_loc_proto(struct btf *btf)
+{
+ struct btf_type *t;
+
+ if (btf_ensure_modifiable(btf))
+ return libbpf_err(-ENOMEM);
+
+ t = btf_add_type_mem(btf, sizeof(struct btf_type));
+ if (!t)
+ return libbpf_err(-ENOMEM);
+
+ t->name_off = 0;
+ t->info = btf_type_info(BTF_KIND_LOC_PROTO, 0, 0);
+ t->size = 0;
+
+ return btf_commit_type(btf, sizeof(struct btf_type));
+}
+
+int btf__add_loc_proto_param(struct btf *btf, __u32 id)
+{
+ struct btf_type *t;
+ __u32 *p;
+ int sz;
+
+ if (validate_type_id(id))
+ return libbpf_err(-EINVAL);
+
+ /* last type should be BTF_KIND_LOC_PROTO */
+ if (btf->nr_types == 0)
+ return libbpf_err(-EINVAL);
+ t = btf_last_type(btf);
+ if (!btf_is_loc_proto(t))
+ return libbpf_err(-EINVAL);
+
+ /* decompose and invalidate raw data */
+ if (btf_ensure_modifiable(btf))
+ return libbpf_err(-ENOMEM);
+
+ sz = sizeof(__u32);
+ p = btf_add_type_mem(btf, sz);
+ if (!p)
+ return libbpf_err(-ENOMEM);
+ *p = id;
+
+ /* update parent type's vlen */
+ t = btf_last_type(btf);
+ btf_type_inc_vlen(t);
+
+ btf->hdr->type_len += sz;
+ btf->hdr->str_off += sz;
+ return 0;
+}
+
+int btf__add_locsec(struct btf *btf, const char *name)
+{
+ struct btf_type *t;
+ int name_off = 0;
+
+ if (btf_ensure_modifiable(btf))
+ return libbpf_err(-ENOMEM);
+
+ if (name && name[0]) {
+ name_off = btf__add_str(btf, name);
+ if (name_off < 0)
+ return name_off;
+ }
+ t = btf_add_type_mem(btf, sizeof(struct btf_type));
+ if (!t)
+ return libbpf_err(-ENOMEM);
+
+ t->name_off = name_off;
+ t->info = btf_type_info(BTF_KIND_LOCSEC, 0, 0);
+ t->size = 0;
+
+ return btf_commit_type(btf, sizeof(struct btf_type));
+}
+
+int btf__add_locsec_loc(struct btf *btf, const char *name, __u32 func_proto, __u32 loc_proto,
+ __u32 offset)
+{
+ struct btf_type *t;
+ struct btf_loc *l;
+ int name_off, sz;
+
+ if (!name || !name[0])
+ return libbpf_err(-EINVAL);
+
+ if (validate_type_id(func_proto) || validate_type_id(loc_proto))
+ return libbpf_err(-EINVAL);
+
+ /* last type should be BTF_KIND_LOCSEC */
+ if (btf->nr_types == 0)
+ return libbpf_err(-EINVAL);
+ t = btf_last_type(btf);
+ if (!btf_is_locsec(t))
+ return libbpf_err(-EINVAL);
+
+ /* decompose and invalidate raw data */
+ if (btf_ensure_modifiable(btf))
+ return libbpf_err(-ENOMEM);
+
+ name_off = btf__add_str(btf, name);
+ if (name_off < 0)
+ return name_off;
+
+ sz = sizeof(*l);
+ l = btf_add_type_mem(btf, sz);
+ if (!l)
+ return libbpf_err(-ENOMEM);
+
+ l->name_off = name_off;
+ l->func_proto = func_proto;
+ l->loc_proto = loc_proto;
+ l->offset = offset;
+
+ /* update parent type's vlen */
+ t = btf_last_type(btf);
+ btf_type_inc_vlen(t);
+
+ btf->hdr->type_len += sz;
+ btf->hdr->str_off += sz;
+ return 0;
+}
+
struct btf_ext_sec_info_param {
__u32 off;
__u32 len;
@@ -3760,8 +3998,8 @@ static struct btf_dedup *btf_dedup_new(struct btf *btf, const struct btf_dedup_o
for (i = 1; i < type_cnt; i++) {
struct btf_type *t = btf_type_by_id(d->btf, i);
- /* VAR and DATASEC are never deduped and are self-canonical */
- if (btf_is_var(t) || btf_is_datasec(t))
+ /* VAR DATASEC and LOCSEC are never deduped and are self-canonical */
+ if (btf_is_var(t) || btf_is_datasec(t) || btf_is_locsec(t))
d->map[i] = i;
else
d->map[i] = BTF_UNPROCESSED_ID;
@@ -4001,6 +4239,26 @@ static bool btf_equal_enum(struct btf_type *t1, struct btf_type *t2)
return btf_equal_enum64_members(t1, t2);
}
+static long btf_hash_loc_proto(struct btf_type *t)
+{
+ __u32 *p = btf_loc_proto_params(t);
+ long h = btf_hash_common(t);
+ int i, vlen = btf_vlen(t);
+
+ for (i = 0; i < vlen; i++, p++)
+ h = hash_combine(h, *p);
+ return h;
+}
+
+static bool btf_equal_loc_param(struct btf_type *t1, struct btf_type *t2)
+{
+ if (!btf_equal_common(t1, t2))
+ return false;
+ return btf_kflag(t1) == btf_kflag(t2) &&
+ t1->size == t2->size &&
+ btf_loc_param_value(t1) == btf_loc_param_value(t2);
+}
+
static inline bool btf_is_enum_fwd(struct btf_type *t)
{
return btf_is_any_enum(t) && btf_vlen(t) == 0;
@@ -4214,7 +4472,8 @@ static int btf_dedup_prep(struct btf_dedup *d)
switch (btf_kind(t)) {
case BTF_KIND_VAR:
case BTF_KIND_DATASEC:
- /* VAR and DATASEC are never hash/deduplicated */
+ case BTF_KIND_LOCSEC:
+ /* VAR DATASEC and LOCSEC are never hash/deduplicated */
continue;
case BTF_KIND_CONST:
case BTF_KIND_VOLATILE:
@@ -4245,6 +4504,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_common(t);
+ break;
+ case BTF_KIND_LOC_PROTO:
+ h = btf_hash_loc_proto(t);
+ break;
default:
pr_debug("unknown kind %d for type [%d]\n", btf_kind(t), type_id);
return -EINVAL;
@@ -4287,6 +4552,8 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
case BTF_KIND_DATASEC:
case BTF_KIND_DECL_TAG:
case BTF_KIND_TYPE_TAG:
+ case BTF_KIND_LOC_PROTO:
+ case BTF_KIND_LOCSEC:
return 0;
case BTF_KIND_INT:
@@ -4336,6 +4603,18 @@ static int btf_dedup_prim_type(struct btf_dedup *d, __u32 type_id)
}
break;
+ case BTF_KIND_LOC_PARAM:
+ h = btf_hash_common(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_loc_param(t, cand)) {
+ new_id = cand_id;
+ break;
+ }
+ }
+ break;
+
default:
return -EINVAL;
}
@@ -4749,6 +5028,13 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
return 1;
}
+ case BTF_KIND_LOC_PARAM:
+ return btf_equal_loc_param(cand_type, canon_type);
+
+ case BTF_KIND_LOC_PROTO:
+ case BTF_KIND_LOCSEC:
+ return 0;
+
default:
return -EINVAL;
}
@@ -5075,6 +5361,45 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
break;
}
+ case BTF_KIND_LOC_PROTO: {
+ __u32 *p1, *p2;
+ __u16 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);
+ p1 = btf_loc_proto_params(t);
+ p2 = btf_loc_proto_params(cand);
+ if (vlen == 0) {
+ new_id = cand_id;
+ break;
+ }
+ for (i = 0; i < vlen; i++, p1++, p2++) {
+ if (*p1 != *p2)
+ break;
+ new_id = cand_id;
+ break;
+ }
+ if (new_id == cand_id)
+ break;
+ }
+ break;
+ }
+
default:
return -EINVAL;
}
@@ -5555,6 +5880,8 @@ static int btf_add_distilled_type_ids(struct btf_distill *dist, __u32 i)
case BTF_KIND_VOLATILE:
case BTF_KIND_FUNC_PROTO:
case BTF_KIND_TYPE_TAG:
+ case BTF_KIND_LOC_PARAM:
+ case BTF_KIND_LOC_PROTO:
dist->id_map[*id] = *id;
break;
default:
@@ -5580,12 +5907,11 @@ static int btf_add_distilled_type_ids(struct btf_distill *dist, __u32 i)
static int btf_add_distilled_types(struct btf_distill *dist)
{
- bool adding_to_base = dist->pipe.dst->start_id == 1;
+ bool adding_to_base = dist->pipe.dst->base_btf == NULL;
int id = btf__type_cnt(dist->pipe.dst);
struct btf_type *t;
int i, err = 0;
-
/* Add types for each of the required references to either distilled
* base or split BTF, depending on type characteristics.
*/
@@ -5650,6 +5976,9 @@ static int btf_add_distilled_types(struct btf_distill *dist)
case BTF_KIND_VOLATILE:
case BTF_KIND_FUNC_PROTO:
case BTF_KIND_TYPE_TAG:
+ case BTF_KIND_LOC_PARAM:
+ case BTF_KIND_LOC_PROTO:
+ case BTF_KIND_LOCSEC:
/* All other types are added to split BTF. */
if (adding_to_base)
continue;
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index ccfd905f03df..0f55518a2be0 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -247,6 +247,18 @@ LIBBPF_API int btf__add_decl_tag(struct btf *btf, const char *value, int ref_typ
LIBBPF_API int btf__add_decl_attr(struct btf *btf, const char *value, int ref_type_id,
int component_idx);
+LIBBPF_API int btf__add_loc_param(struct btf *btf, __s32 size, bool is_value, __u64 value,
+ __u16 reg, __u16 flags, __s32 offset);
+
+LIBBPF_API int btf__add_loc_proto(struct btf *btf);
+
+LIBBPF_API int btf__add_loc_proto_param(struct btf *btf, __u32 id);
+
+LIBBPF_API int btf__add_locsec(struct btf *btf, const char *name);
+
+LIBBPF_API int btf__add_locsec_loc(struct btf *btf, const char *name, __u32 func_proto,
+ __u32 loc_proto, __u32 offset);
+
struct btf_dedup_opts {
size_t sz;
/* optional .BTF.ext info to dedup along the main BTF info */
@@ -360,6 +372,42 @@ btf_dump__dump_type_data(struct btf_dump *d, __u32 id,
#define BTF_KIND_TYPE_TAG 18 /* Type Tag */
#define BTF_KIND_ENUM64 19 /* Enum for up-to 64bit values */
+#ifndef BTF_KIND_LOC_UAPI_DEFINED
+#define BTF_KIND_LOC_LIBBPF_DEFINED
+#define BTF_KIND_LOC_PARAM 20
+#define BTF_KIND_LOC_PROTO 21
+#define BTF_KIND_LOCSEC 22
+
+#define BTF_TYPE_LOC_PARAM_SIZE(t) ((__s32)((t)->size))
+#define BTF_LOC_FLAG_DEREF 0x1
+#define BTF_LOC_FLAG_CONTINUE 0x2
+
+struct btf_loc_param {
+ union {
+ struct {
+ __u16 reg; /* register number */
+ __u16 flags; /* register dereference */
+ __s32 offset; /* offset from register-stored address */
+ };
+ struct {
+ __u32 val_lo32; /* lo 32 bits of 64-bit value */
+ __u32 val_hi32; /* hi 32 bits of 64-bit value */
+ };
+ };
+};
+
+struct btf_loc {
+ __u32 name_off;
+ __u32 func_proto;
+ __u32 loc_proto;
+ __u32 offset;
+};
+
+#else
+struct btf_loc_param;
+struct btf_loc;
+#endif
+
static inline __u16 btf_kind(const struct btf_type *t)
{
return BTF_INFO_KIND(t->info);
@@ -497,6 +545,21 @@ static inline bool btf_is_any_enum(const struct btf_type *t)
return btf_is_enum(t) || btf_is_enum64(t);
}
+static inline bool btf_is_loc_param(const struct btf_type *t)
+{
+ return btf_kind(t) == BTF_KIND_LOC_PARAM;
+}
+
+static inline bool btf_is_loc_proto(const struct btf_type *t)
+{
+ return btf_kind(t) == BTF_KIND_LOC_PROTO;
+}
+
+static inline bool btf_is_locsec(const struct btf_type *t)
+{
+ return btf_kind(t) == BTF_KIND_LOCSEC;
+}
+
static inline bool btf_kind_core_compat(const struct btf_type *t1,
const struct btf_type *t2)
{
@@ -611,6 +674,33 @@ static inline struct btf_decl_tag *btf_decl_tag(const struct btf_type *t)
return (struct btf_decl_tag *)(t + 1);
}
+static inline struct btf_loc_param *btf_loc_param(const struct btf_type *t)
+{
+ return (struct btf_loc_param *)(t + 1);
+}
+
+static inline __s32 btf_loc_param_size(const struct btf_type *t)
+{
+ return (__s32)t->size;
+}
+
+static inline __u64 btf_loc_param_value(const struct btf_type *t)
+{
+ struct btf_loc_param *p = btf_loc_param(t);
+
+ return p->val_lo32 | (((__u64)(p->val_hi32)) << 32);
+}
+
+static inline __u32 *btf_loc_proto_params(const struct btf_type *t)
+{
+ return (__u32 *)(t + 1);
+}
+
+static inline struct btf_loc *btf_locsec_locs(const struct btf_type *t)
+{
+ return (struct btf_loc *)(t + 1);
+}
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index 6388392f49a0..95bdda2f4a2d 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -328,6 +328,9 @@ static int btf_dump_mark_referenced(struct btf_dump *d)
case BTF_KIND_ENUM64:
case BTF_KIND_FWD:
case BTF_KIND_FLOAT:
+ case BTF_KIND_LOC_PARAM:
+ case BTF_KIND_LOC_PROTO:
+ case BTF_KIND_LOCSEC:
break;
case BTF_KIND_VOLATILE:
@@ -339,7 +342,6 @@ static int btf_dump_mark_referenced(struct btf_dump *d)
case BTF_KIND_VAR:
case BTF_KIND_DECL_TAG:
case BTF_KIND_TYPE_TAG:
- d->type_states[t->type].referenced = 1;
break;
case BTF_KIND_ARRAY: {
@@ -609,6 +611,9 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr)
case BTF_KIND_VAR:
case BTF_KIND_DATASEC:
case BTF_KIND_DECL_TAG:
+ case BTF_KIND_LOC_PARAM:
+ case BTF_KIND_LOC_PROTO:
+ case BTF_KIND_LOCSEC:
d->type_states[id].order_state = ORDERED;
return 0;
@@ -2516,6 +2521,9 @@ static int btf_dump_dump_type_data(struct btf_dump *d,
case BTF_KIND_FUNC:
case BTF_KIND_FUNC_PROTO:
case BTF_KIND_DECL_TAG:
+ case BTF_KIND_LOC_PARAM:
+ case BTF_KIND_LOC_PROTO:
+ case BTF_KIND_LOCSEC:
err = btf_dump_unsupported_data(d, t, id);
break;
case BTF_KIND_INT:
diff --git a/tools/lib/bpf/btf_iter.c b/tools/lib/bpf/btf_iter.c
index 9a6c822c2294..e9a865d84d35 100644
--- a/tools/lib/bpf/btf_iter.c
+++ b/tools/lib/bpf/btf_iter.c
@@ -29,6 +29,7 @@ int btf_field_iter_init(struct btf_field_iter *it, struct btf_type *t,
case BTF_KIND_FLOAT:
case BTF_KIND_ENUM:
case BTF_KIND_ENUM64:
+ case BTF_KIND_LOC_PARAM:
it->desc = (struct btf_field_desc) {};
break;
case BTF_KIND_FWD:
@@ -71,6 +72,19 @@ int btf_field_iter_init(struct btf_field_iter *it, struct btf_type *t,
1, {offsetof(struct btf_var_secinfo, type)}
};
break;
+ case BTF_KIND_LOC_PROTO:
+ it->desc = (struct btf_field_desc) {
+ 0, {},
+ sizeof(__u32),
+ 1, {0}};
+ break;
+ case BTF_KIND_LOCSEC:
+ it->desc = (struct btf_field_desc) {
+ 0, {},
+ sizeof(struct btf_loc),
+ 2, {offsetof(struct btf_loc, func_proto),
+ offsetof(struct btf_loc, loc_proto)}};
+ break;
default:
return -EINVAL;
}
@@ -94,6 +108,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 +143,13 @@ 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)},
+ sizeof(struct btf_loc),
+ 1, {offsetof(struct btf_loc, name_off)}
+ };
+ break;
default:
return -EINVAL;
}
diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
index 8ed8749907d4..82a0d2ff1176 100644
--- a/tools/lib/bpf/libbpf.map
+++ b/tools/lib/bpf/libbpf.map
@@ -451,4 +451,9 @@ LIBBPF_1.7.0 {
global:
bpf_map__set_exclusive_program;
bpf_map__exclusive_program;
+ btf__add_loc_param;
+ btf__add_loc_proto;
+ btf__add_loc_proto_param;
+ btf__add_locsec;
+ btf__add_locsec_loc;
} LIBBPF_1.6.0;
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
index 35b2527bedec..2a05518265e9 100644
--- a/tools/lib/bpf/libbpf_internal.h
+++ b/tools/lib/bpf/libbpf_internal.h
@@ -562,7 +562,9 @@ struct btf_field_desc {
/* member struct size, or zero, if no members */
int m_sz;
/* repeated per-member offsets */
- int m_off_cnt, m_offs[1];
+ int m_off_cnt, m_offs[2];
+ /* singular entity size after btf_type, if any */
+ int s_sz;
};
struct btf_field_iter {
--
2.39.3
next prev parent reply other threads:[~2025-10-08 17:35 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-08 17:34 [RFC bpf-next 00/15] support inline tracing with BTF Alan Maguire
2025-10-08 17:34 ` [RFC bpf-next 01/15] bpf: Extend UAPI to support location information Alan Maguire
2025-10-16 18:36 ` Andrii Nakryiko
2025-10-17 8:43 ` Alan Maguire
2025-10-20 20:57 ` Andrii Nakryiko
2025-10-23 8:17 ` Alan Maguire
2025-11-05 0:43 ` Andrii Nakryiko
2025-10-23 0:56 ` Eduard Zingerman
2025-10-23 8:35 ` Alan Maguire
2025-10-08 17:34 ` Alan Maguire [this message]
2025-10-23 0:57 ` [RFC bpf-next 02/15] libbpf: Add support for BTF kinds LOC_PARAM, LOC_PROTO and LOCSEC Eduard Zingerman
2025-10-23 19:18 ` Eduard Zingerman
2025-10-23 19:59 ` Eduard Zingerman
2025-10-08 17:34 ` [RFC bpf-next 03/15] libbpf: Add option to retrieve map from old->new ids from btf__dedup() Alan Maguire
2025-10-16 18:39 ` Andrii Nakryiko
2025-10-17 8:56 ` Alan Maguire
2025-10-20 21:03 ` Andrii Nakryiko
2025-10-23 8:25 ` Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 04/15] libbpf: Fix parsing of multi-split BTF Alan Maguire
2025-10-16 18:36 ` Andrii Nakryiko
2025-10-17 13:47 ` Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 05/15] bpftool: Add ability to dump LOC_PARAM, LOC_PROTO and LOCSEC Alan Maguire
2025-10-23 0:57 ` Eduard Zingerman
2025-10-23 8:38 ` Alan Maguire
2025-10-23 8:50 ` Eduard Zingerman
2025-10-08 17:35 ` [RFC bpf-next 06/15] bpftool: Handle multi-split BTF by supporting multiple base BTFs Alan Maguire
2025-10-16 18:36 ` Andrii Nakryiko
2025-10-17 13:47 ` Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 07/15] selftests/bpf: Test helper support for BTF_KIND_LOC[_PARAM|_PROTO|SEC] Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 08/15] selftests/bpf: Add LOC_PARAM, LOC_PROTO, LOCSEC to field iter tests Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 09/15] selftests/bpf: Add LOC_PARAM, LOC_PROTO, LOCSEC to dedup split tests Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 10/15] selftests/bpf: BTF distill tests to ensure LOC[_PARAM|_PROTO] add to split BTF Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 11/15] kbuild: Add support for extra BTF Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 12/15] kbuild, module, bpf: Support CONFIG_DEBUG_INFO_BTF_EXTRA=m Alan Maguire
2025-10-16 18:37 ` Andrii Nakryiko
2025-10-17 13:54 ` Alan Maguire
2025-10-20 21:05 ` Andrii Nakryiko
2025-10-23 0:58 ` Eduard Zingerman
2025-10-23 12:00 ` Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 13/15] libbpf: add API to load extra BTF Alan Maguire
2025-10-16 18:37 ` Andrii Nakryiko
2025-10-17 13:55 ` Alan Maguire
2025-10-08 17:35 ` [RFC bpf-next 14/15] libbpf: add support for BTF location attachment Alan Maguire
2025-10-16 18:36 ` Andrii Nakryiko
2025-10-17 14:02 ` Alan Maguire
2025-10-20 21:07 ` Andrii Nakryiko
2025-10-08 17:35 ` [RFC bpf-next 15/15] selftests/bpf: Add test tracing inline site using SEC("kloc") Alan Maguire
2025-10-12 23:45 ` [RFC bpf-next 00/15] support inline tracing with BTF Alexei Starovoitov
2025-10-13 7:38 ` Alan Maguire
2025-10-14 0:12 ` Alexei Starovoitov
2025-10-14 9:58 ` Alan Maguire
2025-10-16 18:36 ` Andrii Nakryiko
2025-10-23 14:37 ` Alan Maguire
2025-10-23 16:16 ` Andrii Nakryiko
2025-10-24 11:53 ` Alan Maguire
2025-10-14 11:52 ` Jiri Olsa
2025-10-14 14:55 ` Alan Maguire
2025-10-14 23:04 ` Masami Hiramatsu
2025-10-15 14:17 ` Jiri Olsa
2025-10-15 15:19 ` Alan Maguire
2025-10-15 18:35 ` Jiri Olsa
2025-10-23 22:32 ` Eduard Zingerman
2025-10-24 12:54 ` Alan Maguire
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251008173512.731801-3-alan.maguire@oracle.com \
--to=alan.maguire@oracle.com \
--cc=acme@kernel.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=david.faust@oracle.com \
--cc=haoluo@google.com \
--cc=ihor.solodrai@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=jose.marchesi@oracle.com \
--cc=kpsingh@kernel.org \
--cc=martin.lau@linux.dev \
--cc=qmo@kernel.org \
--cc=sdf@fomichev.me \
--cc=song@kernel.org \
--cc=ttreyer@meta.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).