Re: [PATCH v5 bpf-next 5/9] libbpf: make btf_parse_elf process .BTF.base transparently

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, May 28, 2024 at 5:26 AM Alan Maguire <alan.maguire@xxxxxxxxxx> wrote:
>
> From: Eduard Zingerman <eddyz87@xxxxxxxxx>
>
> Update btf_parse_elf() to check if .BTF.base section is present.
> The logic is as follows:
>
>   if .BTF.base section exists:
>      distilled_base := btf_new(.BTF.base)
>   if distilled_base:
>      btf := btf_new(.BTF, .base_btf=distilled_base)
>      if base_btf:
>         btf_relocate(btf, base_btf)
>   else:
>      btf := btf_new(.BTF)
>   return btf
>
> In other words:
> - if .BTF.base section exists, load BTF from it and use it as a base
>   for .BTF load;
> - if base_btf is specified and .BTF.base section exist, relocate newly
>   loaded .BTF against base_btf.
>
> Signed-off-by: Eduard Zingerman <eddyz87@xxxxxxxxx>
> ---
>  tools/lib/bpf/btf.c | 151 +++++++++++++++++++++++++++++---------------
>  tools/lib/bpf/btf.h |   1 +
>  2 files changed, 102 insertions(+), 50 deletions(-)
>
> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> index cb762d7a5dd7..b57f74eedda0 100644
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c
> @@ -114,7 +114,10 @@ struct btf {
>         /* a set of unique strings */
>         struct strset *strs_set;
>         /* whether strings are already deduplicated */
> -       bool strs_deduped;
> +       unsigned strs_deduped:1;
> +
> +       /* whether base_btf should be freed in btf_free for this instance */
> +       unsigned owns_base:1;

nit: let's not do bit counting (i.e., bit fields for bool flags) on
rather big things like struct btf, which are only a few of them and
4/8 extra bytes just doesn't matter compared to all the other memory
used for actual data.

>
>         /* BTF object FD, if loaded into kernel */
>         int fd;
> @@ -969,6 +972,8 @@ void btf__free(struct btf *btf)
>         free(btf->raw_data);
>         free(btf->raw_data_swapped);
>         free(btf->type_offs);
> +       if (btf->owns_base)
> +               btf__free(btf->base_btf);
>         free(btf);
>  }
>
> @@ -1084,53 +1089,38 @@ struct btf *btf__new_split(const void *data, __u32 size, struct btf *base_btf)
>         return libbpf_ptr(btf_new(data, size, base_btf));
>  }
>
> -static struct btf *btf_parse_elf(const char *path, struct btf *base_btf,
> -                                struct btf_ext **btf_ext)
> +struct elf_sections_info {
> +       Elf_Data *btf_data;
> +       Elf_Data *btf_ext_data;
> +       Elf_Data *btf_base_data;

bikeshedding time: elf_sections_info -> btf_elf_data (or
btf_elf_secs), btf_data -> btf, btf_ext_data -> btf_ext, btf_base_data
-> btf_base ?

> +};
> +
> +static int btf_find_elf_sections(Elf *elf, const char *path, struct elf_sections_info *info)
>  {
> -       Elf_Data *btf_data = NULL, *btf_ext_data = NULL;
> -       int err = 0, fd = -1, idx = 0;
> -       struct btf *btf = NULL;
>         Elf_Scn *scn = NULL;
> -       Elf *elf = NULL;
> +       Elf_Data *data;
>         GElf_Ehdr ehdr;
>         size_t shstrndx;
> +       int idx = 0;

[...]

> +       if (!info.btf_data) {
>                 pr_warn("failed to find '%s' ELF section in %s\n", BTF_ELF_SEC, path);
>                 err = -ENODATA;
>                 goto done;
>         }
> -       btf = btf_new(btf_data->d_buf, btf_data->d_size, base_btf);
> +
> +       if (info.btf_base_data) {
> +               distilled_base_btf = btf_new(info.btf_base_data->d_buf, info.btf_base_data->d_size,
> +                                            NULL);

with the above bikeshedding suggestion, and distilled_base_btf ->
dist_base_btf, let's get it to be a less verbose single-line statement

> +               err = libbpf_get_error(distilled_base_btf);

boo to using libbpf_get_error() in new code. btf_new() is internal, so
IS_ERR()/PTR_ERR(), please

pw-bot: cr


> +               if (err) {
> +                       distilled_base_btf = NULL;
> +                       goto done;
> +               }
> +       }
> +
> +       btf = btf_new(info.btf_data->d_buf, info.btf_data->d_size,
> +                     distilled_base_btf ? distilled_base_btf : base_btf);

dist_base_btf ?: base_btf

>         err = libbpf_get_error(btf);

ditto, IS_ERR/PTR_ERR

>         if (err)
>                 goto done;
>
> +       if (distilled_base_btf && base_btf) {
> +               err = btf__relocate(btf, base_btf);
> +               if (err)
> +                       goto done;
> +               btf__free(distilled_base_btf);
> +               distilled_base_btf = NULL;
> +       }
> +
> +       if (distilled_base_btf)
> +               btf->owns_base = true;

should we reset this to false when changing base in btf__relocate()?

> +
>         switch (gelf_getclass(elf)) {
>         case ELFCLASS32:
>                 btf__set_pointer_size(btf, 4);

[...]





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux