On 22/01/2025 02:53, Ihor Solodrai wrote: > Add the following functions to libbpf API: > * btf__add_type_attr() > * btf__add_decl_attr() > > These functions allow to add to BTF the type tags and decl tags with > info->kflag set to 1. The kflag indicates that the tag directly > encodes an __attribute__ and not a normal tag. > > See Documentation/bpf/btf.rst changes for details on the semantics. > > Suggested-by: Andrii Nakryiko <andrii@xxxxxxxxxx> > Signed-off-by: Ihor Solodrai <ihor.solodrai@xxxxx> need to sync include/uapi/linux/btf.h with tools/include/uapi/linux/btf.h, but other than that Reviewed-by: Alan Maguire <alan.maguire@xxxxxxxxxx> > --- > Documentation/bpf/btf.rst | 27 +++++++++-- > tools/include/uapi/linux/btf.h | 3 +- same change needed to include/uapi/linux/btf.h too, right? > tools/lib/bpf/btf.c | 87 +++++++++++++++++++++++++--------- > tools/lib/bpf/btf.h | 3 ++ > tools/lib/bpf/libbpf.map | 2 + > 5 files changed, 93 insertions(+), 29 deletions(-) > > diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst > index 2478cef758f8..615ded7b2442 100644 > --- a/Documentation/bpf/btf.rst > +++ b/Documentation/bpf/btf.rst > @@ -102,8 +102,9 @@ Each type contains the following common data:: > * bits 24-28: kind (e.g. int, ptr, array...etc) > * bits 29-30: unused > * bit 31: kind_flag, currently used by > - * struct, union, fwd, enum and enum64. > - */ > + * struct, union, enum, fwd, enum64, > + * DECL_TAG and TYPE_TAG > + */ > __u32 info; > /* "size" is used by INT, ENUM, STRUCT, UNION and ENUM64. > * "size" tells the size of the type it is describing. > @@ -478,7 +479,7 @@ No additional type data follow ``btf_type``. > > ``struct btf_type`` encoding requirement: > * ``name_off``: offset to a non-empty string > - * ``info.kind_flag``: 0 > + * ``info.kind_flag``: 0 or 1 > * ``info.kind``: BTF_KIND_DECL_TAG > * ``info.vlen``: 0 > * ``type``: ``struct``, ``union``, ``func``, ``var`` or ``typedef`` > @@ -489,7 +490,6 @@ No additional type data follow ``btf_type``. > __u32 component_idx; > }; > > -The ``name_off`` encodes btf_decl_tag attribute string. > The ``type`` should be ``struct``, ``union``, ``func``, ``var`` or ``typedef``. > For ``var`` or ``typedef`` type, ``btf_decl_tag.component_idx`` must be ``-1``. > For the other three types, if the btf_decl_tag attribute is > @@ -499,12 +499,21 @@ the attribute is applied to a ``struct``/``union`` member or > a ``func`` argument, and ``btf_decl_tag.component_idx`` should be a > valid index (starting from 0) pointing to a member or an argument. > > +If ``info.kind_flag`` is 0, then this is a normal decl tag, and the > +``name_off`` encodes btf_decl_tag attribute string. > + > +If ``info.kind_flag`` is 1, then the decl tag represents an arbitrary > +__attribute__. In this case, ``name_off`` encodes a string > +representing the attribute-list of the attribute specifier. For > +example, for an ``__attribute__((aligned(4)))`` the string's contents > +is ``aligned(4)``. > + > 2.2.18 BTF_KIND_TYPE_TAG > ~~~~~~~~~~~~~~~~~~~~~~~~ > > ``struct btf_type`` encoding requirement: > * ``name_off``: offset to a non-empty string > - * ``info.kind_flag``: 0 > + * ``info.kind_flag``: 0 or 1 > * ``info.kind``: BTF_KIND_TYPE_TAG > * ``info.vlen``: 0 > * ``type``: the type with ``btf_type_tag`` attribute > @@ -522,6 +531,14 @@ type_tag, then zero or more const/volatile/restrict/typedef > and finally the base type. The base type is one of > int, ptr, array, struct, union, enum, func_proto and float types. > > +Similarly to decl tags, if the ``info.kind_flag`` is 0, then this is a > +normal type tag, and the ``name_off`` encodes btf_type_tag attribute > +string. > + > +If ``info.kind_flag`` is 1, then the type tag represents an arbitrary > +__attribute__, and the ``name_off`` encodes a string representing the > +attribute-list of the attribute specifier. > + > 2.2.19 BTF_KIND_ENUM64 > ~~~~~~~~~~~~~~~~~~~~~~ > > diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h > index ec1798b6d3ff..d602c26a0c2a 100644 > --- a/tools/include/uapi/linux/btf.h > +++ b/tools/include/uapi/linux/btf.h > @@ -36,7 +36,8 @@ struct btf_type { > * bits 24-28: kind (e.g. int, ptr, array...etc) > * bits 29-30: unused > * bit 31: kind_flag, currently used by > - * struct, union, enum, fwd and enum64 > + * struct, union, enum, fwd, enum64, > + * DECL_TAG and TYPE_TAG > */ > __u32 info; > /* "size" is used by INT, ENUM, STRUCT, UNION, DATASEC and ENUM64. > diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c > index 48c66f3a9200..df2808cee009 100644 > --- a/tools/lib/bpf/btf.c > +++ b/tools/lib/bpf/btf.c > @@ -2090,7 +2090,7 @@ static int validate_type_id(int id) > } > > /* generic append function for PTR, TYPEDEF, CONST/VOLATILE/RESTRICT */ > -static int btf_add_ref_kind(struct btf *btf, int kind, const char *name, int ref_type_id) > +static int btf_add_ref_kind(struct btf *btf, int kind, const char *name, int ref_type_id, int kflag) > { > struct btf_type *t; > int sz, name_off = 0; > @@ -2113,7 +2113,7 @@ static int btf_add_ref_kind(struct btf *btf, int kind, const char *name, int ref > } > > t->name_off = name_off; > - t->info = btf_type_info(kind, 0, 0); > + t->info = btf_type_info(kind, 0, kflag); > t->type = ref_type_id; > > return btf_commit_type(btf, sz); > @@ -2128,7 +2128,7 @@ static int btf_add_ref_kind(struct btf *btf, int kind, const char *name, int ref > */ > int btf__add_ptr(struct btf *btf, int ref_type_id) > { > - return btf_add_ref_kind(btf, BTF_KIND_PTR, NULL, ref_type_id); > + return btf_add_ref_kind(btf, BTF_KIND_PTR, NULL, ref_type_id, 0); > } > > /* > @@ -2506,7 +2506,7 @@ int btf__add_fwd(struct btf *btf, const char *name, enum btf_fwd_kind fwd_kind) > struct btf_type *t; > int id; > > - id = btf_add_ref_kind(btf, BTF_KIND_FWD, name, 0); > + id = btf_add_ref_kind(btf, BTF_KIND_FWD, name, 0, 0); > if (id <= 0) > return id; > t = btf_type_by_id(btf, id); > @@ -2536,7 +2536,7 @@ int btf__add_typedef(struct btf *btf, const char *name, int ref_type_id) > if (!name || !name[0]) > return libbpf_err(-EINVAL); > > - return btf_add_ref_kind(btf, BTF_KIND_TYPEDEF, name, ref_type_id); > + return btf_add_ref_kind(btf, BTF_KIND_TYPEDEF, name, ref_type_id, 0); > } > > /* > @@ -2548,7 +2548,7 @@ int btf__add_typedef(struct btf *btf, const char *name, int ref_type_id) > */ > int btf__add_volatile(struct btf *btf, int ref_type_id) > { > - return btf_add_ref_kind(btf, BTF_KIND_VOLATILE, NULL, ref_type_id); > + return btf_add_ref_kind(btf, BTF_KIND_VOLATILE, NULL, ref_type_id, 0); > } > > /* > @@ -2560,7 +2560,7 @@ int btf__add_volatile(struct btf *btf, int ref_type_id) > */ > int btf__add_const(struct btf *btf, int ref_type_id) > { > - return btf_add_ref_kind(btf, BTF_KIND_CONST, NULL, ref_type_id); > + return btf_add_ref_kind(btf, BTF_KIND_CONST, NULL, ref_type_id, 0); > } > > /* > @@ -2572,7 +2572,7 @@ int btf__add_const(struct btf *btf, int ref_type_id) > */ > int btf__add_restrict(struct btf *btf, int ref_type_id) > { > - return btf_add_ref_kind(btf, BTF_KIND_RESTRICT, NULL, ref_type_id); > + return btf_add_ref_kind(btf, BTF_KIND_RESTRICT, NULL, ref_type_id, 0); > } > > /* > @@ -2588,7 +2588,24 @@ int btf__add_type_tag(struct btf *btf, const char *value, int ref_type_id) > if (!value || !value[0]) > return libbpf_err(-EINVAL); > > - return btf_add_ref_kind(btf, BTF_KIND_TYPE_TAG, value, ref_type_id); > + return btf_add_ref_kind(btf, BTF_KIND_TYPE_TAG, value, ref_type_id, 0); > +} > + > +/* > + * Append new BTF_KIND_TYPE_TAG type with: > + * - *value*, non-empty/non-NULL tag value; > + * - *ref_type_id* - referenced type ID, it might not exist yet; > + * Set info->kflag to 1, indicating this tag is an __attribute__ > + * Returns: > + * - >0, type ID of newly added BTF type; > + * - <0, on error. > + */ > +int btf__add_type_attr(struct btf *btf, const char *value, int ref_type_id) > +{ > + if (!value || !value[0]) > + return libbpf_err(-EINVAL); > + > + return btf_add_ref_kind(btf, BTF_KIND_TYPE_TAG, value, ref_type_id, 1); > } > > /* > @@ -2610,7 +2627,7 @@ int btf__add_func(struct btf *btf, const char *name, > linkage != BTF_FUNC_EXTERN) > return libbpf_err(-EINVAL); > > - id = btf_add_ref_kind(btf, BTF_KIND_FUNC, name, proto_type_id); > + id = btf_add_ref_kind(btf, BTF_KIND_FUNC, name, proto_type_id, 0); > if (id > 0) { > struct btf_type *t = btf_type_by_id(btf, id); > > @@ -2845,18 +2862,9 @@ int btf__add_datasec_var_info(struct btf *btf, int var_type_id, __u32 offset, __ > return 0; > } > > -/* > - * Append new BTF_KIND_DECL_TAG type with: > - * - *value* - non-empty/non-NULL string; > - * - *ref_type_id* - referenced type ID, it might not exist yet; > - * - *component_idx* - -1 for tagging reference type, otherwise struct/union > - * member or function argument index; > - * Returns: > - * - >0, type ID of newly added BTF type; > - * - <0, on error. > - */ > -int btf__add_decl_tag(struct btf *btf, const char *value, int ref_type_id, > - int component_idx) > + > +static int __btf__add_decl_tag(struct btf *btf, const char *value, > + int ref_type_id, int component_idx, int kflag) > { > struct btf_type *t; > int sz, value_off; > @@ -2880,13 +2888,46 @@ int btf__add_decl_tag(struct btf *btf, const char *value, int ref_type_id, > return value_off; > > t->name_off = value_off; > - t->info = btf_type_info(BTF_KIND_DECL_TAG, 0, false); > + t->info = btf_type_info(BTF_KIND_DECL_TAG, 0, kflag); > t->type = ref_type_id; > btf_decl_tag(t)->component_idx = component_idx; > > return btf_commit_type(btf, sz); > } > > +/* > + * Append new BTF_KIND_DECL_TAG type with: > + * - *value* - non-empty/non-NULL string; > + * - *ref_type_id* - referenced type ID, it might not exist yet; > + * - *component_idx* - -1 for tagging reference type, otherwise struct/union > + * member or function argument index; > + * Returns: > + * - >0, type ID of newly added BTF type; > + * - <0, on error. > + */ > +int btf__add_decl_tag(struct btf *btf, const char *value, int ref_type_id, > + int component_idx) > +{ > + return __btf__add_decl_tag(btf, value, ref_type_id, component_idx, 0); > +} > + > +/* > + * Append new BTF_KIND_DECL_TAG type with: > + * - *value* - non-empty/non-NULL string; > + * - *ref_type_id* - referenced type ID, it might not exist yet; > + * - *component_idx* - -1 for tagging reference type, otherwise struct/union > + * member or function argument index; > + * Set info->kflag to 1, indicating this tag is an __attribute__ > + * Returns: > + * - >0, type ID of newly added BTF type; > + * - <0, on error. > + */ > +int btf__add_decl_attr(struct btf *btf, const char *value, int ref_type_id, > + int component_idx) > +{ > + return __btf__add_decl_tag(btf, value, ref_type_id, component_idx, 1); > +} > + > struct btf_ext_sec_info_param { > __u32 off; > __u32 len; > diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h > index 47ee8f6ac489..1c969a530a3e 100644 > --- a/tools/lib/bpf/btf.h > +++ b/tools/lib/bpf/btf.h > @@ -227,6 +227,7 @@ LIBBPF_API int btf__add_volatile(struct btf *btf, int ref_type_id); > LIBBPF_API int btf__add_const(struct btf *btf, int ref_type_id); > LIBBPF_API int btf__add_restrict(struct btf *btf, int ref_type_id); > LIBBPF_API int btf__add_type_tag(struct btf *btf, const char *value, int ref_type_id); > +LIBBPF_API int btf__add_type_attr(struct btf *btf, const char *value, int ref_type_id); > > /* func and func_proto construction APIs */ > LIBBPF_API int btf__add_func(struct btf *btf, const char *name, > @@ -243,6 +244,8 @@ LIBBPF_API int btf__add_datasec_var_info(struct btf *btf, int var_type_id, > /* tag construction API */ > LIBBPF_API int btf__add_decl_tag(struct btf *btf, const char *value, int ref_type_id, > int component_idx); > +LIBBPF_API int btf__add_decl_attr(struct btf *btf, const char *value, int ref_type_id, > + int component_idx); > > struct btf_dedup_opts { > size_t sz; > diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map > index a8b2936a1646..8616e10b3c1b 100644 > --- a/tools/lib/bpf/libbpf.map > +++ b/tools/lib/bpf/libbpf.map > @@ -436,4 +436,6 @@ LIBBPF_1.6.0 { > bpf_linker__add_buf; > bpf_linker__add_fd; > bpf_linker__new_fd; > + btf__add_decl_attr; > + btf__add_type_attr; > } LIBBPF_1.5.0;