Re: [PATCH bpf-next v3] bpftool: add support for split BTF to gen min_core_btf

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

 



On Fri, Jan 26, 2024 at 2:04 PM Bryce Kahle <git@xxxxxxxxxxxxxx> wrote:
>
> From: Bryce Kahle <bryce.kahle@xxxxxxxxxxxxx>
>
> Enables a user to generate minimized kernel module BTF.
>
> If an eBPF program probes a function within a kernel module or uses
> types that come from a kernel module, split BTF is required. The split
> module BTF contains only the BTF types that are unique to the module.
> It will reference the base/vmlinux BTF types and always starts its type
> IDs at X+1 where X is the largest type ID in the base BTF.
>
> Minimization allows a user to ship only the types necessary to do
> relocations for the program(s) in the provided eBPF object file(s). A
> minimized module BTF will still not contain vmlinux BTF types, so you
> should always minimize the vmlinux file first, and then minimize the
> kernel module file.
>
> Example:
>
> bpftool gen min_core_btf vmlinux.btf vm-min.btf prog.bpf.o
> bpftool -B vm-min.btf gen min_core_btf mod.btf mod-min.btf prog.bpf.o
>
> Signed-off-by: Bryce Kahle <bryce.kahle@xxxxxxxxxxxxx>
> ---
>  .../bpf/bpftool/Documentation/bpftool-gen.rst  | 18 +++++++++++++++++-
>  tools/bpf/bpftool/gen.c                        | 17 ++++++++++++-----
>  2 files changed, 29 insertions(+), 6 deletions(-)
>
> diff --git a/tools/bpf/bpftool/Documentation/bpftool-gen.rst b/tools/bpf/bpftool/Documentation/bpftool-gen.rst
> index 5006e724d..e067d3b05 100644
> --- a/tools/bpf/bpftool/Documentation/bpftool-gen.rst
> +++ b/tools/bpf/bpftool/Documentation/bpftool-gen.rst
> @@ -16,7 +16,7 @@ SYNOPSIS
>
>         **bpftool** [*OPTIONS*] **gen** *COMMAND*
>
> -       *OPTIONS* := { |COMMON_OPTIONS| | { **-L** | **--use-loader** } }
> +       *OPTIONS* := { |COMMON_OPTIONS| | { **-B** | **--base-btf** } | { **-L** | **--use-loader** } }
>
>         *COMMAND* := { **object** | **skeleton** | **help** }
>
> @@ -202,6 +202,14 @@ OPTIONS
>  =======
>         .. include:: common_options.rst
>
> +       -B, --base-btf *FILE*
> +                 Pass a base BTF object. Base BTF objects are typically used
> +                 with BTF objects for kernel modules. To avoid duplicating
> +                 all kernel symbols required by modules, BTF objects for
> +                 modules are "split", they are built incrementally on top of
> +                 the kernel (vmlinux) BTF object. So the base BTF reference
> +                 should usually point to the kernel BTF.
> +
>         -L, --use-loader
>                   For skeletons, generate a "light" skeleton (also known as "loader"
>                   skeleton). A light skeleton contains a loader eBPF program. It does
> @@ -444,3 +452,11 @@ ones given to min_core_btf.
>    obj = bpf_object__open_file("one.bpf.o", &opts);
>
>    ...
> +
> +Kernel module BTF may also be minimized by using the -B option:
> +
> +**$ bpftool -B 5.4.0-smaller.btf gen min_core_btf 5.4.0-module.btf 5.4.0-module-smaller.btf one.bpf.o**
> +
> +A minimized module BTF will still not contain vmlinux BTF types, so you
> +should always minimize the vmlinux file first, and then minimize the
> +kernel module file.
> diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
> index ee3ce2b80..634c809a5 100644
> --- a/tools/bpf/bpftool/gen.c
> +++ b/tools/bpf/bpftool/gen.c
> @@ -1630,6 +1630,7 @@ static int do_help(int argc, char **argv)
>                 "       %1$s %2$s help\n"
>                 "\n"
>                 "       " HELP_SPEC_OPTIONS " |\n"
> +               "                    {-B|--base-btf} |\n"
>                 "                    {-L|--use-loader} }\n"
>                 "",
>                 bin_name, "gen");
> @@ -1695,14 +1696,14 @@ btfgen_new_info(const char *targ_btf_path)
>         if (!info)
>                 return NULL;
>
> -       info->src_btf = btf__parse(targ_btf_path, NULL);
> +       info->src_btf = btf__parse_split(targ_btf_path, base_btf);
>         if (!info->src_btf) {
>                 err = -errno;
>                 p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
>                 goto err_out;
>         }
>
> -       info->marked_btf = btf__parse(targ_btf_path, NULL);
> +       info->marked_btf = btf__parse_split(targ_btf_path, base_btf);
>         if (!info->marked_btf) {
>                 err = -errno;
>                 p_err("failed parsing '%s' BTF file: %s", targ_btf_path, strerror(errno));
> @@ -2141,10 +2142,16 @@ static struct btf *btfgen_get_btf(struct btfgen_info *info)
>  {
>         struct btf *btf_new = NULL;
>         unsigned int *ids = NULL;
> +       const struct btf *base;
>         unsigned int i, n = btf__type_cnt(info->marked_btf);
> +       int start_id = 1;
>         int err = 0;
>
> -       btf_new = btf__new_empty();
> +       base = btf__base_btf(info->src_btf);
> +       if (base)
> +               start_id = btf__type_cnt(base);

stylistic nit, I'd do:

int start_id, err = 0;

and then here

start_id = base ? btf__type_cnt(base) : 1;

I'd also name base as base_btf to make it clearer that it's a btf object

> +
> +       btf_new = btf__new_empty_split((struct btf *)base);

um... and this cast didn't trigger any warnings for you? It might work
ok currently, but clearly the code expects that base_btf might be
modified, so sharing the same base_btf between two split BTF instances
is just a recipe for a hard-to-debug issues, long term.

Let's create a copy of base BTF instead? You can use btf__raw_data() +
btf__new() to make a simple clone

pw-bot: cr

>         if (!btf_new) {
>                 err = -errno;
>                 goto err_out;
> @@ -2157,7 +2164,7 @@ static struct btf *btfgen_get_btf(struct btfgen_info *info)
>         }
>
>         /* first pass: add all marked types to btf_new and add their new ids to the ids map */
> -       for (i = 1; i < n; i++) {
> +       for (i = start_id; i < n; i++) {
>                 const struct btf_type *cloned_type, *type;
>                 const char *name;
>                 int new_id;
> @@ -2213,7 +2220,7 @@ static struct btf *btfgen_get_btf(struct btfgen_info *info)
>         }
>
>         /* second pass: fix up type ids */
> -       for (i = 1; i < btf__type_cnt(btf_new); i++) {
> +       for (i = start_id; i < btf__type_cnt(btf_new); i++) {
>                 struct btf_type *btf_type = (struct btf_type *) btf__type_by_id(btf_new, i);
>
>                 err = btf_type_visit_type_ids(btf_type, btfgen_remap_id, ids);
> --
> 2.25.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