bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Andrii Nakryiko <andrii.nakryiko@gmail.com>
To: John Fastabend <john.fastabend@gmail.com>
Cc: Andrii Nakryiko <andriin@fb.com>, bpf <bpf@vger.kernel.org>,
	Networking <netdev@vger.kernel.org>,
	Alexei Starovoitov <ast@fb.com>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Kernel Team <kernel-team@fb.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: Re: [PATCH bpf-next 5/9] libbpf: allow modification of BTF and add btf__add_str API
Date: Thu, 24 Sep 2020 13:27:22 -0700	[thread overview]
Message-ID: <CAEf4Bzaiz9SCH1JFBK8zou=GHwZwEiDfUxKhtWzUv2t=4jYfkQ@mail.gmail.com> (raw)
In-Reply-To: <5f6cc1a188bdf_4939c208e1@john-XPS-13-9370.notmuch>

On Thu, Sep 24, 2020 at 8:56 AM John Fastabend <john.fastabend@gmail.com> wrote:
>
> Andrii Nakryiko wrote:
> > Allow internal BTF representation to switch from default read-only mode, in
> > which raw BTF data is a single non-modifiable block of memory with BTF header,
> > types, and strings layed out sequentially and contiguously in memory, into
> > a writable representation with types and strings data split out into separate
> > memory regions, that can be dynamically expanded.
> >
> > Such writable internal representation is transparent to users of libbpf APIs,
> > but allows to append new types and strings at the end of BTF, which is
> > a typical use case when generating BTF programmatically. All the basic
> > guarantees of BTF types and strings layout is preserved, i.e., user can get
> > `struct btf_type *` pointer and read it directly. Such btf_type pointers might
> > be invalidated if BTF is modified, so some care is required in such mixed
> > read/write scenarios.
> >
> > Switch from read-only to writable configuration happens automatically the
> > first time when user attempts to modify BTF by either adding a new type or new
> > string. It is still possible to get raw BTF data, which is a single piece of
> > memory that can be persisted in ELF section or into a file as raw BTF. Such
> > raw data memory is also still owned by BTF and will be freed either when BTF
> > object is freed or if another modification to BTF happens, as any modification
> > invalidates BTF raw representation.
> >
> > This patch adds the first BTF writing API: btf__add_str(), which allows to
> > add arbitrary strings to BTF string section. All the added strings are
> > automatically deduplicated. This is achieved by maintaining an additional
> > string lookup index for all unique strings. Such index is built when BTF is
> > switched to modifiable mode. If at that time BTF strings section contained
> > duplicate strings, they are not de-duplicated. This is done specifically to
> > not modify the existing content of BTF (types, their string offsets, etc),
> > which can cause confusion and is especially important property if there is
> > struct btf_ext associated with struct btf. By following this "imperfect
> > deduplication" process, btf_ext is kept consitent and correct. If
> > deduplication of strings is necessary, it can be forced by doing BTF
> > deduplication, at which point all the strings will be eagerly deduplicated and
> > all string offsets both in struct btf and struct btf_ext will be updated.
> >
> > Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> > ---
>
> [...]
>
> > +/* Ensure BTF is ready to be modified (by splitting into a three memory
> > + * regions for header, types, and strings). Also invalidate cached
> > + * raw_data, if any.
> > + */
> > +static int btf_ensure_modifiable(struct btf *btf)
> > +{
> > +     void *hdr, *types, *strs, *strs_end, *s;
> > +     struct hashmap *hash = NULL;
> > +     long off;
> > +     int err;
> > +
> > +     if (btf_is_modifiable(btf)) {
> > +             /* any BTF modification invalidates raw_data */
> > +             if (btf->raw_data) {
>
> I missed why this case is needed? Just being cautious? It looks like
> we get btf->hdr != btf->raw_data (aka btf_is_modifiable) below, but
> by the tiime we do this set it looks like we will always null btf->raw_data
> as well. Again doesn't appear harmful just seeing if I missed a path.

It's because of btf__get_raw_data() (it's currently used by pahole for
BTF dedup). raw_data is cached in struct btf and is owned by it, so
when we attempt modification, we have to invalidate a single-blob
representation, as it is immediately invalid. This is mostly to
preserve existing semantics, but also not to keep allocating new
memory if caller created BTF and then accesses raw_data few times.

>
> > +                     free(btf->raw_data);
> > +                     btf->raw_data = NULL;
> > +             }
> > +             return 0;
> > +     }
> > +
> > +     /* split raw data into three memory regions */
> > +     hdr = malloc(btf->hdr->hdr_len);
> > +     types = malloc(btf->hdr->type_len);
> > +     strs = malloc(btf->hdr->str_len);
> > +     if (!hdr || !types || !strs)
> > +             goto err_out;
> > +
> > +     memcpy(hdr, btf->hdr, btf->hdr->hdr_len);
> > +     memcpy(types, btf->types_data, btf->hdr->type_len);
> > +     memcpy(strs, btf->strs_data, btf->hdr->str_len);
> > +
> > +     /* build lookup index for all strings */
> > +     hash = hashmap__new(strs_hash_fn, strs_hash_equal_fn, btf);
> > +     if (IS_ERR(hash)) {
> > +             err = PTR_ERR(hash);
> > +             hash = NULL;
> > +             goto err_out;
> > +     }
> > +
>
> [...]
>
> Thanks,
> John

  reply	other threads:[~2020-09-24 20:27 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-23 15:54 [PATCH bpf-next 0/9] libbpf: BTF writer APIs Andrii Nakryiko
2020-09-23 15:54 ` [PATCH bpf-next 1/9] libbpf: refactor internals of BTF type index Andrii Nakryiko
2020-09-23 15:54 ` [PATCH bpf-next 2/9] libbpf: remove assumption of single contiguous memory for BTF data Andrii Nakryiko
2020-09-24 15:21   ` John Fastabend
2020-09-24 20:25     ` Andrii Nakryiko
2020-09-23 15:54 ` [PATCH bpf-next 3/9] libbpf: generalize common logic for managing dynamically-sized arrays Andrii Nakryiko
2020-09-23 15:54 ` [PATCH bpf-next 4/9] libbpf: extract generic string hashing function for reuse Andrii Nakryiko
2020-09-23 15:54 ` [PATCH bpf-next 5/9] libbpf: allow modification of BTF and add btf__add_str API Andrii Nakryiko
2020-09-24 15:56   ` John Fastabend
2020-09-24 20:27     ` Andrii Nakryiko [this message]
2020-09-23 15:54 ` [PATCH bpf-next 6/9] libbpf: add btf__new_empty() to create an empty BTF object Andrii Nakryiko
2020-09-23 15:54 ` [PATCH bpf-next 7/9] libbpf: add BTF writing APIs Andrii Nakryiko
2020-09-24 15:59   ` John Fastabend
2020-09-25  3:55   ` Alexei Starovoitov
2020-09-25  6:21     ` Andrii Nakryiko
2020-09-25 15:37       ` Alexei Starovoitov
2020-09-25 16:53         ` Andrii Nakryiko
2020-09-23 15:54 ` [PATCH bpf-next 8/9] libbpf: add btf__str_by_offset() as a more generic variant of name_by_offset Andrii Nakryiko
2020-09-23 15:54 ` [PATCH bpf-next 9/9] selftests/bpf: test BTF writing APIs Andrii Nakryiko
2020-09-24 15:16 ` [PATCH bpf-next 0/9] libbpf: BTF writer APIs John Fastabend

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='CAEf4Bzaiz9SCH1JFBK8zou=GHwZwEiDfUxKhtWzUv2t=4jYfkQ@mail.gmail.com' \
    --to=andrii.nakryiko@gmail.com \
    --cc=acme@redhat.com \
    --cc=andriin@fb.com \
    --cc=ast@fb.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=john.fastabend@gmail.com \
    --cc=kernel-team@fb.com \
    --cc=netdev@vger.kernel.org \
    /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).