summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2026-03-04 23:56:50 +0300
committerAndrii Nakryiko <andrii@kernel.org>2026-03-06 01:57:58 +0300
commitbe872ccf370915b858ab693aa0707a2eff4bb1fd (patch)
tree6ef2d8fc92ad932a1f2129783c38459f771b64d4
parent4faa1893807cfc9363b19624f8666e07e7e42f59 (diff)
downloadlinux-be872ccf370915b858ab693aa0707a2eff4bb1fd.tar.xz
libbpf: Support appending split BTF in btf__add_btf()
btf__add_btf() currently rejects split BTF sources with -ENOTSUP. This prevents merging types from multiple kernel module BTFs that are all split against the same vmlinux base. Extend btf__add_btf() to handle split BTF sources by: - Replacing the blanket -ENOTSUP with a validation that src and dst share the same base BTF pointer when both are split, returning -EOPNOTSUPP on mismatch. - Computing src_start_id from the source's base to distinguish base type ID references (which must remain unchanged) from split type IDs (which must be remapped to new positions in the destination). - Using src_btf->nr_types instead of btf__type_cnt()-1 for the type count, which is correct for both split and non-split sources. - Skipping base string offsets (< start_str_off) during the string rewrite loop, mirroring the type ID skip pattern. Since src and dst share the same base BTF, base string offsets are already valid and need no remapping. For non-split sources the behavior is identical: src_start_id is 1, the type_id < 1 guard is never true (VOID is already skipped), and the remapping formula reduces to the original. start_str_off is 0 so no string offsets are skipped. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Reviewed-by: Alan Maguire <alan.maguire@oracle.com> Link: https://lore.kernel.org/bpf/c00216ed48cf7897078d9645679059d5ebf42738.1772657690.git.josef@toxicpanda.com
-rw-r--r--tools/lib/bpf/btf.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 83fe79ffcb8f..40becc964368 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -2004,12 +2004,18 @@ int btf__add_btf(struct btf *btf, const struct btf *src_btf)
{
struct btf_pipe p = { .src = src_btf, .dst = btf };
int data_sz, sz, cnt, i, err, old_strs_len;
+ __u32 src_start_id;
__u32 *off;
void *t;
- /* appending split BTF isn't supported yet */
- if (src_btf->base_btf)
- return libbpf_err(-ENOTSUP);
+ /*
+ * When appending split BTF, the destination must share the same base
+ * BTF so that base type ID references remain valid.
+ */
+ if (src_btf->base_btf && src_btf->base_btf != btf->base_btf)
+ return libbpf_err(-EOPNOTSUPP);
+
+ src_start_id = src_btf->base_btf ? btf__type_cnt(src_btf->base_btf) : 1;
/* deconstruct BTF, if necessary, and invalidate raw_data */
if (btf_ensure_modifiable(btf))
@@ -2021,7 +2027,7 @@ int btf__add_btf(struct btf *btf, const struct btf *src_btf)
old_strs_len = btf->hdr->str_len;
data_sz = src_btf->hdr->type_len;
- cnt = btf__type_cnt(src_btf) - 1;
+ cnt = src_btf->nr_types;
/* pre-allocate enough memory for new types */
t = btf_add_type_mem(btf, data_sz);
@@ -2060,6 +2066,9 @@ int btf__add_btf(struct btf *btf, const struct btf *src_btf)
if (err)
goto err_out;
while ((str_off = btf_field_iter_next(&it))) {
+ /* don't remap strings from shared base BTF */
+ if (*str_off < src_btf->start_str_off)
+ continue;
err = btf_rewrite_str(&p, str_off);
if (err)
goto err_out;
@@ -2074,11 +2083,11 @@ int btf__add_btf(struct btf *btf, const struct btf *src_btf)
if (!*type_id) /* nothing to do for VOID references */
continue;
- /* we haven't updated btf's type count yet, so
- * btf->start_id + btf->nr_types - 1 is the type ID offset we should
- * add to all newly added BTF types
- */
- *type_id += btf->start_id + btf->nr_types - 1;
+ /* don't remap types from shared base BTF */
+ if (*type_id < src_start_id)
+ continue;
+
+ *type_id += btf->start_id + btf->nr_types - src_start_id;
}
/* go to next type data and type offset index entry */