libbpf: detect supported kernel BTF features and sanitize BTF
Depending on used versions of libbpf, Clang, and kernel, it's possible to
have valid BPF object files with valid BTF information, that still won't
load successfully due to Clang emitting newer BTF features (e.g.,
BTF_KIND_FUNC, .BTF.ext's line_info/func_info, BTF_KIND_DATASEC, etc), that
are not yet supported by older kernel.
This patch adds detection of BTF features and sanitizes BPF object's BTF
by substituting various supported BTF kinds, which have compatible layout:
- BTF_KIND_FUNC -> BTF_KIND_TYPEDEF
- BTF_KIND_FUNC_PROTO -> BTF_KIND_ENUM
- BTF_KIND_VAR -> BTF_KIND_INT
- BTF_KIND_DATASEC -> BTF_KIND_STRUCT
Replacement is done in such a way as to preserve as much information as
possible (names, sizes, etc) where possible without violating kernel's
validation rules.
v2->v3:
- remove duplicate #defines from libbpf_util.h
v1->v2:
- add internal libbpf_internal.h w/ common stuff
- switch SK storage BTF to use new libbpf__probe_raw_btf()
Reported-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2019-05-11 05:13:15 +08:00
|
|
|
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Internal libbpf helpers.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2019 Facebook
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __LIBBPF_LIBBPF_INTERNAL_H
|
|
|
|
#define __LIBBPF_LIBBPF_INTERNAL_H
|
|
|
|
|
2020-08-19 09:36:04 +08:00
|
|
|
#include <stdlib.h>
|
2020-08-20 14:14:09 +08:00
|
|
|
#include <limits.h>
|
2021-05-25 11:59:33 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <linux/err.h>
|
libbpf: Ensure that BPF syscall fds are never 0, 1, or 2
Add a simple wrapper for passing an fd and getting a new one >= 3 if it
is one of 0, 1, or 2. There are two primary reasons to make this change:
First, libbpf relies on the assumption a certain BPF fd is never 0 (e.g.
most recently noticed in [0]). Second, Alexei pointed out in [1] that
some environments reset stdin, stdout, and stderr if they notice an
invalid fd at these numbers. To protect against both these cases, switch
all internal BPF syscall wrappers in libbpf to always return an fd >= 3.
We only need to modify the syscall wrappers and not other code that
assumes a valid fd by doing >= 0, to avoid pointless churn, and because
it is still a valid assumption. The cost paid is two additional syscalls
if fd is in range [0, 2].
[0]: e31eec77e4ab ("bpf: selftests: Fix fd cleanup in get_branch_snapshot")
[1]: https://lore.kernel.org/bpf/CAADnVQKVKY8o_3aU8Gzke443+uHa-eGoM0h7W4srChMXU1S4Bg@mail.gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Song Liu <songliubraving@fb.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211028063501.2239335-5-memxor@gmail.com
2021-10-28 14:34:57 +08:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
2021-07-21 08:08:21 +08:00
|
|
|
#include "relo_core.h"
|
2020-08-19 09:36:06 +08:00
|
|
|
|
|
|
|
/* make sure libbpf doesn't use kernel-only integer typedefs */
|
|
|
|
#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
|
|
|
|
|
|
|
|
/* prevent accidental re-addition of reallocarray() */
|
|
|
|
#pragma GCC poison reallocarray
|
|
|
|
|
2019-05-25 02:58:56 +08:00
|
|
|
#include "libbpf.h"
|
2021-04-24 02:13:34 +08:00
|
|
|
#include "btf.h"
|
2019-05-25 02:58:56 +08:00
|
|
|
|
libbpf: Add BPF static linker APIs
Introduce BPF static linker APIs to libbpf. BPF static linker allows to
perform static linking of multiple BPF object files into a single combined
resulting object file, preserving all the BPF programs, maps, global
variables, etc.
Data sections (.bss, .data, .rodata, .maps, maps, etc) with the same name are
concatenated together. Similarly, code sections are also concatenated. All the
symbols and ELF relocations are also concatenated in their respective ELF
sections and are adjusted accordingly to the new object file layout.
Static variables and functions are handled correctly as well, adjusting BPF
instructions offsets to reflect new variable/function offset within the
combined ELF section. Such relocations are referencing STT_SECTION symbols and
that stays intact.
Data sections in different files can have different alignment requirements, so
that is taken care of as well, adjusting sizes and offsets as necessary to
satisfy both old and new alignment requirements.
DWARF data sections are stripped out, currently. As well as LLLVM_ADDRSIG
section, which is ignored by libbpf in bpf_object__open() anyways. So, in
a way, BPF static linker is an analogue to `llvm-strip -g`, which is a pretty
nice property, especially if resulting .o file is then used to generate BPF
skeleton.
Original string sections are ignored and instead we construct our own set of
unique strings using libbpf-internal `struct strset` API.
To reduce the size of the patch, all the .BTF and .BTF.ext processing was
moved into a separate patch.
The high-level API consists of just 4 functions:
- bpf_linker__new() creates an instance of BPF static linker. It accepts
output filename and (currently empty) options struct;
- bpf_linker__add_file() takes input filename and appends it to the already
processed ELF data; it can be called multiple times, one for each BPF
ELF object file that needs to be linked in;
- bpf_linker__finalize() needs to be called to dump final ELF contents into
the output file, specified when bpf_linker was created; after
bpf_linker__finalize() is called, no more bpf_linker__add_file() and
bpf_linker__finalize() calls are allowed, they will return error;
- regardless of whether bpf_linker__finalize() was called or not,
bpf_linker__free() will free up all the used resources.
Currently, BPF static linker doesn't resolve cross-object file references
(extern variables and/or functions). This will be added in the follow up patch
set.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20210318194036.3521577-7-andrii@kernel.org
2021-03-19 03:40:30 +08:00
|
|
|
#ifndef EM_BPF
|
|
|
|
#define EM_BPF 247
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef R_BPF_64_64
|
|
|
|
#define R_BPF_64_64 1
|
|
|
|
#endif
|
libbpf: Add support for new llvm bpf relocations
LLVM patch https://reviews.llvm.org/D102712
narrowed the scope of existing R_BPF_64_64
and R_BPF_64_32 relocations, and added three
new relocations, R_BPF_64_ABS64, R_BPF_64_ABS32
and R_BPF_64_NODYLD32. The main motivation is
to make relocations linker friendly.
This change, unfortunately, breaks libbpf build,
and we will see errors like below:
libbpf: ELF relo #0 in section #6 has unexpected type 2 in
/home/yhs/work/bpf-next/tools/testing/selftests/bpf/bpf_tcp_nogpl.o
Error: failed to link
'/home/yhs/work/bpf-next/tools/testing/selftests/bpf/bpf_tcp_nogpl.o':
Unknown error -22 (-22)
The new relocation R_BPF_64_ABS64 is generated
and libbpf linker sanity check doesn't understand it.
Relocation section '.rel.struct_ops' at offset 0x1410 contains 1 entries:
Offset Info Type Symbol's Value Symbol's Name
0000000000000018 0000000700000002 R_BPF_64_ABS64 0000000000000000 nogpltcp_init
Look at the selftests/bpf/bpf_tcp_nogpl.c,
void BPF_STRUCT_OPS(nogpltcp_init, struct sock *sk)
{
}
SEC(".struct_ops")
struct tcp_congestion_ops bpf_nogpltcp = {
.init = (void *)nogpltcp_init,
.name = "bpf_nogpltcp",
};
The new llvm relocation scheme categorizes 'nogpltcp_init' reference
as R_BPF_64_ABS64 instead of R_BPF_64_64 which is used to specify
ld_imm64 relocation in the new scheme.
Let us fix the linker sanity checking by including
R_BPF_64_ABS64 and R_BPF_64_ABS32. There is no need to
check R_BPF_64_NODYLD32 which is used for .BTF and .BTF.ext.
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/20210522162341.3687617-1-yhs@fb.com
2021-05-23 00:23:41 +08:00
|
|
|
#ifndef R_BPF_64_ABS64
|
|
|
|
#define R_BPF_64_ABS64 2
|
|
|
|
#endif
|
|
|
|
#ifndef R_BPF_64_ABS32
|
|
|
|
#define R_BPF_64_ABS32 3
|
|
|
|
#endif
|
libbpf: Add BPF static linker APIs
Introduce BPF static linker APIs to libbpf. BPF static linker allows to
perform static linking of multiple BPF object files into a single combined
resulting object file, preserving all the BPF programs, maps, global
variables, etc.
Data sections (.bss, .data, .rodata, .maps, maps, etc) with the same name are
concatenated together. Similarly, code sections are also concatenated. All the
symbols and ELF relocations are also concatenated in their respective ELF
sections and are adjusted accordingly to the new object file layout.
Static variables and functions are handled correctly as well, adjusting BPF
instructions offsets to reflect new variable/function offset within the
combined ELF section. Such relocations are referencing STT_SECTION symbols and
that stays intact.
Data sections in different files can have different alignment requirements, so
that is taken care of as well, adjusting sizes and offsets as necessary to
satisfy both old and new alignment requirements.
DWARF data sections are stripped out, currently. As well as LLLVM_ADDRSIG
section, which is ignored by libbpf in bpf_object__open() anyways. So, in
a way, BPF static linker is an analogue to `llvm-strip -g`, which is a pretty
nice property, especially if resulting .o file is then used to generate BPF
skeleton.
Original string sections are ignored and instead we construct our own set of
unique strings using libbpf-internal `struct strset` API.
To reduce the size of the patch, all the .BTF and .BTF.ext processing was
moved into a separate patch.
The high-level API consists of just 4 functions:
- bpf_linker__new() creates an instance of BPF static linker. It accepts
output filename and (currently empty) options struct;
- bpf_linker__add_file() takes input filename and appends it to the already
processed ELF data; it can be called multiple times, one for each BPF
ELF object file that needs to be linked in;
- bpf_linker__finalize() needs to be called to dump final ELF contents into
the output file, specified when bpf_linker was created; after
bpf_linker__finalize() is called, no more bpf_linker__add_file() and
bpf_linker__finalize() calls are allowed, they will return error;
- regardless of whether bpf_linker__finalize() was called or not,
bpf_linker__free() will free up all the used resources.
Currently, BPF static linker doesn't resolve cross-object file references
(extern variables and/or functions). This will be added in the follow up patch
set.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20210318194036.3521577-7-andrii@kernel.org
2021-03-19 03:40:30 +08:00
|
|
|
#ifndef R_BPF_64_32
|
|
|
|
#define R_BPF_64_32 10
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef SHT_LLVM_ADDRSIG
|
|
|
|
#define SHT_LLVM_ADDRSIG 0x6FFF4C03
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* if libelf is old and doesn't support mmap(), fall back to read() */
|
|
|
|
#ifndef ELF_C_READ_MMAP
|
|
|
|
#define ELF_C_READ_MMAP ELF_C_READ
|
|
|
|
#endif
|
|
|
|
|
2021-05-08 23:22:12 +08:00
|
|
|
/* Older libelf all end up in this expression, for both 32 and 64 bit */
|
2021-10-21 09:43:57 +08:00
|
|
|
#ifndef ELF64_ST_VISIBILITY
|
|
|
|
#define ELF64_ST_VISIBILITY(o) ((o) & 0x03)
|
2021-05-08 23:22:12 +08:00
|
|
|
#endif
|
|
|
|
|
libbpf: detect supported kernel BTF features and sanitize BTF
Depending on used versions of libbpf, Clang, and kernel, it's possible to
have valid BPF object files with valid BTF information, that still won't
load successfully due to Clang emitting newer BTF features (e.g.,
BTF_KIND_FUNC, .BTF.ext's line_info/func_info, BTF_KIND_DATASEC, etc), that
are not yet supported by older kernel.
This patch adds detection of BTF features and sanitizes BPF object's BTF
by substituting various supported BTF kinds, which have compatible layout:
- BTF_KIND_FUNC -> BTF_KIND_TYPEDEF
- BTF_KIND_FUNC_PROTO -> BTF_KIND_ENUM
- BTF_KIND_VAR -> BTF_KIND_INT
- BTF_KIND_DATASEC -> BTF_KIND_STRUCT
Replacement is done in such a way as to preserve as much information as
possible (names, sizes, etc) where possible without violating kernel's
validation rules.
v2->v3:
- remove duplicate #defines from libbpf_util.h
v1->v2:
- add internal libbpf_internal.h w/ common stuff
- switch SK storage BTF to use new libbpf__probe_raw_btf()
Reported-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2019-05-11 05:13:15 +08:00
|
|
|
#define BTF_INFO_ENC(kind, kind_flag, vlen) \
|
|
|
|
((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
|
|
|
|
#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
|
|
|
|
#define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
|
|
|
|
((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
|
|
|
|
#define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
|
|
|
|
BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
|
|
|
|
BTF_INT_ENC(encoding, bits_offset, bits)
|
|
|
|
#define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset)
|
|
|
|
#define BTF_PARAM_ENC(name, type) (name), (type)
|
|
|
|
#define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size)
|
2021-02-27 04:22:49 +08:00
|
|
|
#define BTF_TYPE_FLOAT_ENC(name, sz) \
|
|
|
|
BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_FLOAT, 0, 0), sz)
|
2021-10-13 00:48:38 +08:00
|
|
|
#define BTF_TYPE_DECL_TAG_ENC(value, type, component_idx) \
|
|
|
|
BTF_TYPE_ENC(value, BTF_INFO_ENC(BTF_KIND_DECL_TAG, 0, 0), type), (component_idx)
|
2021-11-12 09:26:14 +08:00
|
|
|
#define BTF_TYPE_TYPE_TAG_ENC(value, type) \
|
|
|
|
BTF_TYPE_ENC(value, BTF_INFO_ENC(BTF_KIND_TYPE_TAG, 0, 0), type)
|
libbpf: detect supported kernel BTF features and sanitize BTF
Depending on used versions of libbpf, Clang, and kernel, it's possible to
have valid BPF object files with valid BTF information, that still won't
load successfully due to Clang emitting newer BTF features (e.g.,
BTF_KIND_FUNC, .BTF.ext's line_info/func_info, BTF_KIND_DATASEC, etc), that
are not yet supported by older kernel.
This patch adds detection of BTF features and sanitizes BPF object's BTF
by substituting various supported BTF kinds, which have compatible layout:
- BTF_KIND_FUNC -> BTF_KIND_TYPEDEF
- BTF_KIND_FUNC_PROTO -> BTF_KIND_ENUM
- BTF_KIND_VAR -> BTF_KIND_INT
- BTF_KIND_DATASEC -> BTF_KIND_STRUCT
Replacement is done in such a way as to preserve as much information as
possible (names, sizes, etc) where possible without violating kernel's
validation rules.
v2->v3:
- remove duplicate #defines from libbpf_util.h
v1->v2:
- add internal libbpf_internal.h w/ common stuff
- switch SK storage BTF to use new libbpf__probe_raw_btf()
Reported-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2019-05-11 05:13:15 +08:00
|
|
|
|
2020-08-19 09:36:04 +08:00
|
|
|
#ifndef likely
|
|
|
|
#define likely(x) __builtin_expect(!!(x), 1)
|
|
|
|
#endif
|
|
|
|
#ifndef unlikely
|
|
|
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
|
|
|
#endif
|
2019-06-18 03:26:50 +08:00
|
|
|
#ifndef min
|
|
|
|
# define min(x, y) ((x) < (y) ? (x) : (y))
|
|
|
|
#endif
|
|
|
|
#ifndef max
|
|
|
|
# define max(x, y) ((x) < (y) ? (y) : (x))
|
|
|
|
#endif
|
2019-08-08 05:39:50 +08:00
|
|
|
#ifndef offsetofend
|
|
|
|
# define offsetofend(TYPE, FIELD) \
|
|
|
|
(offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
|
|
|
|
#endif
|
2022-01-25 03:42:48 +08:00
|
|
|
#ifndef __alias
|
|
|
|
#define __alias(symbol) __attribute__((alias(#symbol)))
|
|
|
|
#endif
|
2019-06-18 03:26:50 +08:00
|
|
|
|
2021-09-29 00:19:42 +08:00
|
|
|
/* Check whether a string `str` has prefix `pfx`, regardless if `pfx` is
|
|
|
|
* a string literal known at compilation time or char * pointer known only at
|
|
|
|
* runtime.
|
|
|
|
*/
|
|
|
|
#define str_has_pfx(str, pfx) \
|
|
|
|
(strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0)
|
|
|
|
|
2022-04-06 19:43:49 +08:00
|
|
|
/* suffix check */
|
|
|
|
static inline bool str_has_sfx(const char *str, const char *sfx)
|
|
|
|
{
|
|
|
|
size_t str_len = strlen(str);
|
|
|
|
size_t sfx_len = strlen(sfx);
|
|
|
|
|
2022-07-19 17:53:01 +08:00
|
|
|
if (sfx_len > str_len)
|
|
|
|
return false;
|
|
|
|
return strcmp(str + str_len - sfx_len, sfx) == 0;
|
2022-04-06 19:43:49 +08:00
|
|
|
}
|
|
|
|
|
libbpf: handle symbol versioning properly for libbpf.a
bcc uses libbpf repo as a submodule. It brings in libbpf source
code and builds everything together to produce shared libraries.
With latest libbpf, I got the following errors:
/bin/ld: libbcc_bpf.so.0.10.0: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
make[2]: *** [src/cc/libbcc_bpf.so.0.10.0] Error 1
In xsk.c, we have
asm(".symver xsk_umem__create_v0_0_2, xsk_umem__create@LIBBPF_0.0.2");
asm(".symver xsk_umem__create_v0_0_4, xsk_umem__create@@LIBBPF_0.0.4");
The linker thinks the built is for LIBBPF but cannot find proper version
LIBBPF_0.0.2/4, so emit errors.
I also confirmed that using libbpf.a to produce a shared library also
has issues:
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
/bin/ld: t.so: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
-bash-4.4$
Symbol versioning does happens in commonly used libraries, e.g., elfutils
and glibc. For static libraries, for a versioned symbol, the old definitions
will be ignored, and the symbol will be an alias to the latest definition.
For example, glibc sched_setaffinity is versioned.
-bash-4.4$ readelf -s /usr/lib64/libc.so.6 | grep sched_setaffinity
756: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2.3.3
757: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_2.3.4
1800: 0000000000000000 0 FILE LOCAL DEFAULT ABS sched_setaffinity.c
4228: 00000000000e2e70 455 FUNC LOCAL DEFAULT 13 __sched_setaffinity_new
4648: 000000000013d3d0 13 FUNC LOCAL DEFAULT 13 __sched_setaffinity_old
7338: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2
7380: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_
-bash-4.4$
For static library, the definition of sched_setaffinity aliases to the new definition.
-bash-4.4$ readelf -s /usr/lib64/libc.a | grep sched_setaffinity
File: /usr/lib64/libc.a(sched_setaffinity.o)
8: 0000000000000000 455 FUNC GLOBAL DEFAULT 1 __sched_setaffinity_new
12: 0000000000000000 455 FUNC WEAK DEFAULT 1 sched_setaffinity
For both elfutils and glibc, additional macros are used to control different handling
of symbol versioning w.r.t static and shared libraries.
For elfutils, the macro is SYMBOL_VERSIONING
(https://sourceware.org/git/?p=elfutils.git;a=blob;f=lib/eu-config.h).
For glibc, the macro is SHARED
(https://sourceware.org/git/?p=glibc.git;a=blob;f=include/shlib-compat.h;hb=refs/heads/master)
This patch used SHARED as the macro name. After this patch, the libbpf.a has
-bash-4.4$ readelf -s libbpf.a | grep xsk_umem__create
372: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_4
405: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create
499: 00000000000175eb 103 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_2
-bash-4.4$
No versioned symbols for xsk_umem__create.
The libbpf.a can be used to build a shared library succesfully.
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
-bash-4.4$
Fixes: 10d30e301732 ("libbpf: add flags to umem config")
Cc: Kevin Laatz <kevin.laatz@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-01 05:02:03 +08:00
|
|
|
/* Symbol versioning is different between static and shared library.
|
|
|
|
* Properly versioned symbols are needed for shared library, but
|
|
|
|
* only the symbol of the new version is needed for static library.
|
2021-09-08 06:10:23 +08:00
|
|
|
* Starting with GNU C 10, use symver attribute instead of .symver assembler
|
|
|
|
* directive, which works better with GCC LTO builds.
|
libbpf: handle symbol versioning properly for libbpf.a
bcc uses libbpf repo as a submodule. It brings in libbpf source
code and builds everything together to produce shared libraries.
With latest libbpf, I got the following errors:
/bin/ld: libbcc_bpf.so.0.10.0: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
make[2]: *** [src/cc/libbcc_bpf.so.0.10.0] Error 1
In xsk.c, we have
asm(".symver xsk_umem__create_v0_0_2, xsk_umem__create@LIBBPF_0.0.2");
asm(".symver xsk_umem__create_v0_0_4, xsk_umem__create@@LIBBPF_0.0.4");
The linker thinks the built is for LIBBPF but cannot find proper version
LIBBPF_0.0.2/4, so emit errors.
I also confirmed that using libbpf.a to produce a shared library also
has issues:
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
/bin/ld: t.so: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
-bash-4.4$
Symbol versioning does happens in commonly used libraries, e.g., elfutils
and glibc. For static libraries, for a versioned symbol, the old definitions
will be ignored, and the symbol will be an alias to the latest definition.
For example, glibc sched_setaffinity is versioned.
-bash-4.4$ readelf -s /usr/lib64/libc.so.6 | grep sched_setaffinity
756: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2.3.3
757: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_2.3.4
1800: 0000000000000000 0 FILE LOCAL DEFAULT ABS sched_setaffinity.c
4228: 00000000000e2e70 455 FUNC LOCAL DEFAULT 13 __sched_setaffinity_new
4648: 000000000013d3d0 13 FUNC LOCAL DEFAULT 13 __sched_setaffinity_old
7338: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2
7380: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_
-bash-4.4$
For static library, the definition of sched_setaffinity aliases to the new definition.
-bash-4.4$ readelf -s /usr/lib64/libc.a | grep sched_setaffinity
File: /usr/lib64/libc.a(sched_setaffinity.o)
8: 0000000000000000 455 FUNC GLOBAL DEFAULT 1 __sched_setaffinity_new
12: 0000000000000000 455 FUNC WEAK DEFAULT 1 sched_setaffinity
For both elfutils and glibc, additional macros are used to control different handling
of symbol versioning w.r.t static and shared libraries.
For elfutils, the macro is SYMBOL_VERSIONING
(https://sourceware.org/git/?p=elfutils.git;a=blob;f=lib/eu-config.h).
For glibc, the macro is SHARED
(https://sourceware.org/git/?p=glibc.git;a=blob;f=include/shlib-compat.h;hb=refs/heads/master)
This patch used SHARED as the macro name. After this patch, the libbpf.a has
-bash-4.4$ readelf -s libbpf.a | grep xsk_umem__create
372: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_4
405: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create
499: 00000000000175eb 103 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_2
-bash-4.4$
No versioned symbols for xsk_umem__create.
The libbpf.a can be used to build a shared library succesfully.
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
-bash-4.4$
Fixes: 10d30e301732 ("libbpf: add flags to umem config")
Cc: Kevin Laatz <kevin.laatz@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-01 05:02:03 +08:00
|
|
|
*/
|
2021-09-08 06:10:23 +08:00
|
|
|
#if defined(SHARED) && defined(__GNUC__) && __GNUC__ >= 10
|
|
|
|
|
|
|
|
#define DEFAULT_VERSION(internal_name, api_name, version) \
|
|
|
|
__attribute__((symver(#api_name "@@" #version)))
|
|
|
|
#define COMPAT_VERSION(internal_name, api_name, version) \
|
|
|
|
__attribute__((symver(#api_name "@" #version)))
|
|
|
|
|
|
|
|
#elif defined(SHARED)
|
|
|
|
|
|
|
|
#define COMPAT_VERSION(internal_name, api_name, version) \
|
libbpf: handle symbol versioning properly for libbpf.a
bcc uses libbpf repo as a submodule. It brings in libbpf source
code and builds everything together to produce shared libraries.
With latest libbpf, I got the following errors:
/bin/ld: libbcc_bpf.so.0.10.0: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
make[2]: *** [src/cc/libbcc_bpf.so.0.10.0] Error 1
In xsk.c, we have
asm(".symver xsk_umem__create_v0_0_2, xsk_umem__create@LIBBPF_0.0.2");
asm(".symver xsk_umem__create_v0_0_4, xsk_umem__create@@LIBBPF_0.0.4");
The linker thinks the built is for LIBBPF but cannot find proper version
LIBBPF_0.0.2/4, so emit errors.
I also confirmed that using libbpf.a to produce a shared library also
has issues:
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
/bin/ld: t.so: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
-bash-4.4$
Symbol versioning does happens in commonly used libraries, e.g., elfutils
and glibc. For static libraries, for a versioned symbol, the old definitions
will be ignored, and the symbol will be an alias to the latest definition.
For example, glibc sched_setaffinity is versioned.
-bash-4.4$ readelf -s /usr/lib64/libc.so.6 | grep sched_setaffinity
756: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2.3.3
757: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_2.3.4
1800: 0000000000000000 0 FILE LOCAL DEFAULT ABS sched_setaffinity.c
4228: 00000000000e2e70 455 FUNC LOCAL DEFAULT 13 __sched_setaffinity_new
4648: 000000000013d3d0 13 FUNC LOCAL DEFAULT 13 __sched_setaffinity_old
7338: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2
7380: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_
-bash-4.4$
For static library, the definition of sched_setaffinity aliases to the new definition.
-bash-4.4$ readelf -s /usr/lib64/libc.a | grep sched_setaffinity
File: /usr/lib64/libc.a(sched_setaffinity.o)
8: 0000000000000000 455 FUNC GLOBAL DEFAULT 1 __sched_setaffinity_new
12: 0000000000000000 455 FUNC WEAK DEFAULT 1 sched_setaffinity
For both elfutils and glibc, additional macros are used to control different handling
of symbol versioning w.r.t static and shared libraries.
For elfutils, the macro is SYMBOL_VERSIONING
(https://sourceware.org/git/?p=elfutils.git;a=blob;f=lib/eu-config.h).
For glibc, the macro is SHARED
(https://sourceware.org/git/?p=glibc.git;a=blob;f=include/shlib-compat.h;hb=refs/heads/master)
This patch used SHARED as the macro name. After this patch, the libbpf.a has
-bash-4.4$ readelf -s libbpf.a | grep xsk_umem__create
372: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_4
405: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create
499: 00000000000175eb 103 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_2
-bash-4.4$
No versioned symbols for xsk_umem__create.
The libbpf.a can be used to build a shared library succesfully.
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
-bash-4.4$
Fixes: 10d30e301732 ("libbpf: add flags to umem config")
Cc: Kevin Laatz <kevin.laatz@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-01 05:02:03 +08:00
|
|
|
asm(".symver " #internal_name "," #api_name "@" #version);
|
2021-09-08 06:10:23 +08:00
|
|
|
#define DEFAULT_VERSION(internal_name, api_name, version) \
|
libbpf: handle symbol versioning properly for libbpf.a
bcc uses libbpf repo as a submodule. It brings in libbpf source
code and builds everything together to produce shared libraries.
With latest libbpf, I got the following errors:
/bin/ld: libbcc_bpf.so.0.10.0: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
make[2]: *** [src/cc/libbcc_bpf.so.0.10.0] Error 1
In xsk.c, we have
asm(".symver xsk_umem__create_v0_0_2, xsk_umem__create@LIBBPF_0.0.2");
asm(".symver xsk_umem__create_v0_0_4, xsk_umem__create@@LIBBPF_0.0.4");
The linker thinks the built is for LIBBPF but cannot find proper version
LIBBPF_0.0.2/4, so emit errors.
I also confirmed that using libbpf.a to produce a shared library also
has issues:
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
/bin/ld: t.so: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
-bash-4.4$
Symbol versioning does happens in commonly used libraries, e.g., elfutils
and glibc. For static libraries, for a versioned symbol, the old definitions
will be ignored, and the symbol will be an alias to the latest definition.
For example, glibc sched_setaffinity is versioned.
-bash-4.4$ readelf -s /usr/lib64/libc.so.6 | grep sched_setaffinity
756: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2.3.3
757: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_2.3.4
1800: 0000000000000000 0 FILE LOCAL DEFAULT ABS sched_setaffinity.c
4228: 00000000000e2e70 455 FUNC LOCAL DEFAULT 13 __sched_setaffinity_new
4648: 000000000013d3d0 13 FUNC LOCAL DEFAULT 13 __sched_setaffinity_old
7338: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2
7380: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_
-bash-4.4$
For static library, the definition of sched_setaffinity aliases to the new definition.
-bash-4.4$ readelf -s /usr/lib64/libc.a | grep sched_setaffinity
File: /usr/lib64/libc.a(sched_setaffinity.o)
8: 0000000000000000 455 FUNC GLOBAL DEFAULT 1 __sched_setaffinity_new
12: 0000000000000000 455 FUNC WEAK DEFAULT 1 sched_setaffinity
For both elfutils and glibc, additional macros are used to control different handling
of symbol versioning w.r.t static and shared libraries.
For elfutils, the macro is SYMBOL_VERSIONING
(https://sourceware.org/git/?p=elfutils.git;a=blob;f=lib/eu-config.h).
For glibc, the macro is SHARED
(https://sourceware.org/git/?p=glibc.git;a=blob;f=include/shlib-compat.h;hb=refs/heads/master)
This patch used SHARED as the macro name. After this patch, the libbpf.a has
-bash-4.4$ readelf -s libbpf.a | grep xsk_umem__create
372: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_4
405: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create
499: 00000000000175eb 103 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_2
-bash-4.4$
No versioned symbols for xsk_umem__create.
The libbpf.a can be used to build a shared library succesfully.
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
-bash-4.4$
Fixes: 10d30e301732 ("libbpf: add flags to umem config")
Cc: Kevin Laatz <kevin.laatz@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-01 05:02:03 +08:00
|
|
|
asm(".symver " #internal_name "," #api_name "@@" #version);
|
2021-09-08 06:10:23 +08:00
|
|
|
|
|
|
|
#else /* !SHARED */
|
|
|
|
|
|
|
|
#define COMPAT_VERSION(internal_name, api_name, version)
|
|
|
|
#define DEFAULT_VERSION(internal_name, api_name, version) \
|
libbpf: handle symbol versioning properly for libbpf.a
bcc uses libbpf repo as a submodule. It brings in libbpf source
code and builds everything together to produce shared libraries.
With latest libbpf, I got the following errors:
/bin/ld: libbcc_bpf.so.0.10.0: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
make[2]: *** [src/cc/libbcc_bpf.so.0.10.0] Error 1
In xsk.c, we have
asm(".symver xsk_umem__create_v0_0_2, xsk_umem__create@LIBBPF_0.0.2");
asm(".symver xsk_umem__create_v0_0_4, xsk_umem__create@@LIBBPF_0.0.4");
The linker thinks the built is for LIBBPF but cannot find proper version
LIBBPF_0.0.2/4, so emit errors.
I also confirmed that using libbpf.a to produce a shared library also
has issues:
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
/bin/ld: t.so: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
-bash-4.4$
Symbol versioning does happens in commonly used libraries, e.g., elfutils
and glibc. For static libraries, for a versioned symbol, the old definitions
will be ignored, and the symbol will be an alias to the latest definition.
For example, glibc sched_setaffinity is versioned.
-bash-4.4$ readelf -s /usr/lib64/libc.so.6 | grep sched_setaffinity
756: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2.3.3
757: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_2.3.4
1800: 0000000000000000 0 FILE LOCAL DEFAULT ABS sched_setaffinity.c
4228: 00000000000e2e70 455 FUNC LOCAL DEFAULT 13 __sched_setaffinity_new
4648: 000000000013d3d0 13 FUNC LOCAL DEFAULT 13 __sched_setaffinity_old
7338: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2
7380: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_
-bash-4.4$
For static library, the definition of sched_setaffinity aliases to the new definition.
-bash-4.4$ readelf -s /usr/lib64/libc.a | grep sched_setaffinity
File: /usr/lib64/libc.a(sched_setaffinity.o)
8: 0000000000000000 455 FUNC GLOBAL DEFAULT 1 __sched_setaffinity_new
12: 0000000000000000 455 FUNC WEAK DEFAULT 1 sched_setaffinity
For both elfutils and glibc, additional macros are used to control different handling
of symbol versioning w.r.t static and shared libraries.
For elfutils, the macro is SYMBOL_VERSIONING
(https://sourceware.org/git/?p=elfutils.git;a=blob;f=lib/eu-config.h).
For glibc, the macro is SHARED
(https://sourceware.org/git/?p=glibc.git;a=blob;f=include/shlib-compat.h;hb=refs/heads/master)
This patch used SHARED as the macro name. After this patch, the libbpf.a has
-bash-4.4$ readelf -s libbpf.a | grep xsk_umem__create
372: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_4
405: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create
499: 00000000000175eb 103 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_2
-bash-4.4$
No versioned symbols for xsk_umem__create.
The libbpf.a can be used to build a shared library succesfully.
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
-bash-4.4$
Fixes: 10d30e301732 ("libbpf: add flags to umem config")
Cc: Kevin Laatz <kevin.laatz@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-01 05:02:03 +08:00
|
|
|
extern typeof(internal_name) api_name \
|
|
|
|
__attribute__((alias(#internal_name)));
|
2021-09-08 06:10:23 +08:00
|
|
|
|
libbpf: handle symbol versioning properly for libbpf.a
bcc uses libbpf repo as a submodule. It brings in libbpf source
code and builds everything together to produce shared libraries.
With latest libbpf, I got the following errors:
/bin/ld: libbcc_bpf.so.0.10.0: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
make[2]: *** [src/cc/libbcc_bpf.so.0.10.0] Error 1
In xsk.c, we have
asm(".symver xsk_umem__create_v0_0_2, xsk_umem__create@LIBBPF_0.0.2");
asm(".symver xsk_umem__create_v0_0_4, xsk_umem__create@@LIBBPF_0.0.4");
The linker thinks the built is for LIBBPF but cannot find proper version
LIBBPF_0.0.2/4, so emit errors.
I also confirmed that using libbpf.a to produce a shared library also
has issues:
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
/bin/ld: t.so: version node not found for symbol xsk_umem__create@LIBBPF_0.0.2
/bin/ld: failed to set dynamic section sizes: Bad value
collect2: error: ld returned 1 exit status
-bash-4.4$
Symbol versioning does happens in commonly used libraries, e.g., elfutils
and glibc. For static libraries, for a versioned symbol, the old definitions
will be ignored, and the symbol will be an alias to the latest definition.
For example, glibc sched_setaffinity is versioned.
-bash-4.4$ readelf -s /usr/lib64/libc.so.6 | grep sched_setaffinity
756: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2.3.3
757: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_2.3.4
1800: 0000000000000000 0 FILE LOCAL DEFAULT ABS sched_setaffinity.c
4228: 00000000000e2e70 455 FUNC LOCAL DEFAULT 13 __sched_setaffinity_new
4648: 000000000013d3d0 13 FUNC LOCAL DEFAULT 13 __sched_setaffinity_old
7338: 000000000013d3d0 13 FUNC GLOBAL DEFAULT 13 sched_setaffinity@GLIBC_2
7380: 00000000000e2e70 455 FUNC GLOBAL DEFAULT 13 sched_setaffinity@@GLIBC_
-bash-4.4$
For static library, the definition of sched_setaffinity aliases to the new definition.
-bash-4.4$ readelf -s /usr/lib64/libc.a | grep sched_setaffinity
File: /usr/lib64/libc.a(sched_setaffinity.o)
8: 0000000000000000 455 FUNC GLOBAL DEFAULT 1 __sched_setaffinity_new
12: 0000000000000000 455 FUNC WEAK DEFAULT 1 sched_setaffinity
For both elfutils and glibc, additional macros are used to control different handling
of symbol versioning w.r.t static and shared libraries.
For elfutils, the macro is SYMBOL_VERSIONING
(https://sourceware.org/git/?p=elfutils.git;a=blob;f=lib/eu-config.h).
For glibc, the macro is SHARED
(https://sourceware.org/git/?p=glibc.git;a=blob;f=include/shlib-compat.h;hb=refs/heads/master)
This patch used SHARED as the macro name. After this patch, the libbpf.a has
-bash-4.4$ readelf -s libbpf.a | grep xsk_umem__create
372: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_4
405: 0000000000017145 1190 FUNC GLOBAL DEFAULT 1 xsk_umem__create
499: 00000000000175eb 103 FUNC GLOBAL DEFAULT 1 xsk_umem__create_v0_0_2
-bash-4.4$
No versioned symbols for xsk_umem__create.
The libbpf.a can be used to build a shared library succesfully.
-bash-4.4$ cat t.c
extern void *xsk_umem__create;
void * test() { return xsk_umem__create; }
-bash-4.4$ gcc -c -fPIC t.c
-bash-4.4$ gcc -shared t.o libbpf.a -o t.so
-bash-4.4$
Fixes: 10d30e301732 ("libbpf: add flags to umem config")
Cc: Kevin Laatz <kevin.laatz@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-01 05:02:03 +08:00
|
|
|
#endif
|
|
|
|
|
2019-05-16 11:39:27 +08:00
|
|
|
extern void libbpf_print(enum libbpf_print_level level,
|
|
|
|
const char *format, ...)
|
|
|
|
__attribute__((format(printf, 2, 3)));
|
|
|
|
|
|
|
|
#define __pr(level, fmt, ...) \
|
|
|
|
do { \
|
|
|
|
libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__); \
|
|
|
|
} while (0)
|
|
|
|
|
2019-10-21 13:55:32 +08:00
|
|
|
#define pr_warn(fmt, ...) __pr(LIBBPF_WARN, fmt, ##__VA_ARGS__)
|
2019-05-16 11:39:27 +08:00
|
|
|
#define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
|
|
|
|
#define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
|
|
|
|
|
2020-08-20 14:14:09 +08:00
|
|
|
#ifndef __has_builtin
|
|
|
|
#define __has_builtin(x) 0
|
|
|
|
#endif
|
libbpf: Wire up USDT API and bpf_link integration
Wire up libbpf USDT support APIs without yet implementing all the
nitty-gritty details of USDT discovery, spec parsing, and BPF map
initialization.
User-visible user-space API is simple and is conceptually very similar
to uprobe API.
bpf_program__attach_usdt() API allows to programmatically attach given
BPF program to a USDT, specified through binary path (executable or
shared lib), USDT provider and name. Also, just like in uprobe case, PID
filter is specified (0 - self, -1 - any process, or specific PID).
Optionally, USDT cookie value can be specified. Such single API
invocation will try to discover given USDT in specified binary and will
use (potentially many) BPF uprobes to attach this program in correct
locations.
Just like any bpf_program__attach_xxx() APIs, bpf_link is returned that
represents this attachment. It is a virtual BPF link that doesn't have
direct kernel object, as it can consist of multiple underlying BPF
uprobe links. As such, attachment is not atomic operation and there can
be brief moment when some USDT call sites are attached while others are
still in the process of attaching. This should be taken into
consideration by user. But bpf_program__attach_usdt() guarantees that
in the case of success all USDT call sites are successfully attached, or
all the successfuly attachments will be detached as soon as some USDT
call sites failed to be attached. So, in theory, there could be cases of
failed bpf_program__attach_usdt() call which did trigger few USDT
program invocations. This is unavoidable due to multi-uprobe nature of
USDT and has to be handled by user, if it's important to create an
illusion of atomicity.
USDT BPF programs themselves are marked in BPF source code as either
SEC("usdt"), in which case they won't be auto-attached through
skeleton's <skel>__attach() method, or it can have a full definition,
which follows the spirit of fully-specified uprobes:
SEC("usdt/<path>:<provider>:<name>"). In the latter case skeleton's
attach method will attempt auto-attachment. Similarly, generic
bpf_program__attach() will have enought information to go off of for
parameterless attachment.
USDT BPF programs are actually uprobes, and as such for kernel they are
marked as BPF_PROG_TYPE_KPROBE.
Another part of this patch is USDT-related feature probing:
- BPF cookie support detection from user-space;
- detection of kernel support for auto-refcounting of USDT semaphore.
The latter is optional. If kernel doesn't support such feature and USDT
doesn't rely on USDT semaphores, no error is returned. But if libbpf
detects that USDT requires setting semaphores and kernel doesn't support
this, libbpf errors out with explicit pr_warn() message. Libbpf doesn't
support poking process's memory directly to increment semaphore value,
like BCC does on legacy kernels, due to inherent raciness and danger of
such process memory manipulation. Libbpf let's kernel take care of this
properly or gives up.
Logistically, all the extra USDT-related infrastructure of libbpf is put
into a separate usdt.c file and abstracted behind struct usdt_manager.
Each bpf_object has lazily-initialized usdt_manager pointer, which is
only instantiated if USDT programs are attempted to be attached. Closing
BPF object frees up usdt_manager resources. usdt_manager keeps track of
USDT spec ID assignment and few other small things.
Subsequent patches will fill out remaining missing pieces of USDT
initialization and setup logic.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Alan Maguire <alan.maguire@oracle.com>
Link: https://lore.kernel.org/bpf/20220404234202.331384-3-andrii@kernel.org
2022-04-05 07:41:57 +08:00
|
|
|
|
|
|
|
struct bpf_link {
|
|
|
|
int (*detach)(struct bpf_link *link);
|
|
|
|
void (*dealloc)(struct bpf_link *link);
|
|
|
|
char *pin_path; /* NULL, if not pinned */
|
|
|
|
int fd; /* hook FD, -1 if not applicable */
|
|
|
|
bool disconnected;
|
|
|
|
};
|
|
|
|
|
2020-08-19 09:36:04 +08:00
|
|
|
/*
|
|
|
|
* Re-implement glibc's reallocarray() for libbpf internal-only use.
|
|
|
|
* reallocarray(), unfortunately, is not available in all versions of glibc,
|
|
|
|
* so requires extra feature detection and using reallocarray() stub from
|
|
|
|
* <tools/libc_compat.h> and COMPAT_NEED_REALLOCARRAY. All this complicates
|
|
|
|
* build of libbpf unnecessarily and is just a maintenance burden. Instead,
|
|
|
|
* it's trivial to implement libbpf-specific internal version and use it
|
|
|
|
* throughout libbpf.
|
|
|
|
*/
|
|
|
|
static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size)
|
|
|
|
{
|
|
|
|
size_t total;
|
|
|
|
|
2020-08-20 14:14:09 +08:00
|
|
|
#if __has_builtin(__builtin_mul_overflow)
|
2020-08-19 09:36:04 +08:00
|
|
|
if (unlikely(__builtin_mul_overflow(nmemb, size, &total)))
|
|
|
|
return NULL;
|
2020-08-20 14:14:09 +08:00
|
|
|
#else
|
|
|
|
if (size == 0 || nmemb > ULONG_MAX / size)
|
|
|
|
return NULL;
|
|
|
|
total = nmemb * size;
|
|
|
|
#endif
|
2020-08-19 09:36:04 +08:00
|
|
|
return realloc(ptr, total);
|
|
|
|
}
|
|
|
|
|
2021-12-11 08:40:43 +08:00
|
|
|
/* Copy up to sz - 1 bytes from zero-terminated src string and ensure that dst
|
|
|
|
* is zero-terminated string no matter what (unless sz == 0, in which case
|
|
|
|
* it's a no-op). It's conceptually close to FreeBSD's strlcpy(), but differs
|
|
|
|
* in what is returned. Given this is internal helper, it's trivial to extend
|
|
|
|
* this, when necessary. Use this instead of strncpy inside libbpf source code.
|
|
|
|
*/
|
|
|
|
static inline void libbpf_strlcpy(char *dst, const char *src, size_t sz)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (sz == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
sz--;
|
|
|
|
for (i = 0; i < sz && src[i]; i++)
|
|
|
|
dst[i] = src[i];
|
|
|
|
dst[i] = '\0';
|
|
|
|
}
|
|
|
|
|
2021-12-23 07:10:03 +08:00
|
|
|
__u32 get_kernel_version(void);
|
|
|
|
|
2021-03-19 03:40:25 +08:00
|
|
|
struct btf;
|
|
|
|
struct btf_type;
|
|
|
|
|
2021-12-02 02:10:24 +08:00
|
|
|
struct btf_type *btf_type_by_id(const struct btf *btf, __u32 type_id);
|
2021-04-24 02:13:38 +08:00
|
|
|
const char *btf_kind_str(const struct btf_type *t);
|
|
|
|
const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id);
|
|
|
|
|
|
|
|
static inline enum btf_func_linkage btf_func_linkage(const struct btf_type *t)
|
|
|
|
{
|
|
|
|
return (enum btf_func_linkage)(int)btf_vlen(t);
|
|
|
|
}
|
2021-03-19 03:40:25 +08:00
|
|
|
|
2021-04-24 02:13:34 +08:00
|
|
|
static inline __u32 btf_type_info(int kind, int vlen, int kflag)
|
|
|
|
{
|
|
|
|
return (kflag << 31) | (kind << 24) | vlen;
|
|
|
|
}
|
|
|
|
|
2021-04-24 02:13:36 +08:00
|
|
|
enum map_def_parts {
|
|
|
|
MAP_DEF_MAP_TYPE = 0x001,
|
|
|
|
MAP_DEF_KEY_TYPE = 0x002,
|
|
|
|
MAP_DEF_KEY_SIZE = 0x004,
|
|
|
|
MAP_DEF_VALUE_TYPE = 0x008,
|
|
|
|
MAP_DEF_VALUE_SIZE = 0x010,
|
|
|
|
MAP_DEF_MAX_ENTRIES = 0x020,
|
|
|
|
MAP_DEF_MAP_FLAGS = 0x040,
|
|
|
|
MAP_DEF_NUMA_NODE = 0x080,
|
|
|
|
MAP_DEF_PINNING = 0x100,
|
|
|
|
MAP_DEF_INNER_MAP = 0x200,
|
2021-10-28 07:45:01 +08:00
|
|
|
MAP_DEF_MAP_EXTRA = 0x400,
|
2021-04-24 02:13:36 +08:00
|
|
|
|
2021-10-28 07:45:01 +08:00
|
|
|
MAP_DEF_ALL = 0x7ff, /* combination of all above */
|
2021-04-24 02:13:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct btf_map_def {
|
|
|
|
enum map_def_parts parts;
|
|
|
|
__u32 map_type;
|
|
|
|
__u32 key_type_id;
|
|
|
|
__u32 key_size;
|
|
|
|
__u32 value_type_id;
|
|
|
|
__u32 value_size;
|
|
|
|
__u32 max_entries;
|
|
|
|
__u32 map_flags;
|
|
|
|
__u32 numa_node;
|
|
|
|
__u32 pinning;
|
2021-10-28 07:45:01 +08:00
|
|
|
__u64 map_extra;
|
2021-04-24 02:13:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
int parse_btf_map_def(const char *map_name, struct btf *btf,
|
|
|
|
const struct btf_type *def_t, bool strict,
|
|
|
|
struct btf_map_def *map_def, struct btf_map_def *inner_def);
|
|
|
|
|
2021-03-19 03:40:27 +08:00
|
|
|
void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz,
|
|
|
|
size_t cur_cnt, size_t max_cnt, size_t add_cnt);
|
|
|
|
int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt);
|
2020-09-26 09:13:51 +08:00
|
|
|
|
2021-08-15 15:06:03 +08:00
|
|
|
static inline bool libbpf_is_mem_zeroed(const char *p, ssize_t len)
|
|
|
|
{
|
|
|
|
while (len > 0) {
|
|
|
|
if (*p)
|
|
|
|
return false;
|
|
|
|
p++;
|
|
|
|
len--;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
libbpf: add bpf_object__open_{file, mem} w/ extensible opts
Add new set of bpf_object__open APIs using new approach to optional
parameters extensibility allowing simpler ABI compatibility approach.
This patch demonstrates an approach to implementing libbpf APIs that
makes it easy to extend existing APIs with extra optional parameters in
such a way, that ABI compatibility is preserved without having to do
symbol versioning and generating lots of boilerplate code to handle it.
To facilitate succinct code for working with options, add OPTS_VALID,
OPTS_HAS, and OPTS_GET macros that hide all the NULL, size, and zero
checks.
Additionally, newly added libbpf APIs are encouraged to follow similar
pattern of having all mandatory parameters as formal function parameters
and always have optional (NULL-able) xxx_opts struct, which should
always have real struct size as a first field and the rest would be
optional parameters added over time, which tune the behavior of existing
API, if specified by user.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-05 06:40:35 +08:00
|
|
|
static inline bool libbpf_validate_opts(const char *opts,
|
|
|
|
size_t opts_sz, size_t user_sz,
|
|
|
|
const char *type_name)
|
|
|
|
{
|
|
|
|
if (user_sz < sizeof(size_t)) {
|
2019-10-21 13:55:32 +08:00
|
|
|
pr_warn("%s size (%zu) is too small\n", type_name, user_sz);
|
libbpf: add bpf_object__open_{file, mem} w/ extensible opts
Add new set of bpf_object__open APIs using new approach to optional
parameters extensibility allowing simpler ABI compatibility approach.
This patch demonstrates an approach to implementing libbpf APIs that
makes it easy to extend existing APIs with extra optional parameters in
such a way, that ABI compatibility is preserved without having to do
symbol versioning and generating lots of boilerplate code to handle it.
To facilitate succinct code for working with options, add OPTS_VALID,
OPTS_HAS, and OPTS_GET macros that hide all the NULL, size, and zero
checks.
Additionally, newly added libbpf APIs are encouraged to follow similar
pattern of having all mandatory parameters as formal function parameters
and always have optional (NULL-able) xxx_opts struct, which should
always have real struct size as a first field and the rest would be
optional parameters added over time, which tune the behavior of existing
API, if specified by user.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-05 06:40:35 +08:00
|
|
|
return false;
|
|
|
|
}
|
2021-08-15 15:06:03 +08:00
|
|
|
if (!libbpf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) {
|
|
|
|
pr_warn("%s has non-zero extra bytes\n", type_name);
|
|
|
|
return false;
|
libbpf: add bpf_object__open_{file, mem} w/ extensible opts
Add new set of bpf_object__open APIs using new approach to optional
parameters extensibility allowing simpler ABI compatibility approach.
This patch demonstrates an approach to implementing libbpf APIs that
makes it easy to extend existing APIs with extra optional parameters in
such a way, that ABI compatibility is preserved without having to do
symbol versioning and generating lots of boilerplate code to handle it.
To facilitate succinct code for working with options, add OPTS_VALID,
OPTS_HAS, and OPTS_GET macros that hide all the NULL, size, and zero
checks.
Additionally, newly added libbpf APIs are encouraged to follow similar
pattern of having all mandatory parameters as formal function parameters
and always have optional (NULL-able) xxx_opts struct, which should
always have real struct size as a first field and the rest would be
optional parameters added over time, which tune the behavior of existing
API, if specified by user.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-05 06:40:35 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define OPTS_VALID(opts, type) \
|
|
|
|
(!(opts) || libbpf_validate_opts((const char *)opts, \
|
|
|
|
offsetofend(struct type, \
|
|
|
|
type##__last_field), \
|
|
|
|
(opts)->sz, #type))
|
|
|
|
#define OPTS_HAS(opts, field) \
|
|
|
|
((opts) && opts->sz >= offsetofend(typeof(*(opts)), field))
|
|
|
|
#define OPTS_GET(opts, field, fallback_value) \
|
|
|
|
(OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
|
2020-09-26 04:54:30 +08:00
|
|
|
#define OPTS_SET(opts, field, value) \
|
|
|
|
do { \
|
|
|
|
if (OPTS_HAS(opts, field)) \
|
|
|
|
(opts)->field = value; \
|
|
|
|
} while (0)
|
libbpf: add bpf_object__open_{file, mem} w/ extensible opts
Add new set of bpf_object__open APIs using new approach to optional
parameters extensibility allowing simpler ABI compatibility approach.
This patch demonstrates an approach to implementing libbpf APIs that
makes it easy to extend existing APIs with extra optional parameters in
such a way, that ABI compatibility is preserved without having to do
symbol versioning and generating lots of boilerplate code to handle it.
To facilitate succinct code for working with options, add OPTS_VALID,
OPTS_HAS, and OPTS_GET macros that hide all the NULL, size, and zero
checks.
Additionally, newly added libbpf APIs are encouraged to follow similar
pattern of having all mandatory parameters as formal function parameters
and always have optional (NULL-able) xxx_opts struct, which should
always have real struct size as a first field and the rest would be
optional parameters added over time, which tune the behavior of existing
API, if specified by user.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-10-05 06:40:35 +08:00
|
|
|
|
2021-08-15 15:06:03 +08:00
|
|
|
#define OPTS_ZEROED(opts, last_nonzero_field) \
|
|
|
|
({ \
|
|
|
|
ssize_t __off = offsetofend(typeof(*(opts)), last_nonzero_field); \
|
|
|
|
!(opts) || libbpf_is_mem_zeroed((const void *)opts + __off, \
|
|
|
|
(opts)->sz - __off); \
|
|
|
|
})
|
|
|
|
|
libbpf: Auto-bump RLIMIT_MEMLOCK if kernel needs it for BPF
The need to increase RLIMIT_MEMLOCK to do anything useful with BPF is
one of the first extremely frustrating gotchas that all new BPF users go
through and in some cases have to learn it a very hard way.
Luckily, starting with upstream Linux kernel version 5.11, BPF subsystem
dropped the dependency on memlock and uses memcg-based memory accounting
instead. Unfortunately, detecting memcg-based BPF memory accounting is
far from trivial (as can be evidenced by this patch), so in practice
most BPF applications still do unconditional RLIMIT_MEMLOCK increase.
As we move towards libbpf 1.0, it would be good to allow users to forget
about RLIMIT_MEMLOCK vs memcg and let libbpf do the sensible adjustment
automatically. This patch paves the way forward in this matter. Libbpf
will do feature detection of memcg-based accounting, and if detected,
will do nothing. But if the kernel is too old, just like BCC, libbpf
will automatically increase RLIMIT_MEMLOCK on behalf of user
application ([0]).
As this is technically a breaking change, during the transition period
applications have to opt into libbpf 1.0 mode by setting
LIBBPF_STRICT_AUTO_RLIMIT_MEMLOCK bit when calling
libbpf_set_strict_mode().
Libbpf allows to control the exact amount of set RLIMIT_MEMLOCK limit
with libbpf_set_memlock_rlim_max() API. Passing 0 will make libbpf do
nothing with RLIMIT_MEMLOCK. libbpf_set_memlock_rlim_max() has to be
called before the first bpf_prog_load(), bpf_btf_load(), or
bpf_object__load() call, otherwise it has no effect and will return
-EBUSY.
[0] Closes: https://github.com/libbpf/libbpf/issues/369
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20211214195904.1785155-2-andrii@kernel.org
2021-12-15 03:59:03 +08:00
|
|
|
enum kern_feature_id {
|
|
|
|
/* v4.14: kernel support for program & map names. */
|
|
|
|
FEAT_PROG_NAME,
|
|
|
|
/* v5.2: kernel support for global data sections. */
|
|
|
|
FEAT_GLOBAL_DATA,
|
|
|
|
/* BTF support */
|
|
|
|
FEAT_BTF,
|
|
|
|
/* BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO support */
|
|
|
|
FEAT_BTF_FUNC,
|
|
|
|
/* BTF_KIND_VAR and BTF_KIND_DATASEC support */
|
|
|
|
FEAT_BTF_DATASEC,
|
|
|
|
/* BTF_FUNC_GLOBAL is supported */
|
|
|
|
FEAT_BTF_GLOBAL_FUNC,
|
|
|
|
/* BPF_F_MMAPABLE is supported for arrays */
|
|
|
|
FEAT_ARRAY_MMAP,
|
|
|
|
/* kernel support for expected_attach_type in BPF_PROG_LOAD */
|
|
|
|
FEAT_EXP_ATTACH_TYPE,
|
|
|
|
/* bpf_probe_read_{kernel,user}[_str] helpers */
|
|
|
|
FEAT_PROBE_READ_KERN,
|
|
|
|
/* BPF_PROG_BIND_MAP is supported */
|
|
|
|
FEAT_PROG_BIND_MAP,
|
|
|
|
/* Kernel support for module BTFs */
|
|
|
|
FEAT_MODULE_BTF,
|
|
|
|
/* BTF_KIND_FLOAT support */
|
|
|
|
FEAT_BTF_FLOAT,
|
|
|
|
/* BPF perf link support */
|
|
|
|
FEAT_PERF_LINK,
|
|
|
|
/* BTF_KIND_DECL_TAG support */
|
|
|
|
FEAT_BTF_DECL_TAG,
|
|
|
|
/* BTF_KIND_TYPE_TAG support */
|
|
|
|
FEAT_BTF_TYPE_TAG,
|
|
|
|
/* memcg-based accounting for BPF maps and progs */
|
|
|
|
FEAT_MEMCG_ACCOUNT,
|
libbpf: Wire up USDT API and bpf_link integration
Wire up libbpf USDT support APIs without yet implementing all the
nitty-gritty details of USDT discovery, spec parsing, and BPF map
initialization.
User-visible user-space API is simple and is conceptually very similar
to uprobe API.
bpf_program__attach_usdt() API allows to programmatically attach given
BPF program to a USDT, specified through binary path (executable or
shared lib), USDT provider and name. Also, just like in uprobe case, PID
filter is specified (0 - self, -1 - any process, or specific PID).
Optionally, USDT cookie value can be specified. Such single API
invocation will try to discover given USDT in specified binary and will
use (potentially many) BPF uprobes to attach this program in correct
locations.
Just like any bpf_program__attach_xxx() APIs, bpf_link is returned that
represents this attachment. It is a virtual BPF link that doesn't have
direct kernel object, as it can consist of multiple underlying BPF
uprobe links. As such, attachment is not atomic operation and there can
be brief moment when some USDT call sites are attached while others are
still in the process of attaching. This should be taken into
consideration by user. But bpf_program__attach_usdt() guarantees that
in the case of success all USDT call sites are successfully attached, or
all the successfuly attachments will be detached as soon as some USDT
call sites failed to be attached. So, in theory, there could be cases of
failed bpf_program__attach_usdt() call which did trigger few USDT
program invocations. This is unavoidable due to multi-uprobe nature of
USDT and has to be handled by user, if it's important to create an
illusion of atomicity.
USDT BPF programs themselves are marked in BPF source code as either
SEC("usdt"), in which case they won't be auto-attached through
skeleton's <skel>__attach() method, or it can have a full definition,
which follows the spirit of fully-specified uprobes:
SEC("usdt/<path>:<provider>:<name>"). In the latter case skeleton's
attach method will attempt auto-attachment. Similarly, generic
bpf_program__attach() will have enought information to go off of for
parameterless attachment.
USDT BPF programs are actually uprobes, and as such for kernel they are
marked as BPF_PROG_TYPE_KPROBE.
Another part of this patch is USDT-related feature probing:
- BPF cookie support detection from user-space;
- detection of kernel support for auto-refcounting of USDT semaphore.
The latter is optional. If kernel doesn't support such feature and USDT
doesn't rely on USDT semaphores, no error is returned. But if libbpf
detects that USDT requires setting semaphores and kernel doesn't support
this, libbpf errors out with explicit pr_warn() message. Libbpf doesn't
support poking process's memory directly to increment semaphore value,
like BCC does on legacy kernels, due to inherent raciness and danger of
such process memory manipulation. Libbpf let's kernel take care of this
properly or gives up.
Logistically, all the extra USDT-related infrastructure of libbpf is put
into a separate usdt.c file and abstracted behind struct usdt_manager.
Each bpf_object has lazily-initialized usdt_manager pointer, which is
only instantiated if USDT programs are attempted to be attached. Closing
BPF object frees up usdt_manager resources. usdt_manager keeps track of
USDT spec ID assignment and few other small things.
Subsequent patches will fill out remaining missing pieces of USDT
initialization and setup logic.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Alan Maguire <alan.maguire@oracle.com>
Link: https://lore.kernel.org/bpf/20220404234202.331384-3-andrii@kernel.org
2022-04-05 07:41:57 +08:00
|
|
|
/* BPF cookie (bpf_get_attach_cookie() BPF helper) support */
|
|
|
|
FEAT_BPF_COOKIE,
|
2022-06-07 14:26:36 +08:00
|
|
|
/* BTF_KIND_ENUM64 support and BTF_KIND_ENUM kflag support */
|
|
|
|
FEAT_BTF_ENUM64,
|
2022-07-14 15:07:54 +08:00
|
|
|
/* Kernel uses syscall wrapper (CONFIG_ARCH_HAS_SYSCALL_WRAPPER) */
|
|
|
|
FEAT_SYSCALL_WRAPPER,
|
libbpf: Auto-bump RLIMIT_MEMLOCK if kernel needs it for BPF
The need to increase RLIMIT_MEMLOCK to do anything useful with BPF is
one of the first extremely frustrating gotchas that all new BPF users go
through and in some cases have to learn it a very hard way.
Luckily, starting with upstream Linux kernel version 5.11, BPF subsystem
dropped the dependency on memlock and uses memcg-based memory accounting
instead. Unfortunately, detecting memcg-based BPF memory accounting is
far from trivial (as can be evidenced by this patch), so in practice
most BPF applications still do unconditional RLIMIT_MEMLOCK increase.
As we move towards libbpf 1.0, it would be good to allow users to forget
about RLIMIT_MEMLOCK vs memcg and let libbpf do the sensible adjustment
automatically. This patch paves the way forward in this matter. Libbpf
will do feature detection of memcg-based accounting, and if detected,
will do nothing. But if the kernel is too old, just like BCC, libbpf
will automatically increase RLIMIT_MEMLOCK on behalf of user
application ([0]).
As this is technically a breaking change, during the transition period
applications have to opt into libbpf 1.0 mode by setting
LIBBPF_STRICT_AUTO_RLIMIT_MEMLOCK bit when calling
libbpf_set_strict_mode().
Libbpf allows to control the exact amount of set RLIMIT_MEMLOCK limit
with libbpf_set_memlock_rlim_max() API. Passing 0 will make libbpf do
nothing with RLIMIT_MEMLOCK. libbpf_set_memlock_rlim_max() has to be
called before the first bpf_prog_load(), bpf_btf_load(), or
bpf_object__load() call, otherwise it has no effect and will return
-EBUSY.
[0] Closes: https://github.com/libbpf/libbpf/issues/369
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20211214195904.1785155-2-andrii@kernel.org
2021-12-15 03:59:03 +08:00
|
|
|
__FEAT_CNT,
|
|
|
|
};
|
|
|
|
|
|
|
|
int probe_memcg_account(void);
|
|
|
|
bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id);
|
|
|
|
int bump_rlimit_memlock(void);
|
2021-08-15 15:06:03 +08:00
|
|
|
|
2019-12-12 09:35:48 +08:00
|
|
|
int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);
|
|
|
|
int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);
|
2019-05-30 02:31:09 +08:00
|
|
|
int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
|
|
|
|
const char *str_sec, size_t str_len);
|
libbpf: Allow passing preallocated log_buf when loading BTF into kernel
Add libbpf-internal btf_load_into_kernel() that allows to pass
preallocated log_buf and custom log_level to be passed into kernel
during BPF_BTF_LOAD call. When custom log_buf is provided,
btf_load_into_kernel() won't attempt an retry with automatically
allocated internal temporary buffer to capture BTF validation log.
It's important to note the relation between log_buf and log_level, which
slightly deviates from stricter kernel logic. From kernel's POV, if
log_buf is specified, log_level has to be > 0, and vice versa. While
kernel has good reasons to request such "sanity, this, in practice, is
a bit unconvenient and restrictive for libbpf's high-level bpf_object APIs.
So libbpf will allow to set non-NULL log_buf and log_level == 0. This is
fine and means to attempt to load BTF without logging requested, but if
it failes, retry the load with custom log_buf and log_level 1. Similar
logic will be implemented for program loading. In practice this means
that users can provide custom log buffer just in case error happens, but
not really request slower verbose logging all the time. This is also
consistent with libbpf behavior when custom log_buf is not set: libbpf
first tries to load everything with log_level=0, and only if error
happens allocates internal log buffer and retries with log_level=1.
Also, while at it, make BTF validation log more obvious and follow the log
pattern libbpf is using for dumping BPF verifier log during
BPF_PROG_LOAD. BTF loading resulting in an error will look like this:
libbpf: BTF loading error: -22
libbpf: -- BEGIN BTF LOAD LOG ---
magic: 0xeb9f
version: 1
flags: 0x0
hdr_len: 24
type_off: 0
type_len: 1040
str_off: 1040
str_len: 2063598257
btf_total_size: 1753
Total section length too long
-- END BTF LOAD LOG --
libbpf: Error loading .BTF into kernel: -22. BTF is optional, ignoring.
This makes it much easier to find relevant parts in libbpf log output.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20211209193840.1248570-4-andrii@kernel.org
2021-12-10 03:38:31 +08:00
|
|
|
int btf_load_into_kernel(struct btf *btf, char *log_buf, size_t log_sz, __u32 log_level);
|
libbpf: detect supported kernel BTF features and sanitize BTF
Depending on used versions of libbpf, Clang, and kernel, it's possible to
have valid BPF object files with valid BTF information, that still won't
load successfully due to Clang emitting newer BTF features (e.g.,
BTF_KIND_FUNC, .BTF.ext's line_info/func_info, BTF_KIND_DATASEC, etc), that
are not yet supported by older kernel.
This patch adds detection of BTF features and sanitizes BPF object's BTF
by substituting various supported BTF kinds, which have compatible layout:
- BTF_KIND_FUNC -> BTF_KIND_TYPEDEF
- BTF_KIND_FUNC_PROTO -> BTF_KIND_ENUM
- BTF_KIND_VAR -> BTF_KIND_INT
- BTF_KIND_DATASEC -> BTF_KIND_STRUCT
Replacement is done in such a way as to preserve as much information as
possible (names, sizes, etc) where possible without violating kernel's
validation rules.
v2->v3:
- remove duplicate #defines from libbpf_util.h
v1->v2:
- add internal libbpf_internal.h w/ common stuff
- switch SK storage BTF to use new libbpf__probe_raw_btf()
Reported-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2019-05-11 05:13:15 +08:00
|
|
|
|
2020-12-04 04:46:23 +08:00
|
|
|
struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf);
|
libbpf: Generate loader program out of BPF ELF file.
The BPF program loading process performed by libbpf is quite complex
and consists of the following steps:
"open" phase:
- parse elf file and remember relocations, sections
- collect externs and ksyms including their btf_ids in prog's BTF
- patch BTF datasec (since llvm couldn't do it)
- init maps (old style map_def, BTF based, global data map, kconfig map)
- collect relocations against progs and maps
"load" phase:
- probe kernel features
- load vmlinux BTF
- resolve externs (kconfig and ksym)
- load program BTF
- init struct_ops
- create maps
- apply CO-RE relocations
- patch ld_imm64 insns with src_reg=PSEUDO_MAP, PSEUDO_MAP_VALUE, PSEUDO_BTF_ID
- reposition subprograms and adjust call insns
- sanitize and load progs
During this process libbpf does sys_bpf() calls to load BTF, create maps,
populate maps and finally load programs.
Instead of actually doing the syscalls generate a trace of what libbpf
would have done and represent it as the "loader program".
The "loader program" consists of single map with:
- union bpf_attr(s)
- BTF bytes
- map value bytes
- insns bytes
and single bpf program that passes bpf_attr(s) and data into bpf_sys_bpf() helper.
Executing such "loader program" via bpf_prog_test_run() command will
replay the sequence of syscalls that libbpf would have done which will result
the same maps created and programs loaded as specified in the elf file.
The "loader program" removes libelf and majority of libbpf dependency from
program loading process.
kconfig, typeless ksym, struct_ops and CO-RE are not supported yet.
The order of relocate_data and relocate_calls had to change, so that
bpf_gen__prog_load() can see all relocations for a given program with
correct insn_idx-es.
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20210514003623.28033-15-alexei.starovoitov@gmail.com
2021-05-14 08:36:16 +08:00
|
|
|
void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type,
|
|
|
|
const char **prefix, int *kind);
|
2019-12-14 09:43:27 +08:00
|
|
|
|
2019-08-08 05:39:50 +08:00
|
|
|
struct btf_ext_info {
|
|
|
|
/*
|
|
|
|
* info points to the individual info section (e.g. func_info and
|
|
|
|
* line_info) from the .BTF.ext. It does not include the __u32 rec_size.
|
|
|
|
*/
|
|
|
|
void *info;
|
|
|
|
__u32 rec_size;
|
|
|
|
__u32 len;
|
2022-04-26 08:45:05 +08:00
|
|
|
/* optional (maintained internally by libbpf) mapping between .BTF.ext
|
|
|
|
* section and corresponding ELF section. This is used to join
|
|
|
|
* information like CO-RE relocation records with corresponding BPF
|
|
|
|
* programs defined in ELF sections
|
|
|
|
*/
|
|
|
|
__u32 *sec_idxs;
|
|
|
|
int sec_cnt;
|
2019-08-08 05:39:50 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#define for_each_btf_ext_sec(seg, sec) \
|
|
|
|
for (sec = (seg)->info; \
|
|
|
|
(void *)sec < (seg)->info + (seg)->len; \
|
|
|
|
sec = (void *)sec + sizeof(struct btf_ext_info_sec) + \
|
|
|
|
(seg)->rec_size * sec->num_info)
|
|
|
|
|
|
|
|
#define for_each_btf_ext_rec(seg, sec, i, rec) \
|
|
|
|
for (i = 0, rec = (void *)&(sec)->data; \
|
|
|
|
i < (sec)->num_info; \
|
|
|
|
i++, rec = (void *)rec + (seg)->rec_size)
|
|
|
|
|
2020-08-19 06:39:14 +08:00
|
|
|
/*
|
|
|
|
* The .BTF.ext ELF section layout defined as
|
|
|
|
* struct btf_ext_header
|
|
|
|
* func_info subsection
|
|
|
|
*
|
|
|
|
* The func_info subsection layout:
|
|
|
|
* record size for struct bpf_func_info in the func_info subsection
|
|
|
|
* struct btf_sec_func_info for section #1
|
|
|
|
* a list of bpf_func_info records for section #1
|
|
|
|
* where struct bpf_func_info mimics one in include/uapi/linux/bpf.h
|
|
|
|
* but may not be identical
|
|
|
|
* struct btf_sec_func_info for section #2
|
|
|
|
* a list of bpf_func_info records for section #2
|
|
|
|
* ......
|
|
|
|
*
|
|
|
|
* Note that the bpf_func_info record size in .BTF.ext may not
|
|
|
|
* be the same as the one defined in include/uapi/linux/bpf.h.
|
|
|
|
* The loader should ensure that record_size meets minimum
|
|
|
|
* requirement and pass the record as is to the kernel. The
|
|
|
|
* kernel will handle the func_info properly based on its contents.
|
|
|
|
*/
|
|
|
|
struct btf_ext_header {
|
|
|
|
__u16 magic;
|
|
|
|
__u8 version;
|
|
|
|
__u8 flags;
|
|
|
|
__u32 hdr_len;
|
|
|
|
|
|
|
|
/* All offsets are in bytes relative to the end of this header */
|
|
|
|
__u32 func_info_off;
|
|
|
|
__u32 func_info_len;
|
|
|
|
__u32 line_info_off;
|
|
|
|
__u32 line_info_len;
|
|
|
|
|
|
|
|
/* optional part of .BTF.ext header */
|
|
|
|
__u32 core_relo_off;
|
|
|
|
__u32 core_relo_len;
|
|
|
|
};
|
|
|
|
|
2019-08-08 05:39:50 +08:00
|
|
|
struct btf_ext {
|
|
|
|
union {
|
|
|
|
struct btf_ext_header *hdr;
|
|
|
|
void *data;
|
|
|
|
};
|
|
|
|
struct btf_ext_info func_info;
|
|
|
|
struct btf_ext_info line_info;
|
2020-08-19 06:39:14 +08:00
|
|
|
struct btf_ext_info core_relo_info;
|
2019-08-08 05:39:50 +08:00
|
|
|
__u32 data_size;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct btf_ext_info_sec {
|
|
|
|
__u32 sec_name_off;
|
|
|
|
__u32 num_info;
|
|
|
|
/* Followed by num_info * record_size number of bytes */
|
bpf, libbpf: Replace zero-length array with flexible-array
The current codebase makes use of the zero-length array language
extension to the C90 standard, but the preferred mechanism to declare
variable-length types such as these ones is a flexible array member[1][2],
introduced in C99:
struct foo {
int stuff;
struct boo array[];
};
By making use of the mechanism above, we will get a compiler warning
in case the flexible array does not occur last in the structure, which
will help us prevent some kind of undefined behavior bugs from being
inadvertently introduced[3] to the codebase from now on.
Also, notice that, dynamic memory allocations won't be affected by
this change:
"Flexible array members have incomplete type, and so the sizeof operator
may not be applied. As a quirk of the original implementation of
zero-length arrays, sizeof evaluates to zero."[1]
sizeof(flexible-array-member) triggers a warning because flexible array
members have incomplete type[1]. There are some instances of code in
which the sizeof operator is being incorrectly/erroneously applied to
zero-length arrays and the result is zero. Such instances may be hiding
some bugs. So, this work (flexible-array member conversions) will also
help to get completely rid of those sorts of issues.
This issue was found with the help of Coccinelle.
[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
[2] https://github.com/KSPP/linux/issues/21
[3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour")
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20200507185057.GA13981@embeddedor
2020-05-08 02:50:57 +08:00
|
|
|
__u8 data[];
|
2019-08-08 05:39:50 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* The minimum bpf_func_info checked by the loader */
|
|
|
|
struct bpf_func_info_min {
|
|
|
|
__u32 insn_off;
|
|
|
|
__u32 type_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* The minimum bpf_line_info checked by the loader */
|
|
|
|
struct bpf_line_info_min {
|
|
|
|
__u32 insn_off;
|
|
|
|
__u32 file_name_off;
|
|
|
|
__u32 line_off;
|
|
|
|
__u32 line_col;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-03-19 03:40:26 +08:00
|
|
|
typedef int (*type_id_visit_fn)(__u32 *type_id, void *ctx);
|
|
|
|
typedef int (*str_off_visit_fn)(__u32 *str_off, void *ctx);
|
|
|
|
int btf_type_visit_type_ids(struct btf_type *t, type_id_visit_fn visit, void *ctx);
|
|
|
|
int btf_type_visit_str_offs(struct btf_type *t, str_off_visit_fn visit, void *ctx);
|
|
|
|
int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx);
|
|
|
|
int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx);
|
2021-10-02 09:17:54 +08:00
|
|
|
__s32 btf__find_by_name_kind_own(const struct btf *btf, const char *type_name,
|
|
|
|
__u32 kind);
|
2021-03-19 03:40:26 +08:00
|
|
|
|
2022-03-16 20:24:13 +08:00
|
|
|
typedef int (*kallsyms_cb_t)(unsigned long long sym_addr, char sym_type,
|
|
|
|
const char *sym_name, void *ctx);
|
|
|
|
|
|
|
|
int libbpf_kallsyms_parse(kallsyms_cb_t cb, void *arg);
|
|
|
|
|
2021-05-25 11:59:33 +08:00
|
|
|
/* handle direct returned errors */
|
|
|
|
static inline int libbpf_err(int ret)
|
|
|
|
{
|
|
|
|
if (ret < 0)
|
|
|
|
errno = -ret;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* handle errno-based (e.g., syscall or libc) errors according to libbpf's
|
|
|
|
* strict mode settings
|
|
|
|
*/
|
|
|
|
static inline int libbpf_err_errno(int ret)
|
|
|
|
{
|
2022-06-28 05:15:26 +08:00
|
|
|
/* errno is already assumed to be set on error */
|
|
|
|
return ret < 0 ? -errno : ret;
|
2021-05-25 11:59:33 +08:00
|
|
|
}
|
|
|
|
|
libbpf: Streamline error reporting for high-level APIs
Implement changes to error reporting for high-level libbpf APIs to make them
less surprising and less error-prone to users:
- in all the cases when error happens, errno is set to an appropriate error
value;
- in libbpf 1.0 mode, all pointer-returning APIs return NULL on error and
error code is communicated through errno; this applies both to APIs that
already returned NULL before (so now they communicate more detailed error
codes), as well as for many APIs that used ERR_PTR() macro and encoded
error numbers as fake pointers.
- in legacy (default) mode, those APIs that were returning ERR_PTR(err),
continue doing so, but still set errno.
With these changes, errno can be always used to extract actual error,
regardless of legacy or libbpf 1.0 modes. This is utilized internally in
libbpf in places where libbpf uses it's own high-level APIs.
libbpf_get_error() is adapted to handle both cases completely transparently to
end-users (and is used by libbpf consistently as well).
More context, justification, and discussion can be found in "Libbpf: the road
to v1.0" document ([0]).
[0] https://docs.google.com/document/d/1UyjTZuPFWiPFyKk1tV5an11_iaRuec6U-ZESZ54nNTY
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/bpf/20210525035935.1461796-5-andrii@kernel.org
2021-05-25 11:59:34 +08:00
|
|
|
/* handle error for pointer-returning APIs, err is assumed to be < 0 always */
|
|
|
|
static inline void *libbpf_err_ptr(int err)
|
|
|
|
{
|
|
|
|
/* set errno on error, this doesn't break anything */
|
|
|
|
errno = -err;
|
2022-06-28 05:15:26 +08:00
|
|
|
return NULL;
|
libbpf: Streamline error reporting for high-level APIs
Implement changes to error reporting for high-level libbpf APIs to make them
less surprising and less error-prone to users:
- in all the cases when error happens, errno is set to an appropriate error
value;
- in libbpf 1.0 mode, all pointer-returning APIs return NULL on error and
error code is communicated through errno; this applies both to APIs that
already returned NULL before (so now they communicate more detailed error
codes), as well as for many APIs that used ERR_PTR() macro and encoded
error numbers as fake pointers.
- in legacy (default) mode, those APIs that were returning ERR_PTR(err),
continue doing so, but still set errno.
With these changes, errno can be always used to extract actual error,
regardless of legacy or libbpf 1.0 modes. This is utilized internally in
libbpf in places where libbpf uses it's own high-level APIs.
libbpf_get_error() is adapted to handle both cases completely transparently to
end-users (and is used by libbpf consistently as well).
More context, justification, and discussion can be found in "Libbpf: the road
to v1.0" document ([0]).
[0] https://docs.google.com/document/d/1UyjTZuPFWiPFyKk1tV5an11_iaRuec6U-ZESZ54nNTY
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/bpf/20210525035935.1461796-5-andrii@kernel.org
2021-05-25 11:59:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* handle pointer-returning APIs' error handling */
|
|
|
|
static inline void *libbpf_ptr(void *ret)
|
|
|
|
{
|
|
|
|
/* set errno on error, this doesn't break anything */
|
|
|
|
if (IS_ERR(ret))
|
|
|
|
errno = -PTR_ERR(ret);
|
|
|
|
|
2022-06-28 05:15:26 +08:00
|
|
|
return IS_ERR(ret) ? NULL : ret;
|
libbpf: Streamline error reporting for high-level APIs
Implement changes to error reporting for high-level libbpf APIs to make them
less surprising and less error-prone to users:
- in all the cases when error happens, errno is set to an appropriate error
value;
- in libbpf 1.0 mode, all pointer-returning APIs return NULL on error and
error code is communicated through errno; this applies both to APIs that
already returned NULL before (so now they communicate more detailed error
codes), as well as for many APIs that used ERR_PTR() macro and encoded
error numbers as fake pointers.
- in legacy (default) mode, those APIs that were returning ERR_PTR(err),
continue doing so, but still set errno.
With these changes, errno can be always used to extract actual error,
regardless of legacy or libbpf 1.0 modes. This is utilized internally in
libbpf in places where libbpf uses it's own high-level APIs.
libbpf_get_error() is adapted to handle both cases completely transparently to
end-users (and is used by libbpf consistently as well).
More context, justification, and discussion can be found in "Libbpf: the road
to v1.0" document ([0]).
[0] https://docs.google.com/document/d/1UyjTZuPFWiPFyKk1tV5an11_iaRuec6U-ZESZ54nNTY
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://lore.kernel.org/bpf/20210525035935.1461796-5-andrii@kernel.org
2021-05-25 11:59:34 +08:00
|
|
|
}
|
|
|
|
|
2021-07-21 08:08:22 +08:00
|
|
|
static inline bool str_is_empty(const char *s)
|
|
|
|
{
|
|
|
|
return !s || !s[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool is_ldimm64_insn(struct bpf_insn *insn)
|
|
|
|
{
|
|
|
|
return insn->code == (BPF_LD | BPF_IMM | BPF_DW);
|
|
|
|
}
|
|
|
|
|
libbpf: Ensure that BPF syscall fds are never 0, 1, or 2
Add a simple wrapper for passing an fd and getting a new one >= 3 if it
is one of 0, 1, or 2. There are two primary reasons to make this change:
First, libbpf relies on the assumption a certain BPF fd is never 0 (e.g.
most recently noticed in [0]). Second, Alexei pointed out in [1] that
some environments reset stdin, stdout, and stderr if they notice an
invalid fd at these numbers. To protect against both these cases, switch
all internal BPF syscall wrappers in libbpf to always return an fd >= 3.
We only need to modify the syscall wrappers and not other code that
assumes a valid fd by doing >= 0, to avoid pointless churn, and because
it is still a valid assumption. The cost paid is two additional syscalls
if fd is in range [0, 2].
[0]: e31eec77e4ab ("bpf: selftests: Fix fd cleanup in get_branch_snapshot")
[1]: https://lore.kernel.org/bpf/CAADnVQKVKY8o_3aU8Gzke443+uHa-eGoM0h7W4srChMXU1S4Bg@mail.gmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Song Liu <songliubraving@fb.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211028063501.2239335-5-memxor@gmail.com
2021-10-28 14:34:57 +08:00
|
|
|
/* if fd is stdin, stdout, or stderr, dup to a fd greater than 2
|
|
|
|
* Takes ownership of the fd passed in, and closes it if calling
|
|
|
|
* fcntl(fd, F_DUPFD_CLOEXEC, 3).
|
|
|
|
*/
|
|
|
|
static inline int ensure_good_fd(int fd)
|
|
|
|
{
|
|
|
|
int old_fd = fd, saved_errno;
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
return fd;
|
|
|
|
if (fd < 3) {
|
|
|
|
fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
|
|
|
|
saved_errno = errno;
|
|
|
|
close(old_fd);
|
|
|
|
if (fd < 0) {
|
|
|
|
pr_warn("failed to dup FD %d to FD > 2: %d\n", old_fd, -saved_errno);
|
|
|
|
errno = saved_errno;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
2022-02-16 06:58:51 +08:00
|
|
|
/* The following two functions are exposed to bpftool */
|
|
|
|
int bpf_core_add_cands(struct bpf_core_cand *local_cand,
|
|
|
|
size_t local_essent_len,
|
|
|
|
const struct btf *targ_btf,
|
|
|
|
const char *targ_btf_name,
|
|
|
|
int targ_start_id,
|
|
|
|
struct bpf_core_cand_list *cands);
|
|
|
|
void bpf_core_free_cands(struct bpf_core_cand_list *cands);
|
|
|
|
|
libbpf: Wire up USDT API and bpf_link integration
Wire up libbpf USDT support APIs without yet implementing all the
nitty-gritty details of USDT discovery, spec parsing, and BPF map
initialization.
User-visible user-space API is simple and is conceptually very similar
to uprobe API.
bpf_program__attach_usdt() API allows to programmatically attach given
BPF program to a USDT, specified through binary path (executable or
shared lib), USDT provider and name. Also, just like in uprobe case, PID
filter is specified (0 - self, -1 - any process, or specific PID).
Optionally, USDT cookie value can be specified. Such single API
invocation will try to discover given USDT in specified binary and will
use (potentially many) BPF uprobes to attach this program in correct
locations.
Just like any bpf_program__attach_xxx() APIs, bpf_link is returned that
represents this attachment. It is a virtual BPF link that doesn't have
direct kernel object, as it can consist of multiple underlying BPF
uprobe links. As such, attachment is not atomic operation and there can
be brief moment when some USDT call sites are attached while others are
still in the process of attaching. This should be taken into
consideration by user. But bpf_program__attach_usdt() guarantees that
in the case of success all USDT call sites are successfully attached, or
all the successfuly attachments will be detached as soon as some USDT
call sites failed to be attached. So, in theory, there could be cases of
failed bpf_program__attach_usdt() call which did trigger few USDT
program invocations. This is unavoidable due to multi-uprobe nature of
USDT and has to be handled by user, if it's important to create an
illusion of atomicity.
USDT BPF programs themselves are marked in BPF source code as either
SEC("usdt"), in which case they won't be auto-attached through
skeleton's <skel>__attach() method, or it can have a full definition,
which follows the spirit of fully-specified uprobes:
SEC("usdt/<path>:<provider>:<name>"). In the latter case skeleton's
attach method will attempt auto-attachment. Similarly, generic
bpf_program__attach() will have enought information to go off of for
parameterless attachment.
USDT BPF programs are actually uprobes, and as such for kernel they are
marked as BPF_PROG_TYPE_KPROBE.
Another part of this patch is USDT-related feature probing:
- BPF cookie support detection from user-space;
- detection of kernel support for auto-refcounting of USDT semaphore.
The latter is optional. If kernel doesn't support such feature and USDT
doesn't rely on USDT semaphores, no error is returned. But if libbpf
detects that USDT requires setting semaphores and kernel doesn't support
this, libbpf errors out with explicit pr_warn() message. Libbpf doesn't
support poking process's memory directly to increment semaphore value,
like BCC does on legacy kernels, due to inherent raciness and danger of
such process memory manipulation. Libbpf let's kernel take care of this
properly or gives up.
Logistically, all the extra USDT-related infrastructure of libbpf is put
into a separate usdt.c file and abstracted behind struct usdt_manager.
Each bpf_object has lazily-initialized usdt_manager pointer, which is
only instantiated if USDT programs are attempted to be attached. Closing
BPF object frees up usdt_manager resources. usdt_manager keeps track of
USDT spec ID assignment and few other small things.
Subsequent patches will fill out remaining missing pieces of USDT
initialization and setup logic.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Alan Maguire <alan.maguire@oracle.com>
Link: https://lore.kernel.org/bpf/20220404234202.331384-3-andrii@kernel.org
2022-04-05 07:41:57 +08:00
|
|
|
struct usdt_manager *usdt_manager_new(struct bpf_object *obj);
|
|
|
|
void usdt_manager_free(struct usdt_manager *man);
|
|
|
|
struct bpf_link * usdt_manager_attach_usdt(struct usdt_manager *man,
|
|
|
|
const struct bpf_program *prog,
|
|
|
|
pid_t pid, const char *path,
|
|
|
|
const char *usdt_provider, const char *usdt_name,
|
2022-04-19 22:52:37 +08:00
|
|
|
__u64 usdt_cookie);
|
libbpf: Wire up USDT API and bpf_link integration
Wire up libbpf USDT support APIs without yet implementing all the
nitty-gritty details of USDT discovery, spec parsing, and BPF map
initialization.
User-visible user-space API is simple and is conceptually very similar
to uprobe API.
bpf_program__attach_usdt() API allows to programmatically attach given
BPF program to a USDT, specified through binary path (executable or
shared lib), USDT provider and name. Also, just like in uprobe case, PID
filter is specified (0 - self, -1 - any process, or specific PID).
Optionally, USDT cookie value can be specified. Such single API
invocation will try to discover given USDT in specified binary and will
use (potentially many) BPF uprobes to attach this program in correct
locations.
Just like any bpf_program__attach_xxx() APIs, bpf_link is returned that
represents this attachment. It is a virtual BPF link that doesn't have
direct kernel object, as it can consist of multiple underlying BPF
uprobe links. As such, attachment is not atomic operation and there can
be brief moment when some USDT call sites are attached while others are
still in the process of attaching. This should be taken into
consideration by user. But bpf_program__attach_usdt() guarantees that
in the case of success all USDT call sites are successfully attached, or
all the successfuly attachments will be detached as soon as some USDT
call sites failed to be attached. So, in theory, there could be cases of
failed bpf_program__attach_usdt() call which did trigger few USDT
program invocations. This is unavoidable due to multi-uprobe nature of
USDT and has to be handled by user, if it's important to create an
illusion of atomicity.
USDT BPF programs themselves are marked in BPF source code as either
SEC("usdt"), in which case they won't be auto-attached through
skeleton's <skel>__attach() method, or it can have a full definition,
which follows the spirit of fully-specified uprobes:
SEC("usdt/<path>:<provider>:<name>"). In the latter case skeleton's
attach method will attempt auto-attachment. Similarly, generic
bpf_program__attach() will have enought information to go off of for
parameterless attachment.
USDT BPF programs are actually uprobes, and as such for kernel they are
marked as BPF_PROG_TYPE_KPROBE.
Another part of this patch is USDT-related feature probing:
- BPF cookie support detection from user-space;
- detection of kernel support for auto-refcounting of USDT semaphore.
The latter is optional. If kernel doesn't support such feature and USDT
doesn't rely on USDT semaphores, no error is returned. But if libbpf
detects that USDT requires setting semaphores and kernel doesn't support
this, libbpf errors out with explicit pr_warn() message. Libbpf doesn't
support poking process's memory directly to increment semaphore value,
like BCC does on legacy kernels, due to inherent raciness and danger of
such process memory manipulation. Libbpf let's kernel take care of this
properly or gives up.
Logistically, all the extra USDT-related infrastructure of libbpf is put
into a separate usdt.c file and abstracted behind struct usdt_manager.
Each bpf_object has lazily-initialized usdt_manager pointer, which is
only instantiated if USDT programs are attempted to be attached. Closing
BPF object frees up usdt_manager resources. usdt_manager keeps track of
USDT spec ID assignment and few other small things.
Subsequent patches will fill out remaining missing pieces of USDT
initialization and setup logic.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Alan Maguire <alan.maguire@oracle.com>
Link: https://lore.kernel.org/bpf/20220404234202.331384-3-andrii@kernel.org
2022-04-05 07:41:57 +08:00
|
|
|
|
2022-06-03 13:51:56 +08:00
|
|
|
static inline bool is_pow_of_2(size_t x)
|
|
|
|
{
|
|
|
|
return x && (x & (x - 1)) == 0;
|
|
|
|
}
|
|
|
|
|
libbpf: detect supported kernel BTF features and sanitize BTF
Depending on used versions of libbpf, Clang, and kernel, it's possible to
have valid BPF object files with valid BTF information, that still won't
load successfully due to Clang emitting newer BTF features (e.g.,
BTF_KIND_FUNC, .BTF.ext's line_info/func_info, BTF_KIND_DATASEC, etc), that
are not yet supported by older kernel.
This patch adds detection of BTF features and sanitizes BPF object's BTF
by substituting various supported BTF kinds, which have compatible layout:
- BTF_KIND_FUNC -> BTF_KIND_TYPEDEF
- BTF_KIND_FUNC_PROTO -> BTF_KIND_ENUM
- BTF_KIND_VAR -> BTF_KIND_INT
- BTF_KIND_DATASEC -> BTF_KIND_STRUCT
Replacement is done in such a way as to preserve as much information as
possible (names, sizes, etc) where possible without violating kernel's
validation rules.
v2->v3:
- remove duplicate #defines from libbpf_util.h
v1->v2:
- add internal libbpf_internal.h w/ common stuff
- switch SK storage BTF to use new libbpf__probe_raw_btf()
Reported-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2019-05-11 05:13:15 +08:00
|
|
|
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */
|