bpftool-gen(8) System Manager's Manual bpftool-gen(8) (NAME) bpftool-gen - C BPF (SYNOPSIS) bpftool [OPTIONS] gen COMMAND OPTIONS := { { -j | --json } [{ -p | --pretty }] | { -d | --debug } | { -L | --use-loader } | [ { -S | --sign } {-k } -i ] } COMMAND := { object | skeleton | help } GEN (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...] () INPUT_FILE OUTPUT_FILE . BPF ELF . BPF .BTF .BTF.ext ( ) . .BTF (deduplicate) INPUT_FILE BTF . BPF BPF BPF BPF ( gen skeleton) libbpf ( bpf_object__open()) . bpftool gen skeleton FILE C BPF FILE . BPF libbpf BPF . BPF . BPF (FILE) . . libbpf ( struct bpf_map) libbpf . BPF (struct bpf_link) BPF BPF . BPF (attach) BPF . BPF libbpf BPF . BPF . libbpf . BPF : (extern). BPF . BPF . BPF (FILE) . BPF . LGPL-2.1 BSD-2-Clause . libbpf . BPF libbpf . . . BPF example.o BPF example . name OBJECT_NAME . ( example ): o example__open example__open_opts. . bpf_object__open() libbpf . _opts bpf_object_open_opts . o example__load. BPF . bpf_object__load() libbpf . o example__open_and_load example__open example__load . o example__attach example__detach. (attach) (detach) BPF . BPF libbpf BPF . BPF BPF . example__detach . o example__destroy. BPF BPF. BPF . / : / .data .bss .rodata .kconfig. / example__load . BPF ( ) BPF . bpftool gen subskeleton FILE C (subskeleton) BPF FILE . . bpf_object . BPF . . : o example__open(bpf_object*). bpf_object ( ). o example__destroy(). BPF . bpftool gen min_core_btf INPUT OUTPUT OBJECT [OBJECT...] BTF OUTPUT BTF INPUT BTF (relocations) CO-RE eBPF . CONFIG_DEBUG_INFO_BTF libbpf eBPF BTF CO-RE . BTF pahole DWARF . . min_core_btf BTF eBPF eBPF CO-RE (portable) . . bpftool gen help . (OPTIONS) -h, --help ( bpftool help). -V, --version bpftool ( bpftool version) libbpf bpftool . LLVM libbfd JIT (bpftool prog dump jited) BPF ( bpftool prog profile pid BPF ). -j, --json JSON. JSON . -p, --pretty JSON . -j . -d, --debug (debug). libbpf (verifier) . -L, --use-loader <<>> (light) ( <> ). eBPF (loader) . libbpf libelf . -S, --sign . -k -i . --use-loader . -k PEM . -i X.509 PEM DER . (EXAMPLES) $ cat example1.bpf.c #include #include #include #include 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 #include #include 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; } $ cat example3.bpf.c #include #include #include /* This header file is provided by the bpf_testmod module. */ #include "bpf_testmod.h" int test_2_result = 0; /* bpf_Testmod.ko calls this function, passing a "4" * and testmod_map->data. */ SEC("struct_ops/test_2") void BPF_PROG(test_2, int a, int b) { test_2_result = a + b; } SEC(".struct_ops") struct bpf_testmod_ops testmod_map = { .test_2 = (void *)test_2, .data = 0x1, }; BPF BPF BPF . . $ clang --target=bpf -g example1.bpf.c -o example1.bpf.o $ clang --target=bpf -g example2.bpf.c -o example2.bpf.o $ clang --target=bpf -g example3.bpf.c -o example3.bpf.o $ bpftool gen object example.bpf.o example1.bpf.o example2.bpf.o example3.bpf.o example1.bpf.c example2.bpf.c example3.bpf.c BPF ELF 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 #include 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; struct bpf_map *testmod_map; } maps; struct { struct example__testmod_map__bpf_testmod_ops { const struct bpf_program *test_1; const struct bpf_program *test_2; int data; } *testmod_map; } struct_ops; 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; int test_2_result; } *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; /* Change the value through the pointer of shadow type */ skel->struct_ops.testmod_map->data = 13; err = example__load(skel); if (err) goto cleanup; /* The result of the function test_2() */ printf("test_2_result: %d\n", skel->bss->test_2_result); 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 test_2_result: 17 my_map name: my_map sys_enter prog FD: 8 my_static_var: 7 . 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) $ 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 $ 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 <<5.4.0-smaller.btf>> libbpf BTF <> <<5.4.0-example>> . BTF eBPF 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); ... (SEE ALSO) bpf(2), bpf-helpers(7), bpftool(8), bpftool-btf(8), bpftool-cgroup(8), bpftool-feature(8), bpftool-iter(8), bpftool-link(8), bpftool-map(8), bpftool-net(8), bpftool-perf(8), bpftool-prog(8), bpftool-struct_ops(8), bpftool-token(8) bpftool-gen(8)