Andrii Nakryiko wrote: > Add APIs for appending new BTF types at the end of BTF object. > > Each BTF kind has either one API of the form btf__append_<kind>(). For types > that have variable amount of additional items (struct/union, enum, func_proto, > datasec), additional API is provided to emit each such item. E.g., for > emitting a struct, one would use the following sequence of API calls: > > btf__append_struct(...); > btf__append_field(...); > ... > btf__append_field(...); > > Each btf__append_field() will ensure that the last BTF type is of STRUCT or > UNION kind and will automatically increment that type's vlen field. > > All the strings are provided as C strings (const char *), not a string offset. > This significantly improves usability of BTF writer APIs. All such strings > will be automatically appended to string section or existing string will be > re-used, if such string was already added previously. > > Each API attempts to do all the reasonable validations, like enforcing > non-empty names for entities with required names, proper value bounds, various > bit offset restrictions, etc. > > Type ID validation is minimal because it's possible to emit a type that refers > to type that will be emitted later, so libbpf has no way to enforce such > cases. User must be careful to properly emit all the necessary types and > specify type IDs that will be valid in the finally generated BTF. > > Each of btf__append_<kind>() APIs return new type ID on success or negative > value on error. APIs like btf__append_field() that emit additional items > return zero on success and negative value on error. > > Signed-off-by: Andrii Nakryiko <andriin@xxxxxx> > --- [...] > + /* deconstruct BTF, if necessary, and invalidate raw_data */ > + if (btf_ensure_modifiable(btf)) > + return -ENOMEM; > + > + sz = sizeof(struct btf_type) + sizeof(int); > + t = btf_add_type_mem(btf, sz); > + if (!t) > + return -ENOMEM; > + > + /* if something goes wrong later, we might end up with extra an string, nit typo, 'with an extra string' > + * but that shouldn't be a problem, because BTF can't be constructed > + * completely anyway and will most probably be just discarded > + */ > + name_off = btf__add_str(btf, name); > + if (name_off < 0) > + return name_off; > + > + t->name_off = name_off; > + t->info = btf_type_info(BTF_KIND_INT, 0, 0); > + t->size = byte_sz; > + /* set INT info, we don't allow setting legacy bit offset/size */ > + *(__u32 *)(t + 1) = (encoding << 24) | (byte_sz * 8); > + > + err = btf_add_type_idx_entry(btf, btf->hdr->type_len); > + if (err) > + return err; > + > + btf->hdr->type_len += sz; > + btf->hdr->str_off += sz; > + btf->nr_types++; > + return btf->nr_types; > +} > +