Make btf_relocate() optionally return the string-offset map it builds while relocating a BTF relative to a distilled base. A subsequent split BTF object can use that map to rebase references to base strings. Also account for the accumulated base string offset when assigning a new BTF base. This is required when the base is itself split. Signed-off-by: Alan Maguire Assisted-by: OpenAI Codex (GPT-5.6) --- include/linux/btf.h | 5 +++-- kernel/bpf/btf.c | 4 ++-- tools/lib/bpf/btf.c | 2 +- tools/lib/bpf/btf_relocate.c | 7 ++++++- tools/lib/bpf/libbpf_internal.h | 3 ++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/linux/btf.h b/include/linux/btf.h index f731c7a5f14c..b66e20a18c54 100644 --- a/include/linux/btf.h +++ b/include/linux/btf.h @@ -608,7 +608,8 @@ struct btf_field_iter { #ifdef CONFIG_BPF_SYSCALL const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id); void btf_set_base_btf(struct btf *btf, const struct btf *base_btf); -int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **map_ids); +int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **map_ids, + __u32 **map_strs); int btf_field_iter_init(struct btf_field_iter *it, struct btf_type *t, enum btf_field_iter_kind iter_kind); __u32 *btf_field_iter_next(struct btf_field_iter *it); @@ -682,7 +683,7 @@ static inline void btf_set_base_btf(struct btf *btf, const struct btf *base_btf) } static inline int btf_relocate(void *log, struct btf *btf, const struct btf *base_btf, - __u32 **map_ids) + __u32 **map_ids, __u32 **map_strs) { return -EOPNOTSUPP; } diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c index 7aef2d662263..4242e00a3f7e 100644 --- a/kernel/bpf/btf.c +++ b/kernel/bpf/btf.c @@ -1945,7 +1945,7 @@ void btf_set_base_btf(struct btf *btf, const struct btf *base_btf) { btf->base_btf = (struct btf *)base_btf; btf->start_id = btf_nr_types(base_btf); - btf->start_str_off = base_btf->hdr.str_len; + btf->start_str_off = base_btf->start_str_off + base_btf->hdr.str_len; } static int env_resolve_init(struct btf_verifier_env *env) @@ -6984,7 +6984,7 @@ static struct btf *btf_parse_module(const char *module_name, const void *data, goto errout; if (base_btf != vmlinux_btf) { - err = btf_relocate(btf, vmlinux_btf, &btf->base_id_map); + err = btf_relocate(btf, vmlinux_btf, &btf->base_id_map, NULL); if (err) goto errout; btf_free(base_btf); diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 512b3962f75f..d2ff6f5d6d5b 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -6640,7 +6640,7 @@ void btf_set_base_btf(struct btf *btf, const struct btf *base_btf) int btf__relocate(struct btf *btf, const struct btf *base_btf) { - int err = btf_relocate(btf, base_btf, NULL); + int err = btf_relocate(btf, base_btf, NULL, NULL); if (!err) btf->owns_base = false; diff --git a/tools/lib/bpf/btf_relocate.c b/tools/lib/bpf/btf_relocate.c index df5fa4bd87d6..e55dd75f6c95 100644 --- a/tools/lib/bpf/btf_relocate.c +++ b/tools/lib/bpf/btf_relocate.c @@ -441,7 +441,8 @@ static int btf_relocate_rewrite_strs(struct btf_relocate *r, __u32 i) /* If successful, output of relocation is updated BTF with base BTF pointing * at base_btf, and type ids, strings adjusted accordingly. */ -int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **id_map) +int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **id_map, + __u32 **str_map) { unsigned int nr_types = btf__type_cnt(btf); const struct btf_header *dist_base_hdr; @@ -512,6 +513,10 @@ int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **id_map) *id_map = r.id_map; r.id_map = NULL; } + if (str_map) { + *str_map = r.str_map; + r.str_map = NULL; + } err_out: free(r.id_map); free(r.str_map); diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index 546f65b95cf4..4e45dfacb548 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -249,7 +249,8 @@ const char *btf_kind_str(const struct btf_type *t); const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id); const struct btf_header *btf_header(const struct btf *btf); void btf_set_base_btf(struct btf *btf, const struct btf *base_btf); -int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **id_map); +int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **id_map, + __u32 **str_map); bool btf_type_is_traceable_func(const struct btf *btf, const struct btf_type *t); static inline enum btf_func_linkage btf_func_linkage(const struct btf_type *t) -- 2.43.5