{
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))
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);
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;
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 */