提交 fb6946b0 编写于 作者: A Andrii Nakryiko 提交者: Zheng Zengkai

bpftool: Add `gen object` command to perform BPF static linking

mainline inclusion
from mainline-5.13-rc1
commit d80b2fcb
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I5EUVD
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d80b2fcbe0a023619e0fc73112f2a02c2662f6ab

-------------------------------------------------

Add `bpftool gen object <output-file> <input_file>...` command to statically
link multiple BPF ELF object files into a single output BPF ELF object file.

This patch also updates bash completions and man page. Man page gets a short
section on `gen object` command, but also updates the skeleton example to show
off workflow for BPF application with two .bpf.c files, compiled individually
with Clang, then resulting object files are linked together with `gen object`,
and then final object file is used to generate usable BPF skeleton. This
should help new users understand realistic workflow w.r.t. compiling
mutli-file BPF application.
Signed-off-by: NAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: NAlexei Starovoitov <ast@kernel.org>
Reviewed-by: NQuentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20210318194036.3521577-10-andrii@kernel.org
(cherry picked from commit d80b2fcb)
Signed-off-by: NWang Yufen <wangyufen@huawei.com>
上级 6adf7bc3
...@@ -14,16 +14,37 @@ SYNOPSIS ...@@ -14,16 +14,37 @@ SYNOPSIS
*OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] } *OPTIONS* := { { **-j** | **--json** } [{ **-p** | **--pretty** }] }
*COMMAND* := { **skeleton** | **help** } *COMMAND* := { **object** | **skeleton** | **help** }
GEN COMMANDS GEN COMMANDS
============= =============
| **bpftool** **gen object** *OUTPUT_FILE* *INPUT_FILE* [*INPUT_FILE*...]
| **bpftool** **gen skeleton** *FILE* [**name** *OBJECT_NAME*] | **bpftool** **gen skeleton** *FILE* [**name** *OBJECT_NAME*]
| **bpftool** **gen help** | **bpftool** **gen help**
DESCRIPTION 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* **bpftool gen skeleton** *FILE*
Generate BPF skeleton C header file for a given *FILE*. Generate BPF skeleton C header file for a given *FILE*.
...@@ -133,26 +154,19 @@ OPTIONS ...@@ -133,26 +154,19 @@ OPTIONS
EXAMPLES EXAMPLES
======== ========
**$ cat example.c** **$ cat example1.bpf.c**
:: ::
#include <stdbool.h> #include <stdbool.h>
#include <linux/ptrace.h> #include <linux/ptrace.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include "bpf_helpers.h" #include <bpf/bpf_helpers.h>
const volatile int param1 = 42; const volatile int param1 = 42;
bool global_flag = true; bool global_flag = true;
struct { int x; } data = {}; struct { int x; } data = {};
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_enter") SEC("raw_tp/sys_enter")
int handle_sys_enter(struct pt_regs *ctx) int handle_sys_enter(struct pt_regs *ctx)
{ {
...@@ -164,6 +178,21 @@ EXAMPLES ...@@ -164,6 +178,21 @@ EXAMPLES
return 0; 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") SEC("raw_tp/sys_exit")
int handle_sys_exit(struct pt_regs *ctx) int handle_sys_exit(struct pt_regs *ctx)
{ {
...@@ -173,9 +202,17 @@ EXAMPLES ...@@ -173,9 +202,17 @@ EXAMPLES
} }
This is example BPF application with two BPF programs and a mix of BPF maps This is example BPF application with two BPF programs and a mix of BPF maps
and global variables. and global variables. Source code is split across two source code files.
**$ bpftool gen skeleton example.o** **$ 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**
:: ::
...@@ -230,7 +267,7 @@ and global variables. ...@@ -230,7 +267,7 @@ and global variables.
#endif /* __EXAMPLE_SKEL_H__ */ #endif /* __EXAMPLE_SKEL_H__ */
**$ cat example_user.c** **$ cat example.c**
:: ::
...@@ -273,7 +310,7 @@ and global variables. ...@@ -273,7 +310,7 @@ and global variables.
return err; return err;
} }
**# ./example_user** **# ./example**
:: ::
......
...@@ -981,6 +981,10 @@ _bpftool() ...@@ -981,6 +981,10 @@ _bpftool()
;; ;;
gen) gen)
case $command in case $command in
object)
_filedir
return 0
;;
skeleton) skeleton)
case $prev in case $prev in
$command) $command)
...@@ -995,7 +999,7 @@ _bpftool() ...@@ -995,7 +999,7 @@ _bpftool()
;; ;;
*) *)
[[ $prev == $object ]] && \ [[ $prev == $object ]] && \
COMPREPLY=( $( compgen -W 'skeleton help' -- "$cur" ) ) COMPREPLY=( $( compgen -W 'object skeleton help' -- "$cur" ) )
;; ;;
esac esac
;; ;;
......
...@@ -614,6 +614,47 @@ static int do_skeleton(int argc, char **argv) ...@@ -614,6 +614,47 @@ static int do_skeleton(int argc, char **argv)
return err; return err;
} }
static int do_object(int argc, char **argv)
{
struct bpf_linker *linker;
const char *output_file, *file;
int err = 0;
if (!REQ_ARGS(2)) {
usage();
return -1;
}
output_file = GET_ARG();
linker = bpf_linker__new(output_file, NULL);
if (!linker) {
p_err("failed to create BPF linker instance");
return -1;
}
while (argc) {
file = GET_ARG();
err = bpf_linker__add_file(linker, file);
if (err) {
p_err("failed to link '%s': %s (%d)", file, strerror(err), err);
goto out;
}
}
err = bpf_linker__finalize(linker);
if (err) {
p_err("failed to finalize ELF file: %s (%d)", strerror(err), err);
goto out;
}
err = 0;
out:
bpf_linker__free(linker);
return err;
}
static int do_help(int argc, char **argv) static int do_help(int argc, char **argv)
{ {
if (json_output) { if (json_output) {
...@@ -622,7 +663,8 @@ static int do_help(int argc, char **argv) ...@@ -622,7 +663,8 @@ static int do_help(int argc, char **argv)
} }
fprintf(stderr, fprintf(stderr,
"Usage: %1$s %2$s skeleton FILE [name OBJECT_NAME]\n" "Usage: %1$s %2$s object OUTPUT_FILE INPUT_FILE [INPUT_FILE...]\n"
" %1$s %2$s skeleton FILE [name OBJECT_NAME]\n"
" %1$s %2$s help\n" " %1$s %2$s help\n"
"\n" "\n"
" " HELP_SPEC_OPTIONS "\n" " " HELP_SPEC_OPTIONS "\n"
...@@ -633,6 +675,7 @@ static int do_help(int argc, char **argv) ...@@ -633,6 +675,7 @@ static int do_help(int argc, char **argv)
} }
static const struct cmd cmds[] = { static const struct cmd cmds[] = {
{ "object", do_object },
{ "skeleton", do_skeleton }, { "skeleton", do_skeleton },
{ "help", do_help }, { "help", do_help },
{ 0 } { 0 }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册