A tool that dumps C from kernel BTF may need a type tag printed differently than btf_dump prints it by default, for example as a macro that the generated header defines. The tool can't change the tag itself: kernel BTF must keep the encoding the kernel expects, and if the dumped BTF is the base of a split, a type in the base can't refer to a type added to the split. A decl tag annotates another type by referencing it, so a split can attach one to a type tag of its base. Let such decl tags override the rendering of the type tag: when a type tag has decl tags with component_idx -1, print them in its place, the same way as decl tags on declarations. The tool that builds the dumped BTF then decides how each type tag is rendered. The kernel rejects decl tags on type tags, so kernel BTF cannot have any, and its C dumps are unchanged. Document this in btf.rst. Signed-off-by: Ihor Solodrai --- Documentation/bpf/btf.rst | 10 ++++++++++ tools/lib/bpf/btf_dump.c | 12 ++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst index 29de1222c3e7..ea0d699749af 100644 --- a/Documentation/bpf/btf.rst +++ b/Documentation/bpf/btf.rst @@ -511,6 +511,9 @@ representing the attribute-list of the attribute specifier. For example, for an ``__attribute__((aligned(4)))`` the string's contents is ``aligned(4)``. +``btf_dump`` also accepts decl tags that reference a ``type_tag``, as +described under ``BTF_KIND_TYPE_TAG``. + 2.2.18 BTF_KIND_TYPE_TAG ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -542,6 +545,13 @@ 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. +``btf_dump`` prints decl tags that reference a type tag, with +``btf_decl_tag.component_idx`` of ``-1``, in place of that type tag. They +are printed the same way as decl tags on declarations. This lets a split +BTF built for a C dump change how the type tags of its base BTF are +printed, without modifying the base. The kernel rejects decl tags that +reference type tags. + 2.2.19 BTF_KIND_ENUM64 ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c index ad43bbd3b442..c12c3c248407 100644 --- a/tools/lib/bpf/btf_dump.c +++ b/tools/lib/bpf/btf_dump.c @@ -1033,10 +1033,11 @@ static void btf_dump_emit_decl_tag(struct btf_dump *d, const struct btf_type *t) * tags of one type form a run that binary search finds the start of, in a * fixed order so that the same BTF always renders the same C. */ -static void btf_dump_emit_decl_tags(struct btf_dump *d, __u32 id, int comp_idx) +static int btf_dump_emit_decl_tags(struct btf_dump *d, __u32 id, int comp_idx) { size_t i, lo = 0, hi = d->decl_tag_cnt, mid; const struct btf_type *t; + int cnt = 0; /* lower bound on target_id */ while (lo < hi) { @@ -1051,9 +1052,13 @@ static void btf_dump_emit_decl_tags(struct btf_dump *d, __u32 id, int comp_idx) for (i = lo; i < d->decl_tag_cnt && d->decl_tags[i].target_id == id; i++) { t = btf__type_by_id(d->btf, d->decl_tags[i].tag_id); - if (btf_decl_tag(t)->component_idx == comp_idx) + if (btf_decl_tag(t)->component_idx == comp_idx) { btf_dump_emit_decl_tag(d, t); + cnt++; + } } + + return cnt; } static void btf_dump_emit_struct_def(struct btf_dump *d, @@ -1592,6 +1597,9 @@ static void btf_dump_emit_type_chain(struct btf_dump *d, break; case BTF_KIND_TYPE_TAG: btf_dump_emit_mods(d, decls); + /* decl tags override the type tag, see btf.rst */ + if (btf_dump_emit_decl_tags(d, id, -1)) + break; name = btf_name_of(d, t->name_off); if (btf_kflag(t)) btf_dump_printf(d, " __attribute__((%s))", name); -- 2.56.0