Skip to content

Commit

Permalink
bpftool: add support for split BTF to gen min_core_btf
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
brycekahle committed Jan 18, 2024
1 parent b0e69ac commit 7ba210f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
18 changes: 17 additions & 1 deletion docs/bpftool-gen.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ SYNOPSIS

**bpftool** [*OPTIONS*] **gen** *COMMAND*

*OPTIONS* := { |COMMON_OPTIONS| | { **-L** | **--use-loader** } }
*OPTIONS* := { |COMMON_OPTIONS| | { **-L** | **--use-loader** } | { **-B** | **--base-btf** } }

*COMMAND* := { **object** | **skeleton** | **help** }

Expand Down Expand Up @@ -208,6 +208,14 @@ OPTIONS
not use the majority of the libbpf infrastructure, and does not need
libelf.

-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.

EXAMPLES
========
**$ cat example1.bpf.c**
Expand Down Expand Up @@ -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.
19 changes: 13 additions & 6 deletions src/gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1630,7 +1630,8 @@ static int do_help(int argc, char **argv)
" %1$s %2$s help\n"
"\n"
" " HELP_SPEC_OPTIONS " |\n"
" {-L|--use-loader} }\n"
" {-L|--use-loader}\n"
" {-B|--base-btf} }\n"
"",
bin_name, "gen");

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);

btf_new = btf__new_empty_split((struct btf *)base);
if (!btf_new) {
err = -errno;
goto err_out;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 7ba210f

Please sign in to comment.