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 2/4] bpftool: add support for subskeletons
Date: Thu, 3 Mar 2022 18:57:32 +0000 [thread overview]
Message-ID: <9028e60f908d30d5f156064cebfd5af8d66c5c9c.camel@fb.com> (raw)
In-Reply-To: <CAEf4BzZzAToLHESKrddn2y1FoLHHUVGzJe7=1ih0E3EA7BBdHg@mail.gmail.com>
Thanks Andrii for taking a thorough look!
On Wed, 2022-03-02 at 17:46 -0800, Andrii Nakryiko wrote:
> There is a need (I needed it in libusdt, for example). Let's add it
> from the very beginning, especially that it can be done in *exactly*
> the same form as for skeletons.
Absolutely, I'll get that into the next version!
> seems like subskel's datasec codegen is considerably different (and
> simpler, really) than skeleton's, I'd add a separate function for it
> instead of all this if (subskel) special-casing. Main concern for
> skeleton is generating correct memory layout, while for subskel we
> just need to generate a list of pointers without any regard to memory
> layout.
I'm not 100% convinced given how much code would end up being duplicated but I
can go in that direction, if you'd prefer it.
>
> it's unfortunate to have to modify original BTF just to have this '*'
> added. If I remember correctly, C syntax for pointers has special
> case only for arrays and func prototypes, so it should work with this
> logic (not tested, obviously)
>
> 1. if top variable type is array or func_proto, set var_ident to "(*<variable>)"
> 2. otherwise set var_ident to "*<variable>"
>
> we'd need to test it for array and func_proto, but it definitely
> should work for all other cases
A couple of thoughts here:
1. We are not modifing the original BTF, we are layering in-memory-only types on
top of it. This ends up working transparently through btf_dump code, which is
the source of truth of what "correct" is. I think this is strictly better than
the alternative textual modifications to var_ident.
2. I guess we see the change differently - to me it's not just about adding an
asterisk but instead working with derivative types. This might come in handy in
other contexts that we haven't envisioned yet and I feel is a direction worth
supporting overall.
3. We have a full type system with layering and mixed file- and memory-based
storage. Why limit ourselves to templating instead of using it in the codegen?
If I were writing this from scratch, much of codegen_datasecs would instead
create in-memory BTF types and have btf_dump emit them (but that's not the
bikeshed I want to paint here!).
> > + char header_guard[MAX_OBJ_NAME_LEN + sizeof("__SKEL_H__")];
>
> use __SUBSKEL_H__ here?
Sure, I can introduce the .subskel.h suffix everywhere.
>
> > + strncpy(obj_name, *argv, MAX_OBJ_NAME_LEN - 1);
> > + obj_name[MAX_OBJ_NAME_LEN - 1] = '\0';
>
> we should probably force obj_name to be an empty string, so that all
> map names match their proper section names
Ah, maybe this is why bpf_map__name was not doing the right thing before. I
don't really like that we're relying on side effects of the empty obj_name but
I'll try it and see if anything breaks (the templating for one will need it
anyway).
>
> > + if (verifier_logs)
> > + /* log_level1 + log_level2 + stats, but not stable UAPI */
> > + opts.kernel_log_level = 1 + 2 + 4;
>
> hm.. we shouldn't need this, we are not loading anything into kernel
> and don't use light skeleton
You're right, will remove.
>
> > + obj = bpf_object__open_mem(obj_data, file_sz, &opts);
> > + err = libbpf_get_error(obj);
>
> no need for libbpf_get_error() anymore, bpftool is in libbpf 1.0 mode,
> so it will get NULL on error and error itself will be in errno
Ah, yes, I won't add new callsites.
>
> >
> > + map_type_id = btf__find_by_name_kind(btf, bpf_map__section_name(map), BTF_KIND_DATASEC);
>
> if we set obj_name to "", bpf_map__name() should return ELF section
> name here, so no need to expose this as an API
>
>
> oh, but also bpf_map__btf_value_type_id() should give you this ID directly
TIL, that's not obvious at all. There's a few places in gen.c that could be
simplified then - find_type_for_map goes through slicing the complete name and
walking over every BTF type to match on the slice. Is there some compatibility
reason to do that or is btf_value_type_id always there?
>
> > + for (i = 0, var = btf_var_secinfos(map_type), len = btf_vlen(map_type);
> > + i < len;
> > + i++, var++) {
>
> nit: move those long one-time assignments out of the for() loop and
> keep it single-line?
Yeah, I hate that structure too, I'll clean it up.
>
> >
> > + if (!subskel) { \n\
> > + errno = ENOMEM; \n\
> > + return NULL; \n\
>
> leaking obj here
Yeah, I noticed that I didn't use __destroy in the subskel, will fix for v2.
> > + /* walk through each symbol and emit the runtime representation
> > + */
>
> nit: keep this comment single-lined?
I did initially and checkpatch scolded me :)
>
> > + bpf_object__for_each_map(map, obj) {
> > + if (!bpf_map__is_internal(map))
> > + continue;
> > +
> > + if (!(bpf_map__map_flags(map) & BPF_F_MMAPABLE))
> > + continue;
> > +
> > + if (!get_map_ident(map, ident, sizeof(ident)))
> > + continue;
>
> this sequence of ifs seems so frequently repeated that it's probably
> time to add a helper function?
It is and it's annoying me too. I'll look at the whole iteration pattern more
closely.
>
>
> > + codegen("\
> > + \n\
> > + syms[%4$d].name = \"%1$s\"; \n\
> > + syms[%4$d].section = \"%3$s\"; \n\
> > + syms[%4$d].addr = (void**) &obj->%2$s.%1$s; \n\
> > + ", var_ident, ident, bpf_map__section_name(map), sym_idx);
> > + }
> > + }
>
> why not assign subskel->sym_cnt here using sym_idx and avoid that
> extra loop over all variables above?
Good call, will do.
>
> Quentin will remind you that you should also update the man page and
> bash completion script :)
Ah, yes, glad to see it's rst and I don't have to suffer groff/mdoc flashbacks!
Thanks,
Delyan
next prev parent reply other threads:[~2022-03-03 18:57 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-02 2:48 [PATCH bpf-next 0/4] Subskeleton support for BPF libraries Delyan Kratunov
2022-03-02 2:48 ` [PATCH bpf-next 3/4] libbpf: add subskeleton scaffolding Delyan Kratunov
2022-03-02 21:43 ` Daniel Borkmann
2022-03-03 0:20 ` Delyan Kratunov
2022-03-03 0:28 ` Andrii Nakryiko
2022-03-03 0:44 ` Delyan Kratunov
2022-03-03 4:33 ` Andrii Nakryiko
2022-03-03 4:34 ` Andrii Nakryiko
2022-03-03 19:09 ` Delyan Kratunov
2022-03-04 19:40 ` Andrii Nakryiko
2022-03-02 2:48 ` [PATCH bpf-next 4/4] selftests/bpf: test subskeleton functionality Delyan Kratunov
2022-03-02 22:30 ` Alexei Starovoitov
2022-03-03 0:06 ` Delyan Kratunov
2022-03-03 4:58 ` Andrii Nakryiko
2022-03-02 2:48 ` [PATCH bpf-next 1/4] libbpf: expose map elf section name Delyan Kratunov
2022-03-03 1:13 ` Andrii Nakryiko
2022-03-03 18:19 ` Delyan Kratunov
2022-03-02 2:48 ` [PATCH bpf-next 2/4] bpftool: add support for subskeletons Delyan Kratunov
2022-03-03 1:46 ` Andrii Nakryiko
2022-03-03 18:57 ` Delyan Kratunov [this message]
2022-03-03 20:54 ` Delyan Kratunov
2022-03-04 19:29 ` Andrii Nakryiko
2022-03-04 19:29 ` Andrii Nakryiko
2022-03-10 0:09 ` Delyan Kratunov
2022-03-10 0:38 ` 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=9028e60f908d30d5f156064cebfd5af8d66c5c9c.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;
as well as URLs for NNTP newsgroup(s).