BPF List
 help / color / mirror / Atom feed
From: Delyan Kratunov <delyank@fb.com>
To: "andrii.nakryiko@gmail.com" <andrii.nakryiko@gmail.com>
Cc: "daniel@iogearbox.net" <daniel@iogearbox.net>,
	"ast@kernel.org" <ast@kernel.org>,
	"andrii@kernel.org" <andrii@kernel.org>,
	"bpf@vger.kernel.org" <bpf@vger.kernel.org>
Subject: Re: [PATCH bpf-next v2 4/5] bpftool: add support for subskeletons
Date: Mon, 14 Mar 2022 23:18:32 +0000	[thread overview]
Message-ID: <e3e84d87c2a0c13ae9f20e44493c1578e06b6618.camel@fb.com> (raw)
In-Reply-To: <CAEf4BzaeycEUjZVCd+7sxFaQWfbqhmsMd_G_bydS15+45LcDvA@mail.gmail.com>

Thanks, Andrii! The nits/refactors are straightforward but have some questions
below:

On Fri, 2022-03-11 at 15:27 -0800, Andrii Nakryiko wrote:
> > +
> > +                       /* sanitize variable name, e.g., for static vars inside
> > +                        * a function, it's name is '<function name>.<variable name>',
> > +                        * which we'll turn into a '<function name>_<variable name>'.
> > +                        */
> > +                       sanitize_identifier(var_ident + 1);
> 
> btw, I think we don't need sanitization anymore. We needed it for
> static variables (they would be of the form <func_name>.<var_name> for
> static variables inside the functions), but now it's just unnecessary
> complication

How would we handle static variables inside functions in libraries then?

> 
> > +                       var_ident[0] = ' ';
> > +
> > +                       /* The datasec member has KIND_VAR but we want the
> > +                        * underlying type of the variable (e.g. KIND_INT).
> > +                        */
> > +                       var = btf__type_by_id(btf, var->type);
> 
> you need to use skip_mods_and_typedefs() or equivalent to skip any
> const/volatile/restrict modifiers before checking btf_is_array()

Good catch!

> 
> > +
> > +                       /* Prepend * to the field name to make it a pointer. */
> > +                       var_ident[0] = '*';
> > +
> > +                       printf("\t\t");
> > +                       /* Func and array members require special handling.
> > +                        * Instead of producing `typename *var`, they produce
> > +                        * `typeof(typename) *var`. This allows us to keep a
> > +                        * similar syntax where the identifier is just prefixed
> > +                        * by *, allowing us to ignore C declaration minutae.
> > +                        */
> > +                       if (btf_is_array(var) ||
> > +                           btf_is_ptr_to_func_proto(btf, var)) {
> > +                               printf("typeof(");
> > +                               /* print the type inside typeof() without a name */
> > +                               opts.field_name = "";
> > +                               err = btf_dump__emit_type_decl(d, var_type_id, &opts);
> > +                               if (err)
> > +                                       goto out;
> > +                               printf(") %s", var_ident);
> > +                       } else {
> > +                               err = btf_dump__emit_type_decl(d, var_type_id, &opts);
> > +                               if (err)
> > +                                       goto out;
> > +                       }
> > +                       printf(";\n");
> 
> we can simplify this a bit around var_ident and two
> btf_dump__emit_type_decl() invocations. We know that we are handling
> "non-uniform" C syntax for array and func pointer, so we don't need to
> use opts.field_name. Doing this (schematically) should work (taking
> into account no need for sanitization as well):
> 
> if (btf_is_array() || btf_is_ptr_to_func_proto())
>     printf("typeof(");
> btf_dump__emit_type_decl(... /* opts.field_name stays NULL */);
> printf(" *%s", var_name);
> 
> or did I miss some corner case?

You didn't close the "typeof" :) 

if (btf_is_array() || btf_is_ptr_to_func_proto())
     printf("typeof(");
btf_dump__emit_type_decl(... /* opts.field_name stays NULL */);
if (btf_is_array() || btf_is_ptr_to_func_proto())
     printf(")");
printf(" *%s", var_name);

If you feel that's easier to understand, sure. I don't love it but it's
understandable enough.

[...]


> we don't know the name of the final object, why would we allow to set
> any object name at all?

We don't really care about the final object name but we do need an object name
for the subskeleton. The subskeleton type name, header guard etc all use it.
We can say that it's always taken from the file name, but giving the user the
option to override it feels right, given the parallel with skeletons (and what
would we do if the file name is a pipe from a subshell invocation?).

> > 
> > +
> > +       /* The empty object name allows us to use bpf_map__name and produce
> > +        * ELF section names out of it. (".data" instead of "obj.data")
> > +        */
> > +       opts.object_name = "";
> 
> yep, like this. So that "name" argument "support" above is bogus,
> let's remove it

See above, it changes real things.

> 
> > +       obj = bpf_object__open_mem(obj_data, file_sz, &opts);
> > +       if (!obj) {
> > +               char err_buf[256];
> > +
> > +               libbpf_strerror(errno, err_buf, sizeof(err_buf));
> > +               p_err("failed to open BPF object file: %s", err_buf);
> > +               obj = NULL;
> > +               goto out;
> > +       }
> > +
> 
> [...]
> 
> > +               for (i = 0; i < len; i++, var++) {
> > +                       var_type = btf__type_by_id(btf, var->type);
> > +                       var_name = btf__name_by_offset(btf, var_type->name_off);
> > +
> > +                       if (btf_var(var_type)->linkage == BTF_VAR_STATIC)
> > +                               continue;
> > +
> > +                       var_ident[0] = '\0';
> > +                       strncat(var_ident, var_name, sizeof(var_ident) - 1);
> > +                       sanitize_identifier(var_ident);
> > +
> > +                       /* Note that we use the dot prefix in .data as the
> > +                        * field access operator i.e. maps%s becomes maps.data
> > +                        */
> > +                       codegen("\
> > +                       \n\
> > +                               s->vars[%4$d].name = \"%1$s\";              \n\
> > +                               s->vars[%4$d].map = &obj->maps%3$s;         \n\
> > +                               s->vars[%4$d].addr = (void**) &obj->%2$s.%1$s;\n\
> > +                       ", var_ident, ident, bpf_map__name(map), var_idx);
> 
> map reference should be using ident, not bpf_map__name(), as it refers
> to a field. The way it is now it shouldn't work for custom
> .data.my_section case (do you have a test for this?) You shouldn't
> need bpf_map__name() here at all.

Good catch, I'll add a .data.custom test.

[...]

> 
> > +               "       %1$s %2$s subskeleton FILE [name OBJECT_NAME]\n"
> 
> [name OBJECT_NAME] should be supported

Not sure what you mean by "supported" here.

> 
> >                 "       %1$s %2$s min_core_btf INPUT OUTPUT OBJECT [OBJECT...]\n"
> >                 "       %1$s %2$s help\n"
> >                 "\n"
> > @@ -1788,6 +2250,7 @@ static int do_min_core_btf(int argc, char **argv)
> >  static const struct cmd cmds[] = {
> >         { "object",             do_object },
> >         { "skeleton",           do_skeleton },
> > +       { "subskeleton",        do_subskeleton },
> >         { "min_core_btf",       do_min_core_btf},
> >         { "help",               do_help },
> >         { 0 }
> > --
> > 2.34.1

-- Delyan


  reply	other threads:[~2022-03-14 23:18 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-11  0:11 [PATCH bpf-next v2 0/5] Subskeleton support for BPF libraries Delyan Kratunov
2022-03-11  0:11 ` [PATCH bpf-next v2 1/5] libbpf: add new strict flag for .text subprograms Delyan Kratunov
2022-03-11 22:30   ` Andrii Nakryiko
2022-03-11  0:11 ` [PATCH bpf-next v2 2/5] libbpf: init btf_{key,value}_type_id on internal map open Delyan Kratunov
2022-03-11 22:42   ` Andrii Nakryiko
2022-03-11  0:11 ` [PATCH bpf-next v2 3/5] libbpf: add subskeleton scaffolding Delyan Kratunov
2022-03-11 22:52   ` Andrii Nakryiko
2022-03-11 23:08     ` Andrii Nakryiko
2022-03-11 23:28       ` Delyan Kratunov
2022-03-11 23:41         ` Andrii Nakryiko
2022-03-11  0:11 ` [PATCH bpf-next v2 4/5] bpftool: add support for subskeletons Delyan Kratunov
2022-03-11 23:27   ` Andrii Nakryiko
2022-03-14 23:18     ` Delyan Kratunov [this message]
2022-03-15 17:28       ` Delyan Kratunov
2022-03-15 18:07         ` Andrii Nakryiko
2022-03-15 18:07       ` Andrii Nakryiko
2022-03-11  0:12 ` [PATCH bpf-next v2 5/5] selftests/bpf: test subskeleton functionality Delyan Kratunov
2022-03-11 23:40   ` Andrii Nakryiko
2022-03-14 23:50     ` Delyan Kratunov
2022-03-15 18:31       ` Andrii Nakryiko
2022-03-11  5:10 ` [PATCH bpf-next v2 0/5] Subskeleton support for BPF libraries Yonghong Song
2022-03-11 18:18   ` Delyan Kratunov
2022-03-12  0:39     ` Yonghong Song

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=e3e84d87c2a0c13ae9f20e44493c1578e06b6618.camel@fb.com \
    --to=delyank@fb.com \
    --cc=andrii.nakryiko@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    /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