2022-01-12 09:27 UTC-0500 ~ Mauricio Vásquez <mauricio@xxxxxxxxxx> > This commit implements the logic to record the relocation information > for the different kind of relocations. > > btfgen_record_field_relo() uses the target specification to save all the > types that are involved in a field-based CO-RE relocation. In this case > types resolved and added recursively (using btfgen_put_type()). > Only the struct and union members and their types) involved in the > relocation are added to optimize the size of the generated BTF file. > > On the other hand, btfgen_record_type_relo() saves the types involved in > a type-based CO-RE relocation. In this case all the members for the > struct and union types are added. This is not strictly required since > libbpf doesn't use them while performing this kind of relocation, > however that logic could change on the future. Additionally, we expect > that the number of this kind of relocations in an BPF object to be very > low, hence the impact on the size of the generated BTF should be > negligible. > > Finally, btfgen_record_enumval_relo() saves the whole enum type for > enum-based relocations. > > Signed-off-by: Mauricio Vásquez <mauricio@xxxxxxxxxx> > Signed-off-by: Rafael David Tinoco <rafael.tinoco@xxxxxxxxxxx> > Signed-off-by: Lorenzo Fontana <lorenzo.fontana@xxxxxxxxxx> > Signed-off-by: Leonardo Di Donato <leonardo.didonato@xxxxxxxxxx> > --- > tools/bpf/bpftool/gen.c | 260 +++++++++++++++++++++++++++++++++++++++- > 1 file changed, 257 insertions(+), 3 deletions(-) > > diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c > index cef0ea99d4d9..8c13dde0b74d 100644 > --- a/tools/bpf/bpftool/gen.c > +++ b/tools/bpf/bpftool/gen.c > @@ -1207,19 +1228,252 @@ btfgen_new_info(const char *targ_btf_path) > +static struct btfgen_type * > +_btfgen_put_type(struct btf *btf, struct btfgen_info *info, struct btf_type *btf_type, > + unsigned int id, bool all_members) > +{ > + struct btfgen_type *btfgen_type, *tmp; > + struct btf_array *array; > + unsigned int child_id; > + struct btf_member *m; > + int err, i, n; > + > + /* check if we already have this type */ > + if (hashmap__find(info->types, uint_as_hash_key(id), (void **) &btfgen_type)) { > + if (!all_members || btfgen_type->all_members) > + return btfgen_type; > + } else { > + btfgen_type = calloc(1, sizeof(*btfgen_type)); > + if (!btfgen_type) > + return NULL; > + > + btfgen_type->type = btf_type; > + btfgen_type->id = id; > + > + /* append this type to the types list before anything else */ > + err = hashmap__add(info->types, uint_as_hash_key(btfgen_type->id), btfgen_type); > + if (err) { > + free(btfgen_type); > + return NULL; > + } > + } > + > + /* avoid infinite recursion and yet be able to add all > + * fields/members for types also managed by this function > + */ > + btfgen_type->all_members = all_members; > + > + Nit: double blank line. > + /* recursively add other types needed by it */ > + switch (btf_kind(btfgen_type->type)) { > + case BTF_KIND_UNKN: > + case BTF_KIND_INT: > static int btfgen_record_field_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec) > { > - return -EOPNOTSUPP; > + struct btf *btf = (struct btf *) info->src_btf; > + struct btfgen_type *btfgen_type; > + struct btf_member *btf_member; > + struct btf_type *btf_type; > + struct btf_array *array; > + unsigned int id; > + int idx, err; > + > + btf_type = (struct btf_type *) btf__type_by_id(btf, targ_spec->root_type_id); > + > + /* create btfgen_type for root type */ > + btfgen_type = btfgen_put_type(btf, info, btf_type, targ_spec->root_type_id); > + if (!btfgen_type) > + return -errno; > + > + /* add types for complex types (arrays, unions, structures) */ > + for (int i = 1; i < targ_spec->raw_len; i++) { > + /* skip typedefs and mods */ > + while (btf_is_mod(btf_type) || btf_is_typedef(btf_type)) { > + id = btf_type->type; > + btfgen_type = btfgen_get_type(info, id); > + if (!btfgen_type) > + return -ENOENT; > + btf_type = (struct btf_type *) btf__type_by_id(btf, id); > + } > + > + switch (btf_kind(btf_type)) { > + case BTF_KIND_STRUCT: > + case BTF_KIND_UNION: > + idx = targ_spec->raw_spec[i]; > + btf_member = btf_members(btf_type) + idx; > + btf_type = (struct btf_type *) btf__type_by_id(btf, btf_member->type); > + > + /* add member to relocation type */ > + err = btfgen_add_member(btfgen_type, btf_member, idx); > + if (err) > + return err; > + /* put btfgen type */ > + btfgen_type = btfgen_put_type(btf, info, btf_type, btf_member->type); > + if (!btfgen_type) > + return -errno; > + break; > + case BTF_KIND_ARRAY: > + array = btf_array(btf_type); > + btfgen_type = btfgen_get_type(info, array->type); > + if (!btfgen_type) > + return -ENOENT; > + btf_type = (struct btf_type *) btf__type_by_id(btf, array->type); > + break; > + default: > + p_err("spec type wasn't handled"); This message might benefit from a bit more context (step, type number?). > + return -EINVAL; > + } > + } > + > + return 0; > } > > static int btfgen_record_type_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec) > { > - return -EOPNOTSUPP; > + struct btf *btf = (struct btf *) info->src_btf; > + struct btfgen_type *btfgen_type; > + struct btf_type *btf_type; > + > + btf_type = (struct btf_type *) btf__type_by_id(btf, targ_spec->root_type_id); > + > + btfgen_type = btfgen_put_type_all(btf, info, btf_type, targ_spec->root_type_id); > + return btfgen_type ? 0 : -errno; Nit: double space in "? 0". > } > > static int btfgen_record_enumval_relo(struct btfgen_info *info, struct bpf_core_spec *targ_spec) > { > - return -EOPNOTSUPP; > + struct btf *btf = (struct btf *) info->src_btf; > + struct btfgen_type *btfgen_type; > + struct btf_type *btf_type; > + > + btf_type = (struct btf_type *) btf__type_by_id(btf, targ_spec->root_type_id); > + > + btfgen_type = btfgen_put_type_all(btf, info, btf_type, targ_spec->root_type_id); > + return btfgen_type ? 0 : -errno; Nit: double space in "? 0". > } > > static int btfgen_record_reloc(struct btfgen_info *info, struct bpf_core_spec *res)