mbox series

[bpf-next,0/5] BTF: arbitrary __attribute__ encoding

Message ID 20250122025308.2717553-1-ihor.solodrai@pm.me (mailing list archive)
Headers show
Series BTF: arbitrary __attribute__ encoding | expand

Message

Ihor Solodrai Jan. 22, 2025, 2:53 a.m. UTC
This patch series extends BPF Type Format (BTF) to support arbitrary
__attribute__ encoding.

Setting the kind_flag to 1 in BTF type tags and decl tags now changes
the meaning for the encoded tag, in particular with respect to
btf_dump in libbpf.

If the kflag is set, then the string encoded by the tag represents the
full attribute-list of an attribute specifier [1].

This feature will allow extending tools such as pahole and bpftool to
capture and use more granular type information, and make it easier to
manage compatibility between clang and gcc BPF compilers.

[1] https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Attribute-Syntax.html

Ihor Solodrai (5):
  libbpf: introduce kflag for type_tags and decl_tags in BTF
  libbpf: check the kflag of type tags in btf_dump
  selftests/bpf: add a btf_dump test for type_tags
  bpf: allow kind_flag for BTF type and decl tags
  selftests/bpf: add a BTF verification test for kflagged type_tag

 Documentation/bpf/btf.rst                     |  27 +++-
 kernel/bpf/btf.c                              |   7 +-
 tools/include/uapi/linux/btf.h                |   3 +-
 tools/lib/bpf/btf.c                           |  87 +++++++---
 tools/lib/bpf/btf.h                           |   3 +
 tools/lib/bpf/btf_dump.c                      |   5 +-
 tools/lib/bpf/libbpf.map                      |   2 +
 tools/testing/selftests/bpf/prog_tests/btf.c  |  23 ++-
 .../selftests/bpf/prog_tests/btf_dump.c       | 148 +++++++++++++-----
 tools/testing/selftests/bpf/test_btf.h        |   6 +
 10 files changed, 234 insertions(+), 77 deletions(-)

Comments

Alan Maguire Jan. 22, 2025, 10:13 a.m. UTC | #1
On 22/01/2025 02:53, Ihor Solodrai wrote:
> This patch series extends BPF Type Format (BTF) to support arbitrary
> __attribute__ encoding.
> 
> Setting the kind_flag to 1 in BTF type tags and decl tags now changes
> the meaning for the encoded tag, in particular with respect to
> btf_dump in libbpf.
> 
> If the kflag is set, then the string encoded by the tag represents the
> full attribute-list of an attribute specifier [1].
> 
> This feature will allow extending tools such as pahole and bpftool to
> capture and use more granular type information, and make it easier to
> manage compatibility between clang and gcc BPF compilers.
>

sounds good! So presumably pahole will then have a "full_attribute" or
similar BTF feature that will only do full attribute encoding for
kernels that expect the kind flag to be set? Otherwise we'll run the
risk of generating invalid BTF for older kernels with newer pahole
(since those older kernels will fail to verify tags with a kind flag set).

Thanks!

Alan

> [1] https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Attribute-Syntax.html
> 
> Ihor Solodrai (5):
>   libbpf: introduce kflag for type_tags and decl_tags in BTF
>   libbpf: check the kflag of type tags in btf_dump
>   selftests/bpf: add a btf_dump test for type_tags
>   bpf: allow kind_flag for BTF type and decl tags
>   selftests/bpf: add a BTF verification test for kflagged type_tag
> 
>  Documentation/bpf/btf.rst                     |  27 +++-
>  kernel/bpf/btf.c                              |   7 +-
>  tools/include/uapi/linux/btf.h                |   3 +-
>  tools/lib/bpf/btf.c                           |  87 +++++++---
>  tools/lib/bpf/btf.h                           |   3 +
>  tools/lib/bpf/btf_dump.c                      |   5 +-
>  tools/lib/bpf/libbpf.map                      |   2 +
>  tools/testing/selftests/bpf/prog_tests/btf.c  |  23 ++-
>  .../selftests/bpf/prog_tests/btf_dump.c       | 148 +++++++++++++-----
>  tools/testing/selftests/bpf/test_btf.h        |   6 +
>  10 files changed, 234 insertions(+), 77 deletions(-)
>
Jose E. Marchesi Jan. 22, 2025, 11:44 a.m. UTC | #2
> This patch series extends BPF Type Format (BTF) to support arbitrary
> __attribute__ encoding.
>
> Setting the kind_flag to 1 in BTF type tags and decl tags now changes
> the meaning for the encoded tag, in particular with respect to
> btf_dump in libbpf.
>
> If the kflag is set, then the string encoded by the tag represents the
> full attribute-list of an attribute specifier [1].

Why is extending BTF necessary for this?  Type and declaration tags
contain arbitrary strings, and AFAIK you can have more than one type tag
associated with a single type or declaration.  Why coupling the
interpretation of the contents of the string with the transport format?

Something like "cattribute:always_inline".

> This feature will allow extending tools such as pahole and bpftool to
> capture and use more granular type information, and make it easier to
> manage compatibility between clang and gcc BPF compilers.
>
> [1] https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Attribute-Syntax.html
>
> Ihor Solodrai (5):
>   libbpf: introduce kflag for type_tags and decl_tags in BTF
>   libbpf: check the kflag of type tags in btf_dump
>   selftests/bpf: add a btf_dump test for type_tags
>   bpf: allow kind_flag for BTF type and decl tags
>   selftests/bpf: add a BTF verification test for kflagged type_tag
>
>  Documentation/bpf/btf.rst                     |  27 +++-
>  kernel/bpf/btf.c                              |   7 +-
>  tools/include/uapi/linux/btf.h                |   3 +-
>  tools/lib/bpf/btf.c                           |  87 +++++++---
>  tools/lib/bpf/btf.h                           |   3 +
>  tools/lib/bpf/btf_dump.c                      |   5 +-
>  tools/lib/bpf/libbpf.map                      |   2 +
>  tools/testing/selftests/bpf/prog_tests/btf.c  |  23 ++-
>  .../selftests/bpf/prog_tests/btf_dump.c       | 148 +++++++++++++-----
>  tools/testing/selftests/bpf/test_btf.h        |   6 +
>  10 files changed, 234 insertions(+), 77 deletions(-)
Ihor Solodrai Jan. 22, 2025, 6:06 p.m. UTC | #3
On Wednesday, January 22nd, 2025 at 3:44 AM, Jose E. Marchesi <jose.marchesi@oracle.com> wrote:

> 
> 
> > This patch series extends BPF Type Format (BTF) to support arbitrary
> > attribute encoding.
> > 
> > Setting the kind_flag to 1 in BTF type tags and decl tags now changes
> > the meaning for the encoded tag, in particular with respect to
> > btf_dump in libbpf.
> > 
> > If the kflag is set, then the string encoded by the tag represents the
> > full attribute-list of an attribute specifier [1].
> 
> 
> Why is extending BTF necessary for this? Type and declaration tags
> contain arbitrary strings, and AFAIK you can have more than one type tag
> associated with a single type or declaration. Why coupling the
> interpretation of the contents of the string with the transport format?
> 
> Something like "cattribute:always_inline".

Hi Jose. Good questions.

You are correct that the tags can contain arbitrary strings already,
and that multiple tags can be associated with the same type or
declaration.

A specific problem I'm trying to solve is how to direct btf_dump in
interpreting tags as attributes, and do it in a generic way, as it's a
part of libbpf.

I discussed with Andrii, Eduard and Alexei a couple of approaches, and
tried some of them.

For example, a set of dump options could be introduced to handle
specific use-cases, similar to what you suggested in a
ATTR_PRESERVE_ACCESS_INDEX patch [1]. This is a valid approach,
however it is not very generic. An option will have to be introduced
and implemented for every new use-case.

A more generic approach is adding a set of callbacks to btf_dump. This
is a big design task, which I think should be avoided unless
absolutely necessary.

The benefit of this change - defining flagged tags as attributes - is
that it enables BTF to natively encode attributes as part of a type,
which is not possible currently. And it's a simple change.

Using the contents of the tag to indicate it's meaning (such as
"cattrubite:always_inline") will work too. However I don't think it's
desirable to have to parse the tag strings within libbpf, even more so
in BPF verifier.

In a discussion with Andrii we briefly entertained an idea of allowing
btf_dump to print the tag string directly (without requiring it to be
a tag or attribute), which would allow all kinds of hacks. Tempting,
but probably very bug-prone.

[1] https://lore.kernel.org/bpf/20240503111836.25275-1-jose.marchesi@oracle.com/

> 
> > This feature will allow extending tools such as pahole and bpftool to
> > capture and use more granular type information, and make it easier to
> > manage compatibility between clang and gcc BPF compilers.
> > 
> > [1] https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Attribute-Syntax.html
> > 
> > Ihor Solodrai (5):
> > libbpf: introduce kflag for type_tags and decl_tags in BTF
> > libbpf: check the kflag of type tags in btf_dump
> > selftests/bpf: add a btf_dump test for type_tags
> > bpf: allow kind_flag for BTF type and decl tags
> > selftests/bpf: add a BTF verification test for kflagged type_tag
> > 
> > Documentation/bpf/btf.rst | 27 +++-
> > kernel/bpf/btf.c | 7 +-
> > tools/include/uapi/linux/btf.h | 3 +-
> > tools/lib/bpf/btf.c | 87 +++++++---
> > tools/lib/bpf/btf.h | 3 +
> > tools/lib/bpf/btf_dump.c | 5 +-
> > tools/lib/bpf/libbpf.map | 2 +
> > tools/testing/selftests/bpf/prog_tests/btf.c | 23 ++-
> > .../selftests/bpf/prog_tests/btf_dump.c | 148 +++++++++++++-----
> > tools/testing/selftests/bpf/test_btf.h | 6 +
> > 10 files changed, 234 insertions(+), 77 deletions(-)
Jose E. Marchesi Jan. 22, 2025, 7:47 p.m. UTC | #4
> On Wednesday, January 22nd, 2025 at 3:44 AM, Jose E. Marchesi <jose.marchesi@oracle.com> wrote:
>
>> 
>> 
>> > This patch series extends BPF Type Format (BTF) to support arbitrary
>> > attribute encoding.
>> > 
>> > Setting the kind_flag to 1 in BTF type tags and decl tags now changes
>> > the meaning for the encoded tag, in particular with respect to
>> > btf_dump in libbpf.
>> > 
>> > If the kflag is set, then the string encoded by the tag represents the
>> > full attribute-list of an attribute specifier [1].
>> 
>> 
>> Why is extending BTF necessary for this? Type and declaration tags
>> contain arbitrary strings, and AFAIK you can have more than one type tag
>> associated with a single type or declaration. Why coupling the
>> interpretation of the contents of the string with the transport format?
>> 
>> Something like "cattribute:always_inline".
>
> Hi Jose. Good questions.
>
> You are correct that the tags can contain arbitrary strings already,
> and that multiple tags can be associated with the same type or
> declaration.
>
> A specific problem I'm trying to solve is how to direct btf_dump in
> interpreting tags as attributes, and do it in a generic way, as it's a
> part of libbpf.
>
> I discussed with Andrii, Eduard and Alexei a couple of approaches, and
> tried some of them.
>
> For example, a set of dump options could be introduced to handle
> specific use-cases, similar to what you suggested in a
> ATTR_PRESERVE_ACCESS_INDEX patch [1]. This is a valid approach,
> however it is not very generic. An option will have to be introduced
> and implemented for every new use-case.
>
> A more generic approach is adding a set of callbacks to btf_dump. This
> is a big design task, which I think should be avoided unless
> absolutely necessary.
>
> The benefit of this change - defining flagged tags as attributes - is
> that it enables BTF to natively encode attributes as part of a type,
> which is not possible currently. And it's a simple change.
>
> Using the contents of the tag to indicate it's meaning (such as
> "cattrubite:always_inline") will work too. However I don't think it's
> desirable to have to parse the tag strings within libbpf, even more so
> in BPF verifier.

I expect the verifier will in any case have to distinguish the different
strings it gets in the tags, for other purposes, right, so this wouldn't
be introducing anything different?

Also FWIW DWARF doesn't have a kind_flag.

>
> In a discussion with Andrii we briefly entertained an idea of allowing
> btf_dump to print the tag string directly (without requiring it to be
> a tag or attribute), which would allow all kinds of hacks. Tempting,
> but probably very bug-prone.
>
> [1] https://lore.kernel.org/bpf/20240503111836.25275-1-jose.marchesi@oracle.com/
>
>> 
>> > This feature will allow extending tools such as pahole and bpftool to
>> > capture and use more granular type information, and make it easier to
>> > manage compatibility between clang and gcc BPF compilers.
>> > 
>> > [1] https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Attribute-Syntax.html
>> > 
>> > Ihor Solodrai (5):
>> > libbpf: introduce kflag for type_tags and decl_tags in BTF
>> > libbpf: check the kflag of type tags in btf_dump
>> > selftests/bpf: add a btf_dump test for type_tags
>> > bpf: allow kind_flag for BTF type and decl tags
>> > selftests/bpf: add a BTF verification test for kflagged type_tag
>> > 
>> > Documentation/bpf/btf.rst | 27 +++-
>> > kernel/bpf/btf.c | 7 +-
>> > tools/include/uapi/linux/btf.h | 3 +-
>> > tools/lib/bpf/btf.c | 87 +++++++---
>> > tools/lib/bpf/btf.h | 3 +
>> > tools/lib/bpf/btf_dump.c | 5 +-
>> > tools/lib/bpf/libbpf.map | 2 +
>> > tools/testing/selftests/bpf/prog_tests/btf.c | 23 ++-
>> > .../selftests/bpf/prog_tests/btf_dump.c | 148 +++++++++++++-----
>> > tools/testing/selftests/bpf/test_btf.h | 6 +
>> > 10 files changed, 234 insertions(+), 77 deletions(-)
Ihor Solodrai Jan. 22, 2025, 8:38 p.m. UTC | #5
On Wednesday, January 22nd, 2025 at 11:47 AM, Jose E. Marchesi <jose.marchesi@oracle.com> wrote:

> [...]
> > 
> > Using the contents of the tag to indicate it's meaning (such as
> > "cattrubite:always_inline") will work too. However I don't think it's
> > desirable to have to parse the tag strings within libbpf, even more so
> > in BPF verifier.
> 
> 
> I expect the verifier will in any case have to distinguish the different
> strings it gets in the tags, for other purposes, right, so this wouldn't
> be introducing anything different?

I only see direct string comparisons in the BTF verification, for example:

    if (btf_type_is_type_tag(t)) {
    		tag_value = __btf_name_by_offset(btf, t->name_off);
    		if (strcmp(tag_value, "user") == 0)
    			info->reg_type |= MEM_USER;
    		if (strcmp(tag_value, "percpu") == 0)
    			info->reg_type |= MEM_PERCPU;
    	}

What's different is that this way a syntax is introduced, even if very
simple like "prefix:suffix". And so it potentially has to be parsed by
the tag reader, be it btf_dump or anything else. Testing a kflag is
just a much simpler operation. Maybe if we had N kinds of tags, and
not just two this would make sense?

Also. would this way of encoding be a part of the BTF spec then?
It can be done in principle, I just don't know if it's a good idea.

> 
> Also FWIW DWARF doesn't have a kind_flag.

Right, but BTF was designed with different goals, and one of them is to
be compact. kind_flag so far just hasn't been used by the tags, but it
is used in other BTF types.

> 
> [...]
Andrii Nakryiko Jan. 22, 2025, 9:52 p.m. UTC | #6
On Wed, Jan 22, 2025 at 3:44 AM Jose E. Marchesi
<jose.marchesi@oracle.com> wrote:
>
>
> > This patch series extends BPF Type Format (BTF) to support arbitrary
> > __attribute__ encoding.
> >
> > Setting the kind_flag to 1 in BTF type tags and decl tags now changes
> > the meaning for the encoded tag, in particular with respect to
> > btf_dump in libbpf.
> >
> > If the kflag is set, then the string encoded by the tag represents the
> > full attribute-list of an attribute specifier [1].
>
> Why is extending BTF necessary for this?  Type and declaration tags
> contain arbitrary strings, and AFAIK you can have more than one type tag

Because currently TYPE_TAG(some_string) is
__attribute__((btf_type_tag("some_string"))).

That btf_type_tag() attribute name is hard-coded in the semantics of
current TYPE_TAG (and DECL_TAG as well). So here Ihor is generalizing
this to be __attribute__((some_string)).

> associated with a single type or declaration.  Why coupling the
> interpretation of the contents of the string with the transport format?
>
> Something like "cattribute:always_inline".

I think that ship has sailed. We didn't define any extra semantics for
any sort of "prefix:" part of TYPE_TAG's string, and I'm not sure we
want to retroactively define anything like that at this point.

What is exactly the problem with using kflag=1? Keep in mind, at least
initially, this is meant for tools like pahole and bpftool, not
GCC/Clang itself, to augment BTF with extra annotations (like
preserve_access_index attribute that is added when generating
vmlinux.h).

>
> > This feature will allow extending tools such as pahole and bpftool to
> > capture and use more granular type information, and make it easier to
> > manage compatibility between clang and gcc BPF compilers.
> >
> > [1] https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Attribute-Syntax.html
> >
> > Ihor Solodrai (5):
> >   libbpf: introduce kflag for type_tags and decl_tags in BTF
> >   libbpf: check the kflag of type tags in btf_dump
> >   selftests/bpf: add a btf_dump test for type_tags
> >   bpf: allow kind_flag for BTF type and decl tags
> >   selftests/bpf: add a BTF verification test for kflagged type_tag
> >
> >  Documentation/bpf/btf.rst                     |  27 +++-
> >  kernel/bpf/btf.c                              |   7 +-
> >  tools/include/uapi/linux/btf.h                |   3 +-
> >  tools/lib/bpf/btf.c                           |  87 +++++++---
> >  tools/lib/bpf/btf.h                           |   3 +
> >  tools/lib/bpf/btf_dump.c                      |   5 +-
> >  tools/lib/bpf/libbpf.map                      |   2 +
> >  tools/testing/selftests/bpf/prog_tests/btf.c  |  23 ++-
> >  .../selftests/bpf/prog_tests/btf_dump.c       | 148 +++++++++++++-----
> >  tools/testing/selftests/bpf/test_btf.h        |   6 +
> >  10 files changed, 234 insertions(+), 77 deletions(-)
Jose E. Marchesi Jan. 22, 2025, 10:44 p.m. UTC | #7
> On Wed, Jan 22, 2025 at 3:44 AM Jose E. Marchesi
> <jose.marchesi@oracle.com> wrote:
>>
>>
>> > This patch series extends BPF Type Format (BTF) to support arbitrary
>> > __attribute__ encoding.
>> >
>> > Setting the kind_flag to 1 in BTF type tags and decl tags now changes
>> > the meaning for the encoded tag, in particular with respect to
>> > btf_dump in libbpf.
>> >
>> > If the kflag is set, then the string encoded by the tag represents the
>> > full attribute-list of an attribute specifier [1].
>>
>> Why is extending BTF necessary for this?  Type and declaration tags
>> contain arbitrary strings, and AFAIK you can have more than one type tag
>
> Because currently TYPE_TAG(some_string) is
> __attribute__((btf_type_tag("some_string"))).
>
> That btf_type_tag() attribute name is hard-coded in the semantics of
> current TYPE_TAG (and DECL_TAG as well). So here Ihor is generalizing
> this to be __attribute__((some_string)).
>
>> associated with a single type or declaration.  Why coupling the
>> interpretation of the contents of the string with the transport format?
>>
>> Something like "cattribute:always_inline".
>
> I think that ship has sailed. We didn't define any extra semantics for
> any sort of "prefix:" part of TYPE_TAG's string, and I'm not sure we
> want to retroactively define anything like that at this point.
>
> What is exactly the problem with using kflag=1? Keep in mind, at least
> initially, this is meant for tools like pahole and bpftool, not
> GCC/Clang itself, to augment BTF with extra annotations (like
> preserve_access_index attribute that is added when generating
> vmlinux.h).

Ah ok, I misunderstood how this is intended to be used.

I thought it would be the BPF compiler that would be creating these
entries.  But it is these tools that will emit the attributes in the
headers, and then augment the BTF entries for these particular
attributes when loading the programs that include the headers?

>
>>
>> > This feature will allow extending tools such as pahole and bpftool to
>> > capture and use more granular type information, and make it easier to
>> > manage compatibility between clang and gcc BPF compilers.
>> >
>> > [1] https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Attribute-Syntax.html
>> >
>> > Ihor Solodrai (5):
>> >   libbpf: introduce kflag for type_tags and decl_tags in BTF
>> >   libbpf: check the kflag of type tags in btf_dump
>> >   selftests/bpf: add a btf_dump test for type_tags
>> >   bpf: allow kind_flag for BTF type and decl tags
>> >   selftests/bpf: add a BTF verification test for kflagged type_tag
>> >
>> >  Documentation/bpf/btf.rst                     |  27 +++-
>> >  kernel/bpf/btf.c                              |   7 +-
>> >  tools/include/uapi/linux/btf.h                |   3 +-
>> >  tools/lib/bpf/btf.c                           |  87 +++++++---
>> >  tools/lib/bpf/btf.h                           |   3 +
>> >  tools/lib/bpf/btf_dump.c                      |   5 +-
>> >  tools/lib/bpf/libbpf.map                      |   2 +
>> >  tools/testing/selftests/bpf/prog_tests/btf.c  |  23 ++-
>> >  .../selftests/bpf/prog_tests/btf_dump.c       | 148 +++++++++++++-----
>> >  tools/testing/selftests/bpf/test_btf.h        |   6 +
>> >  10 files changed, 234 insertions(+), 77 deletions(-)