447 строки
15 KiB
ReStructuredText
447 строки
15 KiB
ReStructuredText
.. SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
|
|
|
================
|
|
bpftool-gen
|
|
================
|
|
-------------------------------------------------------------------------------
|
|
tool for BPF code-generation
|
|
-------------------------------------------------------------------------------
|
|
|
|
:Manual section: 8
|
|
|
|
.. include:: substitutions.rst
|
|
|
|
SYNOPSIS
|
|
========
|
|
|
|
**bpftool** [*OPTIONS*] **gen** *COMMAND*
|
|
|
|
*OPTIONS* := { |COMMON_OPTIONS| | { **-L** | **--use-loader** } }
|
|
|
|
*COMMAND* := { **object** | **skeleton** | **help** }
|
|
|
|
GEN COMMANDS
|
|
=============
|
|
|
|
| **bpftool** **gen object** *OUTPUT_FILE* *INPUT_FILE* [*INPUT_FILE*...]
|
|
| **bpftool** **gen skeleton** *FILE* [**name** *OBJECT_NAME*]
|
|
| **bpftool** **gen subskeleton** *FILE* [**name** *OBJECT_NAME*]
|
|
| **bpftool** **gen min_core_btf** *INPUT* *OUTPUT* *OBJECT* [*OBJECT*...]
|
|
| **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 subskeleton** *FILE*
|
|
Generate BPF subskeleton C header file for a given *FILE*.
|
|
|
|
Subskeletons are similar to skeletons, except they do not own
|
|
the corresponding maps, programs, or global variables. They
|
|
require that the object file used to generate them is already
|
|
loaded into a *bpf_object* by some other means.
|
|
|
|
This functionality is useful when a library is included into a
|
|
larger BPF program. A subskeleton for the library would have
|
|
access to all objects and globals defined in it, without
|
|
having to know about the larger program.
|
|
|
|
Consequently, there are only two functions defined
|
|
for subskeletons:
|
|
|
|
- **example__open(bpf_object\*)**
|
|
Instantiates a subskeleton from an already opened (but not
|
|
necessarily loaded) **bpf_object**.
|
|
|
|
- **example__destroy()**
|
|
Frees the storage for the subskeleton but *does not* unload
|
|
any BPF programs or maps.
|
|
|
|
**bpftool** **gen min_core_btf** *INPUT* *OUTPUT* *OBJECT* [*OBJECT*...]
|
|
Generate a minimum BTF file as *OUTPUT*, derived from a given
|
|
*INPUT* BTF file, containing all needed BTF types so one, or
|
|
more, given eBPF objects CO-RE relocations may be satisfied.
|
|
|
|
When kernels aren't compiled with CONFIG_DEBUG_INFO_BTF,
|
|
libbpf, when loading an eBPF object, has to rely on external
|
|
BTF files to be able to calculate CO-RE relocations.
|
|
|
|
Usually, an external BTF file is built from existing kernel
|
|
DWARF data using pahole. It contains all the types used by
|
|
its respective kernel image and, because of that, is big.
|
|
|
|
The min_core_btf feature builds smaller BTF files, customized
|
|
to one or multiple eBPF objects, so they can be distributed
|
|
together with an eBPF CO-RE based application, turning the
|
|
application portable to different kernel versions.
|
|
|
|
Check examples bellow for more information how to use it.
|
|
|
|
**bpftool gen help**
|
|
Print short help message.
|
|
|
|
OPTIONS
|
|
=======
|
|
.. include:: common_options.rst
|
|
|
|
-L, --use-loader
|
|
For skeletons, generate a "light" skeleton (also known as "loader"
|
|
skeleton). A light skeleton contains a loader eBPF program. It does
|
|
not use the majority of the libbpf infrastructure, and does not need
|
|
libelf.
|
|
|
|
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.
|
|
|
|
min_core_btf
|
|
------------
|
|
|
|
**$ bpftool btf dump file 5.4.0-example.btf format raw**
|
|
|
|
::
|
|
|
|
[1] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
|
|
[2] CONST '(anon)' type_id=1
|
|
[3] VOLATILE '(anon)' type_id=1
|
|
[4] ARRAY '(anon)' type_id=1 index_type_id=21 nr_elems=2
|
|
[5] PTR '(anon)' type_id=8
|
|
[6] CONST '(anon)' type_id=5
|
|
[7] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=(none)
|
|
[8] CONST '(anon)' type_id=7
|
|
[9] INT 'unsigned int' size=4 bits_offset=0 nr_bits=32 encoding=(none)
|
|
<long output>
|
|
|
|
**$ bpftool btf dump file one.bpf.o format raw**
|
|
|
|
::
|
|
|
|
[1] PTR '(anon)' type_id=2
|
|
[2] STRUCT 'trace_event_raw_sys_enter' size=64 vlen=4
|
|
'ent' type_id=3 bits_offset=0
|
|
'id' type_id=7 bits_offset=64
|
|
'args' type_id=9 bits_offset=128
|
|
'__data' type_id=12 bits_offset=512
|
|
[3] STRUCT 'trace_entry' size=8 vlen=4
|
|
'type' type_id=4 bits_offset=0
|
|
'flags' type_id=5 bits_offset=16
|
|
'preempt_count' type_id=5 bits_offset=24
|
|
<long output>
|
|
|
|
**$ bpftool gen min_core_btf 5.4.0-example.btf 5.4.0-smaller.btf one.bpf.o**
|
|
|
|
**$ bpftool btf dump file 5.4.0-smaller.btf format raw**
|
|
|
|
::
|
|
|
|
[1] TYPEDEF 'pid_t' type_id=6
|
|
[2] STRUCT 'trace_event_raw_sys_enter' size=64 vlen=1
|
|
'args' type_id=4 bits_offset=128
|
|
[3] STRUCT 'task_struct' size=9216 vlen=2
|
|
'pid' type_id=1 bits_offset=17920
|
|
'real_parent' type_id=7 bits_offset=18048
|
|
[4] ARRAY '(anon)' type_id=5 index_type_id=8 nr_elems=6
|
|
[5] INT 'long unsigned int' size=8 bits_offset=0 nr_bits=64 encoding=(none)
|
|
[6] TYPEDEF '__kernel_pid_t' type_id=8
|
|
[7] PTR '(anon)' type_id=3
|
|
[8] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
|
|
<end>
|
|
|
|
Now, the "5.4.0-smaller.btf" file may be used by libbpf as an external BTF file
|
|
when loading the "one.bpf.o" object into the "5.4.0-example" kernel. Note that
|
|
the generated BTF file won't allow other eBPF objects to be loaded, just the
|
|
ones given to min_core_btf.
|
|
|
|
::
|
|
|
|
LIBBPF_OPTS(bpf_object_open_opts, opts, .btf_custom_path = "5.4.0-smaller.btf");
|
|
struct bpf_object *obj;
|
|
|
|
obj = bpf_object__open_file("one.bpf.o", &opts);
|
|
|
|
...
|