| ================ |
| bpftool-gen |
| ================ |
| ------------------------------------------------------------------------------- |
| tool for BPF code-generation |
| ------------------------------------------------------------------------------- |
| |
| :Manual section: 8 |
| |
| SYNOPSIS |
| ======== |
| |
| **bpftool** [*OPTIONS*] **gen** *COMMAND* |
| |
| *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] } |
| |
| *COMMAND* := { **object** | **skeleton** | **help** } |
| |
| GEN COMMANDS |
| ============= |
| |
| | **bpftool** **gen object** *OUTPUT_FILE* *INPUT_FILE* [*INPUT_FILE*...] |
| | **bpftool** **gen skeleton** *FILE* [**name** *OBJECT_NAME*] |
| | **bpftool** **gen help** |
| |
| DESCRIPTION |
| =========== |
| **bpftool gen object** *OUTPUT_FILE* *INPUT_FILE* [*INPUT_FILE*...] |
| Statically link (combine) together one or more *INPUT_FILE*'s |
| into a single resulting *OUTPUT_FILE*. All the files involved |
| are BPF ELF object files. |
| |
| The rules of BPF static linking are mostly the same as for |
| user-space object files, but in addition to combining data |
| and instruction sections, .BTF and .BTF.ext (if present in |
| any of the input files) data are combined together. .BTF |
| data is deduplicated, so all the common types across |
| *INPUT_FILE*'s will only be represented once in the resulting |
| BTF information. |
| |
| BPF static linking allows to partition BPF source code into |
| individually compiled files that are then linked into |
| a single resulting BPF object file, which can be used to |
| generated BPF skeleton (with **gen skeleton** command) or |
| passed directly into **libbpf** (using **bpf_object__open()** |
| family of APIs). |
| |
| **bpftool gen skeleton** *FILE* |
| Generate BPF skeleton C header file for a given *FILE*. |
| |
| BPF skeleton is an alternative interface to existing libbpf |
| APIs for working with BPF objects. Skeleton code is intended |
| to significantly shorten and simplify code to load and work |
| with BPF programs from userspace side. Generated code is |
| tailored to specific input BPF object *FILE*, reflecting its |
| structure by listing out available maps, program, variables, |
| etc. Skeleton eliminates the need to lookup mentioned |
| components by name. Instead, if skeleton instantiation |
| succeeds, they are populated in skeleton structure as valid |
| libbpf types (e.g., **struct bpf_map** pointer) and can be |
| passed to existing generic libbpf APIs. |
| |
| In addition to simple and reliable access to maps and |
| programs, skeleton provides a storage for BPF links (**struct |
| bpf_link**) for each BPF program within BPF object. When |
| requested, supported BPF programs will be automatically |
| attached and resulting BPF links stored for further use by |
| user in pre-allocated fields in skeleton struct. For BPF |
| programs that can't be automatically attached by libbpf, |
| user can attach them manually, but store resulting BPF link |
| in per-program link field. All such set up links will be |
| automatically destroyed on BPF skeleton destruction. This |
| eliminates the need for users to manage links manually and |
| rely on libbpf support to detach programs and free up |
| resources. |
| |
| Another facility provided by BPF skeleton is an interface to |
| global variables of all supported kinds: mutable, read-only, |
| as well as extern ones. This interface allows to pre-setup |
| initial values of variables before BPF object is loaded and |
| verified by kernel. For non-read-only variables, the same |
| interface can be used to fetch values of global variables on |
| userspace side, even if they are modified by BPF code. |
| |
| During skeleton generation, contents of source BPF object |
| *FILE* is embedded within generated code and is thus not |
| necessary to keep around. This ensures skeleton and BPF |
| object file are matching 1-to-1 and always stay in sync. |
| Generated code is dual-licensed under LGPL-2.1 and |
| BSD-2-Clause licenses. |
| |
| It is a design goal and guarantee that skeleton interfaces |
| are interoperable with generic libbpf APIs. User should |
| always be able to use skeleton API to create and load BPF |
| object, and later use libbpf APIs to keep working with |
| specific maps, programs, etc. |
| |
| As part of skeleton, few custom functions are generated. |
| Each of them is prefixed with object name. Object name can |
| either be derived from object file name, i.e., if BPF object |
| file name is **example.o**, BPF object name will be |
| **example**. Object name can be also specified explicitly |
| through **name** *OBJECT_NAME* parameter. The following |
| custom functions are provided (assuming **example** as |
| the object name): |
| |
| - **example__open** and **example__open_opts**. |
| These functions are used to instantiate skeleton. It |
| corresponds to libbpf's **bpf_object__open**\ () API. |
| **_opts** variants accepts extra **bpf_object_open_opts** |
| options. |
| |
| - **example__load**. |
| This function creates maps, loads and verifies BPF |
| programs, initializes global data maps. It corresponds to |
| libppf's **bpf_object__load**\ () API. |
| |
| - **example__open_and_load** combines **example__open** and |
| **example__load** invocations in one commonly used |
| operation. |
| |
| - **example__attach** and **example__detach** |
| This pair of functions allow to attach and detach, |
| correspondingly, already loaded BPF object. Only BPF |
| programs of types supported by libbpf for auto-attachment |
| will be auto-attached and their corresponding BPF links |
| instantiated. For other BPF programs, user can manually |
| create a BPF link and assign it to corresponding fields in |
| skeleton struct. **example__detach** will detach both |
| links created automatically, as well as those populated by |
| user manually. |
| |
| - **example__destroy** |
| Detach and unload BPF programs, free up all the resources |
| used by skeleton and BPF object. |
| |
| If BPF object has global variables, corresponding structs |
| with memory layout corresponding to global data data section |
| layout will be created. Currently supported ones are: *.data*, |
| *.bss*, *.rodata*, and *.kconfig* structs/data sections. |
| These data sections/structs can be used to set up initial |
| values of variables, if set before **example__load**. |
| Afterwards, if target kernel supports memory-mapped BPF |
| arrays, same structs can be used to fetch and update |
| (non-read-only) data from userspace, with same simplicity |
| as for BPF side. |
| |
| **bpftool gen help** |
| Print short help message. |
| |
| OPTIONS |
| ======= |
| .. include:: common_options.rst |
| |
| EXAMPLES |
| ======== |
| **$ cat example1.bpf.c** |
| |
| :: |
| |
| #include <stdbool.h> |
| #include <linux/ptrace.h> |
| #include <linux/bpf.h> |
| #include <bpf/bpf_helpers.h> |
| |
| const volatile int param1 = 42; |
| bool global_flag = true; |
| struct { int x; } data = {}; |
| |
| SEC("raw_tp/sys_enter") |
| int handle_sys_enter(struct pt_regs *ctx) |
| { |
| static long my_static_var; |
| if (global_flag) |
| my_static_var++; |
| else |
| data.x += param1; |
| return 0; |
| } |
| |
| **$ cat example2.bpf.c** |
| |
| :: |
| |
| #include <linux/ptrace.h> |
| #include <linux/bpf.h> |
| #include <bpf/bpf_helpers.h> |
| |
| struct { |
| __uint(type, BPF_MAP_TYPE_HASH); |
| __uint(max_entries, 128); |
| __type(key, int); |
| __type(value, long); |
| } my_map SEC(".maps"); |
| |
| SEC("raw_tp/sys_exit") |
| int handle_sys_exit(struct pt_regs *ctx) |
| { |
| int zero = 0; |
| bpf_map_lookup_elem(&my_map, &zero); |
| return 0; |
| } |
| |
| This is example BPF application with two BPF programs and a mix of BPF maps |
| and global variables. Source code is split across two source code files. |
| |
| **$ clang -target bpf -g example1.bpf.c -o example1.bpf.o** |
| **$ clang -target bpf -g example2.bpf.c -o example2.bpf.o** |
| **$ bpftool gen object example.bpf.o example1.bpf.o example2.bpf.o** |
| |
| This set of commands compiles *example1.bpf.c* and *example2.bpf.c* |
| individually and then statically links respective object files into the final |
| BPF ELF object file *example.bpf.o*. |
| |
| **$ bpftool gen skeleton example.bpf.o name example | tee example.skel.h** |
| |
| :: |
| |
| /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ |
| |
| /* THIS FILE IS AUTOGENERATED! */ |
| #ifndef __EXAMPLE_SKEL_H__ |
| #define __EXAMPLE_SKEL_H__ |
| |
| #include <stdlib.h> |
| #include <bpf/libbpf.h> |
| |
| struct example { |
| struct bpf_object_skeleton *skeleton; |
| struct bpf_object *obj; |
| struct { |
| struct bpf_map *rodata; |
| struct bpf_map *data; |
| struct bpf_map *bss; |
| struct bpf_map *my_map; |
| } maps; |
| struct { |
| struct bpf_program *handle_sys_enter; |
| struct bpf_program *handle_sys_exit; |
| } progs; |
| struct { |
| struct bpf_link *handle_sys_enter; |
| struct bpf_link *handle_sys_exit; |
| } links; |
| struct example__bss { |
| struct { |
| int x; |
| } data; |
| } *bss; |
| struct example__data { |
| _Bool global_flag; |
| long int handle_sys_enter_my_static_var; |
| } *data; |
| struct example__rodata { |
| int param1; |
| } *rodata; |
| }; |
| |
| static void example__destroy(struct example *obj); |
| static inline struct example *example__open_opts( |
| const struct bpf_object_open_opts *opts); |
| static inline struct example *example__open(); |
| static inline int example__load(struct example *obj); |
| static inline struct example *example__open_and_load(); |
| static inline int example__attach(struct example *obj); |
| static inline void example__detach(struct example *obj); |
| |
| #endif /* __EXAMPLE_SKEL_H__ */ |
| |
| **$ cat example.c** |
| |
| :: |
| |
| #include "example.skel.h" |
| |
| int main() |
| { |
| struct example *skel; |
| int err = 0; |
| |
| skel = example__open(); |
| if (!skel) |
| goto cleanup; |
| |
| skel->rodata->param1 = 128; |
| |
| err = example__load(skel); |
| if (err) |
| goto cleanup; |
| |
| err = example__attach(skel); |
| if (err) |
| goto cleanup; |
| |
| /* all libbpf APIs are usable */ |
| printf("my_map name: %s\n", bpf_map__name(skel->maps.my_map)); |
| printf("sys_enter prog FD: %d\n", |
| bpf_program__fd(skel->progs.handle_sys_enter)); |
| |
| /* detach and re-attach sys_exit program */ |
| bpf_link__destroy(skel->links.handle_sys_exit); |
| skel->links.handle_sys_exit = |
| bpf_program__attach(skel->progs.handle_sys_exit); |
| |
| printf("my_static_var: %ld\n", |
| skel->bss->handle_sys_enter_my_static_var); |
| |
| cleanup: |
| example__destroy(skel); |
| return err; |
| } |
| |
| **# ./example** |
| |
| :: |
| |
| my_map name: my_map |
| sys_enter prog FD: 8 |
| my_static_var: 7 |
| |
| This is a stripped-out version of skeleton generated for above example code. |