mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
321 lines
10 KiB
321 lines
10 KiB
================ |
|
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.
|
|
|