BPF List
 help / color / mirror / Atom feed
From: Eduard Zingerman <eddyz87@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>,
	Yonghong Song <yhs@meta.com>
Cc: bpf@vger.kernel.org, ast@kernel.org, andrii@kernel.org,
	daniel@iogearbox.net, kernel-team@fb.com, yhs@fb.com,
	alan.maguire@oracle.com
Subject: Re: [PATCH bpf-next 1/2] libbpf: __attribute__((btf_decl_tag("..."))) for btf dump in C format
Date: Tue, 08 Nov 2022 01:17:21 +0200	[thread overview]
Message-ID: <726d3b01f69ddb158ff79e648f29bed5c9b27e0e.camel@gmail.com> (raw)
In-Reply-To: <CAEf4BzYzVLTojnbx-qK6BchBYj599yK7fohssfDX=nSbHUJRwA@mail.gmail.com>

On Mon, 2022-11-07 at 15:09 -0800, Andrii Nakryiko wrote:
> On Mon, Nov 7, 2022 at 7:35 AM Eduard Zingerman <eddyz87@gmail.com> wrote:
> > 
> > On Fri, 2022-11-04 at 13:54 -0700, Andrii Nakryiko wrote:
> > > On Thu, Nov 3, 2022 at 6:45 AM Eduard Zingerman <eddyz87@gmail.com> wrote:
> > > > 
> > > > Clang's `__attribute__((btf_decl_tag("...")))` is represented in BTF
> > > > as a record of kind BTF_KIND_DECL_TAG with `type` field pointing to
> > > > the type annotated with this attribute. This commit adds
> > > > reconstitution of such attributes for BTF dump in C format.
> > > > 
> > > > BTF doc says that BTF_KIND_DECL_TAGs should follow a target type but
> > > > this is not enforced and tests don't honor this restriction.
> > > > This commit uses hashmap to map types to the list of decl tags.
> > > > The hashmap is filled by `btf_dump_assign_decl_tags` function called
> > > > from `btf_dump__new`.
> > > > 
> > > > It is assumed that total number of types annotated with decl tags is
> > > > relatively small, thus some space is saved by using hashmap instead of
> > > > adding a new field to `struct btf_dump_type_aux_state`.
> > > > 
> > > > It is assumed that list of decl tags associated with a single type is
> > > > small. Thus the list is represented by an array which grows linearly.
> > > > 
> > > > To accommodate older Clang versions decl tags are dumped using the
> > > > following macro:
> > > > 
> > > >  #if __has_attribute(btf_decl_tag)
> > > >  #  define __btf_decl_tag(x) __attribute__((btf_decl_tag(x)))
> > > >  #else
> > > >  #  define __btf_decl_tag(x)
> > > >  #endif
> > > > 
> > > > The macro definition is emitted upon first call to `btf_dump__dump_type`.
> > > > 
> > > > Clang allows to attach btf_decl_tag attributes to the following kinds
> > > > of items:
> > > > - struct/union         supported
> > > > - struct/union field   supported
> > > > - typedef              supported
> > > > - function             not applicable
> > > > - function parameter   not applicable
> > > > - variable             not applicable
> > > > 
> > > > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> > > > ---
> > > >  tools/lib/bpf/btf_dump.c | 163 ++++++++++++++++++++++++++++++++++++++-
> > > >  1 file changed, 160 insertions(+), 3 deletions(-)
> > > > 
> > > 
> > > Functions and their args can also have tags. This works:
> > > 
> > > diff --git a/tools/testing/selftests/bpf/progs/btf_dump_test_case_decl_tag.c
> > > b/tools/testing/selftests/bpf/progs/btf_dump_test_case_decl_tag.c
> > > index 7a5af8b86065..75fcabe700cd 100644
> > > --- a/tools/testing/selftests/bpf/progs/btf_dump_test_case_decl_tag.c
> > > +++ b/tools/testing/selftests/bpf/progs/btf_dump_test_case_decl_tag.c
> > > @@ -54,7 +54,7 @@ struct root_struct {
> > > 
> > >  /* ------ END-EXPECTED-OUTPUT ------ */
> > > 
> > > -int f(struct root_struct *s)
> > > +int f(struct root_struct *s __btf_decl_tag("func_arg_tag"))
> > > __btf_decl_tag("func_tag")
> > >  {
> > >         return 0;
> > >  }
> > > 
> > > And I see correct BTF:
> > > 
> > > [26] FUNC 'f' type_id=25 linkage=global
> > > [27] DECL_TAG 'func_arg_tag' type_id=26 component_idx=0
> > > [28] DECL_TAG 'func_tag' type_id=26 component_idx=-1
> > > 
> > > So let's add support and test for that case as well. btf_dump
> > > shouldn't assume vmlinux.h-only case.
> > > 
> > > Also, please check if DATASEC and VARs can have decl_tags associated with them.
> > 
> > I see that right now decl tags are saved for:
> > - BTF_KIND_VAR
> > - BTF_KIND_FUNC
> > - BTF_KIND_FUNC arguments
> > 
> > Decl tags are lost but legal for:
> > - BTF_KIND_FUNC_PROTO arguments
> 
> ah, that's unfortunate and even DECL_TAGS example I showed above seems
> like a bug. FUNC itself doesn't have args, I implicitly assumed that
> all DECL_TAG will be actually associated with underlying FUNC_PROTO.
> 
> Yonghong, is this by design or a bug?
> 
> > 
> > I have not found a way to attach decl tag to DATASEC.
> > 
> > For BTF_KIND_FUNC_PROTO  arguments it would  be great to  update clang
> > first. Then  it would be  possible to keep all  decl tags checks  as a
> > single  `btf_dump_test_case`.  On  the   other  hand  this  will  make
> > testsuite dependent on the latest clang version, which is not great. I
> > can add a test with hand-crafted BTF instead. Which way is preferable?
> 
> let's figure out if current state is accidental or by design.
> 
> From practical standpoint, I'd still implement the code for FUNC_PROTO
> and its args, but I wouldn't go all the way to hand-craft BTF
> programmatically. As you said, btf_dump tests are way more ergonomic
> because we rely on compiler to do the heavy lifting.
> 
> As for the dependency on latest clang for some tests, I think that's
> totally fine and unavoidable. Worst case some subtests will fail on
> old kernels, they can be denylisted on systems with old compiler. All
> that won't break the build (which is much worse and inconvenient).
> 
> > 
> > BTF_KIND_FUNC is ignored by `btf_dump__dump_type_data`
> > (via `btf_dump_unsupported_data`).
> > 
> > BTF_KIND_VAR is dumped but current  testing infrastructure is not very
> > convenient, it only checks for  some variables defined in vmlinux BTF.
> > I can write a  test that accepts a custom built BTF  but this is still
> > inferior   to  what   `test_btf_dump_case`  provides.   I've  extended
> > `test_btf_dump_case` to print DATASEC  with subordinate vars alongside
> > the type definitions instead.
> > 
> 
> dumping DATASEC/VAR and FUNC is something that seems useful in
> general, but we should treat it as a separate problem. Seeing DATASEC
> variables and FUNCs in a familiar C syntax would be nice, but it
> probably should be guarded behind a bpftool option or something.
> 
> So in summary, let's figure out the situation with FUNC and FUNC_PROTO
> first, and let's not due too laborious selftests yet

Actually, to test the decl tag attachment for VAR I already implemented
a change to the `test_btf_dump_case`. It can be separated as a different
kind of tests but I don't see a point as it would be very similar to
`test_btf_dump_case`.

And manually creating BTF to attach decl tag to function proto parameter
highlighted an issue that `btf_dump_assign_decl_tags` is only called once.
So, the incremental scenario is not supported.

I can post v2 with the change to `test_btf_dump_case`, support for
decl tags on VARs and a fix for incremental dump behavior.

> 
> > ------
> > 
> > $ cat test.c
> > #define __btf_decl_tag(x) __attribute__((btf_decl_tag(x)))
> > 
> > int var __btf_decl_tag("var_tag");
> > 
> > struct root {
> >   int a;
> >   int (*b)(int x __btf_decl_tag("arg_tag_proto")) __btf_decl_tag("field_tag");
> > };
> > 
> > int foo(struct root *x __btf_decl_tag("arg_tag_fn")) __btf_decl_tag("func_tag_fn") {
> >   return 0;
> > }
> > $ clang -g -O2 -mcpu=v3 -target bpf -c test.c -o test.o
> > $ bpftool btf dump file test.o
> > [1] PTR '(anon)' type_id=2
> > [2] STRUCT 'root' size=16 vlen=2
> >         'a' type_id=3 bits_offset=0
> >         'b' type_id=4 bits_offset=64
> > [3] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
> > [4] PTR '(anon)' type_id=5
> > [5] FUNC_PROTO '(anon)' ret_type_id=3 vlen=1
> >         '(anon)' type_id=3
> > [6] DECL_TAG 'field_tag' type_id=2 component_idx=1
> > [7] FUNC_PROTO '(anon)' ret_type_id=3 vlen=1
> >         'x' type_id=1
> > [8] FUNC 'foo' type_id=7 linkage=global
> > [9] DECL_TAG 'arg_tag_fn' type_id=8 component_idx=0
> > [10] DECL_TAG 'func_tag_fn' type_id=8 component_idx=-1
> > [11] VAR 'var' type_id=3, linkage=global
> > [12] DECL_TAG 'var_tag' type_id=11 component_idx=-1
> > [13] DATASEC '.bss' size=0 vlen=1
> >         type_id=11 offset=0 size=4 (VAR 'var')
> > 
> > > [...]
> > > 
> 
> [...]


  reply	other threads:[~2022-11-07 23:17 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-03 13:45 [PATCH bpf-next 1/2] libbpf: __attribute__((btf_decl_tag("..."))) for btf dump in C format Eduard Zingerman
2022-11-03 13:45 ` [PATCH bpf-next 2/2] selftests/bpf: Tests for BTF_KIND_DECL_TAG " Eduard Zingerman
2022-11-04 20:54 ` [PATCH bpf-next 1/2] libbpf: __attribute__((btf_decl_tag("..."))) for btf " Andrii Nakryiko
2022-11-06 21:40   ` Eduard Zingerman
2022-11-07 22:52     ` Andrii Nakryiko
2022-11-07 15:35   ` Eduard Zingerman
2022-11-07 23:09     ` Andrii Nakryiko
2022-11-07 23:17       ` Eduard Zingerman [this message]
2022-11-08  0:54         ` Andrii Nakryiko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=726d3b01f69ddb158ff79e648f29bed5c9b27e0e.camel@gmail.com \
    --to=eddyz87@gmail.com \
    --cc=alan.maguire@oracle.com \
    --cc=andrii.nakryiko@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@fb.com \
    --cc=yhs@fb.com \
    --cc=yhs@meta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox