Re: [PATCH v2 bpf-next 04/13] libbpf: add btf__parse_opts() API for flexible BTF parsing

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

 



On Wed, Apr 24, 2024 at 8:48 AM Alan Maguire <alan.maguire@xxxxxxxxxx> wrote:
>
> Options cover existing parsing scenarios (ELF, raw, retrieving
> .BTF.ext) and also allow specification of the ELF section name
> containing BTF.  This will allow consumers to retrieve BTF from
> .BTF.base sections (BTF_BASE_ELF_SEC) also.
>
> Signed-off-by: Alan Maguire <alan.maguire@xxxxxxxxxx>
> ---
>  tools/lib/bpf/btf.c      | 50 ++++++++++++++++++++++++++++------------
>  tools/lib/bpf/btf.h      | 32 +++++++++++++++++++++++++
>  tools/lib/bpf/libbpf.map |  1 +
>  3 files changed, 68 insertions(+), 15 deletions(-)
>
> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> index 419cc4fa2e86..9036c1dc45d0 100644
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c
> @@ -1084,7 +1084,7 @@ 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,
> +static struct btf *btf_parse_elf(const char *path, const char *btf_sec, struct btf *base_btf,
>                                  struct btf_ext **btf_ext)
>  {
>         Elf_Data *btf_data = NULL, *btf_ext_data = NULL;
> @@ -1146,7 +1146,7 @@ static struct btf *btf_parse_elf(const char *path, struct btf *base_btf,
>                                 idx, path);
>                         goto done;
>                 }
> -               if (strcmp(name, BTF_ELF_SEC) == 0) {
> +               if (strcmp(name, btf_sec) == 0) {
>                         btf_data = elf_getdata(scn, 0);
>                         if (!btf_data) {
>                                 pr_warn("failed to get section(%d, %s) data from %s\n",
> @@ -1166,7 +1166,7 @@ static struct btf *btf_parse_elf(const char *path, struct btf *base_btf,
>         }
>
>         if (!btf_data) {
> -               pr_warn("failed to find '%s' ELF section in %s\n", BTF_ELF_SEC, path);
> +               pr_warn("failed to find '%s' ELF section in %s\n", btf_sec, path);
>                 err = -ENODATA;
>                 goto done;
>         }
> @@ -1212,12 +1212,12 @@ static struct btf *btf_parse_elf(const char *path, struct btf *base_btf,
>
>  struct btf *btf__parse_elf(const char *path, struct btf_ext **btf_ext)
>  {
> -       return libbpf_ptr(btf_parse_elf(path, NULL, btf_ext));
> +       return libbpf_ptr(btf_parse_elf(path, BTF_ELF_SEC, NULL, btf_ext));
>  }
>
>  struct btf *btf__parse_elf_split(const char *path, struct btf *base_btf)
>  {
> -       return libbpf_ptr(btf_parse_elf(path, base_btf, NULL));
> +       return libbpf_ptr(btf_parse_elf(path, BTF_ELF_SEC, base_btf, NULL));
>  }
>
>  static struct btf *btf_parse_raw(const char *path, struct btf *base_btf)
> @@ -1293,7 +1293,8 @@ struct btf *btf__parse_raw_split(const char *path, struct btf *base_btf)
>         return libbpf_ptr(btf_parse_raw(path, base_btf));
>  }
>
> -static struct btf *btf_parse(const char *path, struct btf *base_btf, struct btf_ext **btf_ext)
> +static struct btf *btf_parse(const char *path, const char *btf_elf_sec, struct btf *base_btf,
> +                            struct btf_ext **btf_ext)
>  {
>         struct btf *btf;
>         int err;
> @@ -1301,23 +1302,42 @@ static struct btf *btf_parse(const char *path, struct btf *base_btf, struct btf_
>         if (btf_ext)
>                 *btf_ext = NULL;
>
> -       btf = btf_parse_raw(path, base_btf);
> -       err = libbpf_get_error(btf);
> -       if (!err)
> -               return btf;
> -       if (err != -EPROTO)
> -               return ERR_PTR(err);
> -       return btf_parse_elf(path, base_btf, btf_ext);
> +       if (!btf_elf_sec) {
> +               btf = btf_parse_raw(path, base_btf);
> +               err = libbpf_get_error(btf);
> +               if (!err)
> +                       return btf;
> +               if (err != -EPROTO)
> +                       return ERR_PTR(err);
> +       }
> +       if (!btf_elf_sec)
> +               btf_elf_sec = BTF_ELF_SEC;
> +
> +       return btf_parse_elf(path, btf_elf_sec, base_btf, btf_ext);

nit: btf_elf_sec ?: BTF_ELF_SEC


> +}
> +
> +struct btf *btf__parse_opts(const char *path, struct btf_parse_opts *opts)
> +{
> +       struct btf *base_btf;
> +       const char *btf_sec;
> +       struct btf_ext **btf_ext;
> +
> +       if (!OPTS_VALID(opts, btf_parse_opts))
> +               return libbpf_err_ptr(-EINVAL);
> +       base_btf = OPTS_GET(opts, base_btf, NULL);
> +       btf_sec = OPTS_GET(opts, btf_sec, NULL);
> +       btf_ext = OPTS_GET(opts, btf_ext, NULL);
> +       return libbpf_ptr(btf_parse(path, btf_sec, base_btf, btf_ext));
>  }
>
>  struct btf *btf__parse(const char *path, struct btf_ext **btf_ext)
>  {
> -       return libbpf_ptr(btf_parse(path, NULL, btf_ext));
> +       return libbpf_ptr(btf_parse(path, NULL, NULL, btf_ext));
>  }
>
>  struct btf *btf__parse_split(const char *path, struct btf *base_btf)
>  {
> -       return libbpf_ptr(btf_parse(path, base_btf, NULL));
> +       return libbpf_ptr(btf_parse(path, NULL, base_btf, NULL));
>  }
>
>  static void *btf_get_raw_data(const struct btf *btf, __u32 *size, bool swap_endian);
> diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
> index 025ed28b7fe8..94dfdfdef617 100644
> --- a/tools/lib/bpf/btf.h
> +++ b/tools/lib/bpf/btf.h
> @@ -18,6 +18,7 @@ extern "C" {
>
>  #define BTF_ELF_SEC ".BTF"
>  #define BTF_EXT_ELF_SEC ".BTF.ext"
> +#define BTF_BASE_ELF_SEC ".BTF.base"

Does libbpf code itself use this? If not, let's get rid of it.

>  #define MAPS_ELF_SEC ".maps"
>
>  struct btf;
> @@ -134,6 +135,37 @@ LIBBPF_API struct btf *btf__parse_elf_split(const char *path, struct btf *base_b
>  LIBBPF_API struct btf *btf__parse_raw(const char *path);
>  LIBBPF_API struct btf *btf__parse_raw_split(const char *path, struct btf *base_btf);
>
> +struct btf_parse_opts {
> +       size_t sz;
> +       /* use base BTF to parse split BTF */
> +       struct btf *base_btf;
> +       /* retrieve optional .BTF.ext info */
> +       struct btf_ext **btf_ext;
> +       /* BTF section name */

let's mention that if not set, libbpf will default to trying to parse
data as raw BTF, and then will fallback to .BTF in ELF. If it is set
to non-NULL, we'll assume ELF and use that section to fetch BTF data.

> +       const char *btf_sec;
> +       size_t:0;

nit: size_t :0; (consistency)

> +};
> +
> +#define btf_parse_opts__last_field btf_sec
> +
> +/* @brief **btf__parse_opts()** parses BTF information from either a
> + * raw BTF file (*btf_sec* is NULL) or from the specified BTF section,
> + * also retrieving  .BTF.ext info if *btf_ext* is non-NULL.  If
> + * *base_btf* is specified, use it to parse split BTF from the
> + * specified location.
> + *
> + * @return new BTF object instance which has to be eventually freed with
> + * **btf__free()**
> + *
> + * On error, error-code-encoded-as-pointer is returned, not a NULL. To extract

this is false, we don't encode error as pointer anymore. starting from
v1.0 it's always NULL + errno.

> + * error code from such a pointer `libbpf_get_error()` should be used. If
> + * `libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS)` is enabled, NULL is
> + * returned on error instead. In both cases thread-local `errno` variable is
> + * always set to error code as well.
> + */
> +
> +LIBBPF_API struct btf *btf__parse_opts(const char *path, struct btf_parse_opts *opts);
> +
>  LIBBPF_API struct btf *btf__load_vmlinux_btf(void);
>  LIBBPF_API struct btf *btf__load_module_btf(const char *module_name, struct btf *vmlinux_btf);
>
> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> index c4d9bd7d3220..a9151e31dfa9 100644
> --- a/tools/lib/bpf/libbpf.map
> +++ b/tools/lib/bpf/libbpf.map
> @@ -421,6 +421,7 @@ LIBBPF_1.5.0 {
>         global:
>                 bpf_program__attach_sockmap;
>                 btf__distill_base;
> +               btf__parse_opts;
>                 ring__consume_n;
>                 ring_buffer__consume_n;
>  } LIBBPF_1.4.0;
> --
> 2.31.1
>





[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