/src/libbpf/src/libbpf_internal.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ |
2 | | |
3 | | /* |
4 | | * Internal libbpf helpers. |
5 | | * |
6 | | * Copyright (c) 2019 Facebook |
7 | | */ |
8 | | |
9 | | #ifndef __LIBBPF_LIBBPF_INTERNAL_H |
10 | | #define __LIBBPF_LIBBPF_INTERNAL_H |
11 | | |
12 | | #include <stdlib.h> |
13 | | #include <byteswap.h> |
14 | | #include <limits.h> |
15 | | #include <errno.h> |
16 | | #include <linux/err.h> |
17 | | #include <fcntl.h> |
18 | | #include <unistd.h> |
19 | | #include <sys/syscall.h> |
20 | | #include <libelf.h> |
21 | | #include "relo_core.h" |
22 | | |
23 | | /* Android's libc doesn't support AT_EACCESS in faccessat() implementation |
24 | | * ([0]), and just returns -EINVAL even if file exists and is accessible. |
25 | | * See [1] for issues caused by this. |
26 | | * |
27 | | * So just redefine it to 0 on Android. |
28 | | * |
29 | | * [0] https://android.googlesource.com/platform/bionic/+/refs/heads/android13-release/libc/bionic/faccessat.cpp#50 |
30 | | * [1] https://github.com/libbpf/libbpf-bootstrap/issues/250#issuecomment-1911324250 |
31 | | */ |
32 | | #ifdef __ANDROID__ |
33 | | #undef AT_EACCESS |
34 | | #define AT_EACCESS 0 |
35 | | #endif |
36 | | |
37 | | /* make sure libbpf doesn't use kernel-only integer typedefs */ |
38 | | #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 |
39 | | |
40 | | /* prevent accidental re-addition of reallocarray() */ |
41 | | #pragma GCC poison reallocarray |
42 | | |
43 | | #include "libbpf.h" |
44 | | #include "btf.h" |
45 | | |
46 | | #ifndef EM_BPF |
47 | | #define EM_BPF 247 |
48 | | #endif |
49 | | |
50 | | #ifndef R_BPF_64_64 |
51 | | #define R_BPF_64_64 1 |
52 | | #endif |
53 | | #ifndef R_BPF_64_ABS64 |
54 | | #define R_BPF_64_ABS64 2 |
55 | | #endif |
56 | | #ifndef R_BPF_64_ABS32 |
57 | | #define R_BPF_64_ABS32 3 |
58 | | #endif |
59 | | #ifndef R_BPF_64_32 |
60 | | #define R_BPF_64_32 10 |
61 | | #endif |
62 | | |
63 | | #ifndef SHT_LLVM_ADDRSIG |
64 | 40.5k | #define SHT_LLVM_ADDRSIG 0x6FFF4C03 |
65 | | #endif |
66 | | |
67 | | /* if libelf is old and doesn't support mmap(), fall back to read() */ |
68 | | #ifndef ELF_C_READ_MMAP |
69 | 0 | #define ELF_C_READ_MMAP ELF_C_READ |
70 | | #endif |
71 | | |
72 | | /* Older libelf all end up in this expression, for both 32 and 64 bit */ |
73 | | #ifndef ELF64_ST_VISIBILITY |
74 | | #define ELF64_ST_VISIBILITY(o) ((o) & 0x03) |
75 | | #endif |
76 | | |
77 | | #define BTF_INFO_ENC(kind, kind_flag, vlen) \ |
78 | 0 | ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN)) |
79 | 0 | #define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type) |
80 | | #define BTF_INT_ENC(encoding, bits_offset, nr_bits) \ |
81 | 0 | ((encoding) << 24 | (bits_offset) << 16 | (nr_bits)) |
82 | | #define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \ |
83 | 0 | BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \ |
84 | 0 | BTF_INT_ENC(encoding, bits_offset, bits) |
85 | 0 | #define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset) |
86 | 0 | #define BTF_PARAM_ENC(name, type) (name), (type) |
87 | 0 | #define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size) |
88 | | #define BTF_TYPE_FLOAT_ENC(name, sz) \ |
89 | 0 | BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_FLOAT, 0, 0), sz) |
90 | | #define BTF_TYPE_DECL_TAG_ENC(value, type, component_idx) \ |
91 | 0 | BTF_TYPE_ENC(value, BTF_INFO_ENC(BTF_KIND_DECL_TAG, 0, 0), type), (component_idx) |
92 | | #define BTF_TYPE_TYPE_TAG_ENC(value, type) \ |
93 | 0 | BTF_TYPE_ENC(value, BTF_INFO_ENC(BTF_KIND_TYPE_TAG, 0, 0), type) |
94 | | |
95 | | #ifndef likely |
96 | | #define likely(x) __builtin_expect(!!(x), 1) |
97 | | #endif |
98 | | #ifndef unlikely |
99 | 0 | #define unlikely(x) __builtin_expect(!!(x), 0) |
100 | | #endif |
101 | | #ifndef min |
102 | | # define min(x, y) ((x) < (y) ? (x) : (y)) |
103 | | #endif |
104 | | #ifndef max |
105 | | # define max(x, y) ((x) < (y) ? (y) : (x)) |
106 | | #endif |
107 | | #ifndef offsetofend |
108 | | # define offsetofend(TYPE, FIELD) \ |
109 | 104k | (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD)) |
110 | | #endif |
111 | | #ifndef __alias |
112 | | #define __alias(symbol) __attribute__((alias(#symbol))) |
113 | | #endif |
114 | | |
115 | | /* Check whether a string `str` has prefix `pfx`, regardless if `pfx` is |
116 | | * a string literal known at compilation time or char * pointer known only at |
117 | | * runtime. |
118 | | */ |
119 | | #define str_has_pfx(str, pfx) \ |
120 | 90.2k | (strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0) |
121 | | |
122 | | /* suffix check */ |
123 | | static inline bool str_has_sfx(const char *str, const char *sfx) |
124 | 0 | { |
125 | 0 | size_t str_len = strlen(str); |
126 | 0 | size_t sfx_len = strlen(sfx); |
127 | |
|
128 | 0 | if (sfx_len > str_len) |
129 | 0 | return false; |
130 | 0 | return strcmp(str + str_len - sfx_len, sfx) == 0; |
131 | 0 | } Unexecuted instantiation: libbpf.c:str_has_sfx Unexecuted instantiation: libbpf_probes.c:str_has_sfx Unexecuted instantiation: gen_loader.c:str_has_sfx Unexecuted instantiation: relo_core.c:str_has_sfx Unexecuted instantiation: usdt.c:str_has_sfx Unexecuted instantiation: zip.c:str_has_sfx Unexecuted instantiation: elf.c:str_has_sfx Unexecuted instantiation: features.c:str_has_sfx Unexecuted instantiation: bpf.c:str_has_sfx Unexecuted instantiation: btf.c:str_has_sfx Unexecuted instantiation: strset.c:str_has_sfx Unexecuted instantiation: btf_iter.c:str_has_sfx Unexecuted instantiation: btf_relocate.c:str_has_sfx |
132 | | |
133 | | /* Symbol versioning is different between static and shared library. |
134 | | * Properly versioned symbols are needed for shared library, but |
135 | | * only the symbol of the new version is needed for static library. |
136 | | * Starting with GNU C 10, use symver attribute instead of .symver assembler |
137 | | * directive, which works better with GCC LTO builds. |
138 | | */ |
139 | | #if defined(SHARED) && defined(__GNUC__) && __GNUC__ >= 10 |
140 | | |
141 | | #define DEFAULT_VERSION(internal_name, api_name, version) \ |
142 | | __attribute__((symver(#api_name "@@" #version))) |
143 | | #define COMPAT_VERSION(internal_name, api_name, version) \ |
144 | | __attribute__((symver(#api_name "@" #version))) |
145 | | |
146 | | #elif defined(SHARED) |
147 | | |
148 | | #define COMPAT_VERSION(internal_name, api_name, version) \ |
149 | | asm(".symver " #internal_name "," #api_name "@" #version); |
150 | | #define DEFAULT_VERSION(internal_name, api_name, version) \ |
151 | | asm(".symver " #internal_name "," #api_name "@@" #version); |
152 | | |
153 | | #else /* !SHARED */ |
154 | | |
155 | | #define COMPAT_VERSION(internal_name, api_name, version) |
156 | | #define DEFAULT_VERSION(internal_name, api_name, version) \ |
157 | | extern typeof(internal_name) api_name \ |
158 | | __attribute__((alias(#internal_name))); |
159 | | |
160 | | #endif |
161 | | |
162 | | extern void libbpf_print(enum libbpf_print_level level, |
163 | | const char *format, ...) |
164 | | __attribute__((format(printf, 2, 3))); |
165 | | |
166 | 116k | #define __pr(level, fmt, ...) \ |
167 | 116k | do { \ |
168 | 116k | libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__); \ |
169 | 114k | } while (0) |
170 | | |
171 | 18.0k | #define pr_warn(fmt, ...) __pr(LIBBPF_WARN, fmt, ##__VA_ARGS__) |
172 | 16.2k | #define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__) |
173 | 81.8k | #define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__) |
174 | | |
175 | | #ifndef __has_builtin |
176 | | #define __has_builtin(x) 0 |
177 | | #endif |
178 | | |
179 | | struct bpf_link { |
180 | | int (*detach)(struct bpf_link *link); |
181 | | void (*dealloc)(struct bpf_link *link); |
182 | | char *pin_path; /* NULL, if not pinned */ |
183 | | int fd; /* hook FD, -1 if not applicable */ |
184 | | bool disconnected; |
185 | | }; |
186 | | |
187 | | /* |
188 | | * Re-implement glibc's reallocarray() for libbpf internal-only use. |
189 | | * reallocarray(), unfortunately, is not available in all versions of glibc, |
190 | | * so requires extra feature detection and using reallocarray() stub from |
191 | | * <tools/libc_compat.h> and COMPAT_NEED_REALLOCARRAY. All this complicates |
192 | | * build of libbpf unnecessarily and is just a maintenance burden. Instead, |
193 | | * it's trivial to implement libbpf-specific internal version and use it |
194 | | * throughout libbpf. |
195 | | */ |
196 | | static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size) |
197 | 20.5k | { |
198 | 20.5k | size_t total; |
199 | | |
200 | 20.5k | #if __has_builtin(__builtin_mul_overflow) |
201 | 20.5k | if (unlikely(__builtin_mul_overflow(nmemb, size, &total))) |
202 | 0 | return NULL; |
203 | | #else |
204 | | if (size == 0 || nmemb > ULONG_MAX / size) |
205 | | return NULL; |
206 | | total = nmemb * size; |
207 | | #endif |
208 | 20.5k | return realloc(ptr, total); |
209 | 20.5k | } libbpf.c:libbpf_reallocarray Line | Count | Source | 197 | 14.5k | { | 198 | 14.5k | size_t total; | 199 | | | 200 | 14.5k | #if __has_builtin(__builtin_mul_overflow) | 201 | 14.5k | if (unlikely(__builtin_mul_overflow(nmemb, size, &total))) | 202 | 0 | return NULL; | 203 | | #else | 204 | | if (size == 0 || nmemb > ULONG_MAX / size) | 205 | | return NULL; | 206 | | total = nmemb * size; | 207 | | #endif | 208 | 14.5k | return realloc(ptr, total); | 209 | 14.5k | } |
Unexecuted instantiation: libbpf_probes.c:libbpf_reallocarray Unexecuted instantiation: gen_loader.c:libbpf_reallocarray Unexecuted instantiation: relo_core.c:libbpf_reallocarray Unexecuted instantiation: usdt.c:libbpf_reallocarray Unexecuted instantiation: zip.c:libbpf_reallocarray Unexecuted instantiation: elf.c:libbpf_reallocarray Unexecuted instantiation: features.c:libbpf_reallocarray Unexecuted instantiation: bpf.c:libbpf_reallocarray btf.c:libbpf_reallocarray Line | Count | Source | 197 | 5.97k | { | 198 | 5.97k | size_t total; | 199 | | | 200 | 5.97k | #if __has_builtin(__builtin_mul_overflow) | 201 | 5.97k | if (unlikely(__builtin_mul_overflow(nmemb, size, &total))) | 202 | 0 | return NULL; | 203 | | #else | 204 | | if (size == 0 || nmemb > ULONG_MAX / size) | 205 | | return NULL; | 206 | | total = nmemb * size; | 207 | | #endif | 208 | 5.97k | return realloc(ptr, total); | 209 | 5.97k | } |
Unexecuted instantiation: strset.c:libbpf_reallocarray Unexecuted instantiation: btf_iter.c:libbpf_reallocarray Unexecuted instantiation: btf_relocate.c:libbpf_reallocarray |
210 | | |
211 | | /* Copy up to sz - 1 bytes from zero-terminated src string and ensure that dst |
212 | | * is zero-terminated string no matter what (unless sz == 0, in which case |
213 | | * it's a no-op). It's conceptually close to FreeBSD's strlcpy(), but differs |
214 | | * in what is returned. Given this is internal helper, it's trivial to extend |
215 | | * this, when necessary. Use this instead of strncpy inside libbpf source code. |
216 | | */ |
217 | | static inline void libbpf_strlcpy(char *dst, const char *src, size_t sz) |
218 | 11.3k | { |
219 | 11.3k | size_t i; |
220 | | |
221 | 11.3k | if (sz == 0) |
222 | 0 | return; |
223 | | |
224 | 11.3k | sz--; |
225 | 133k | for (i = 0; i < sz && src[i]; i++) |
226 | 122k | dst[i] = src[i]; |
227 | 11.3k | dst[i] = '\0'; |
228 | 11.3k | } Line | Count | Source | 218 | 11.3k | { | 219 | 11.3k | size_t i; | 220 | | | 221 | 11.3k | if (sz == 0) | 222 | 0 | return; | 223 | | | 224 | 11.3k | sz--; | 225 | 133k | for (i = 0; i < sz && src[i]; i++) | 226 | 122k | dst[i] = src[i]; | 227 | 11.3k | dst[i] = '\0'; | 228 | 11.3k | } |
Unexecuted instantiation: libbpf_probes.c:libbpf_strlcpy Unexecuted instantiation: gen_loader.c:libbpf_strlcpy Unexecuted instantiation: relo_core.c:libbpf_strlcpy Unexecuted instantiation: usdt.c:libbpf_strlcpy Unexecuted instantiation: zip.c:libbpf_strlcpy Unexecuted instantiation: elf.c:libbpf_strlcpy Unexecuted instantiation: features.c:libbpf_strlcpy Unexecuted instantiation: bpf.c:libbpf_strlcpy Unexecuted instantiation: btf.c:libbpf_strlcpy Unexecuted instantiation: strset.c:libbpf_strlcpy Unexecuted instantiation: btf_iter.c:libbpf_strlcpy Unexecuted instantiation: btf_relocate.c:libbpf_strlcpy |
229 | | |
230 | | __u32 get_kernel_version(void); |
231 | | |
232 | | struct btf; |
233 | | struct btf_type; |
234 | | |
235 | | struct btf_type *btf_type_by_id(const struct btf *btf, __u32 type_id); |
236 | | const char *btf_kind_str(const struct btf_type *t); |
237 | | const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id); |
238 | | const struct btf_header *btf_header(const struct btf *btf); |
239 | | void btf_set_base_btf(struct btf *btf, const struct btf *base_btf); |
240 | | int btf_relocate(struct btf *btf, const struct btf *base_btf, __u32 **id_map); |
241 | | |
242 | | static inline enum btf_func_linkage btf_func_linkage(const struct btf_type *t) |
243 | 509 | { |
244 | 509 | return (enum btf_func_linkage)(int)btf_vlen(t); |
245 | 509 | } libbpf.c:btf_func_linkage Line | Count | Source | 243 | 509 | { | 244 | 509 | return (enum btf_func_linkage)(int)btf_vlen(t); | 245 | 509 | } |
Unexecuted instantiation: libbpf_probes.c:btf_func_linkage Unexecuted instantiation: gen_loader.c:btf_func_linkage Unexecuted instantiation: relo_core.c:btf_func_linkage Unexecuted instantiation: usdt.c:btf_func_linkage Unexecuted instantiation: zip.c:btf_func_linkage Unexecuted instantiation: elf.c:btf_func_linkage Unexecuted instantiation: features.c:btf_func_linkage Unexecuted instantiation: bpf.c:btf_func_linkage Unexecuted instantiation: btf.c:btf_func_linkage Unexecuted instantiation: strset.c:btf_func_linkage Unexecuted instantiation: btf_iter.c:btf_func_linkage Unexecuted instantiation: btf_relocate.c:btf_func_linkage |
246 | | |
247 | | static inline __u32 btf_type_info(int kind, int vlen, int kflag) |
248 | 396 | { |
249 | 396 | return (kflag << 31) | (kind << 24) | vlen; |
250 | 396 | } Unexecuted instantiation: libbpf.c:btf_type_info Unexecuted instantiation: libbpf_probes.c:btf_type_info Unexecuted instantiation: gen_loader.c:btf_type_info Unexecuted instantiation: relo_core.c:btf_type_info Unexecuted instantiation: usdt.c:btf_type_info Unexecuted instantiation: zip.c:btf_type_info Unexecuted instantiation: elf.c:btf_type_info Unexecuted instantiation: features.c:btf_type_info Unexecuted instantiation: bpf.c:btf_type_info Line | Count | Source | 248 | 396 | { | 249 | 396 | return (kflag << 31) | (kind << 24) | vlen; | 250 | 396 | } |
Unexecuted instantiation: strset.c:btf_type_info Unexecuted instantiation: btf_iter.c:btf_type_info Unexecuted instantiation: btf_relocate.c:btf_type_info |
251 | | |
252 | | enum map_def_parts { |
253 | | MAP_DEF_MAP_TYPE = 0x001, |
254 | | MAP_DEF_KEY_TYPE = 0x002, |
255 | | MAP_DEF_KEY_SIZE = 0x004, |
256 | | MAP_DEF_VALUE_TYPE = 0x008, |
257 | | MAP_DEF_VALUE_SIZE = 0x010, |
258 | | MAP_DEF_MAX_ENTRIES = 0x020, |
259 | | MAP_DEF_MAP_FLAGS = 0x040, |
260 | | MAP_DEF_NUMA_NODE = 0x080, |
261 | | MAP_DEF_PINNING = 0x100, |
262 | | MAP_DEF_INNER_MAP = 0x200, |
263 | | MAP_DEF_MAP_EXTRA = 0x400, |
264 | | |
265 | | MAP_DEF_ALL = 0x7ff, /* combination of all above */ |
266 | | }; |
267 | | |
268 | | struct btf_map_def { |
269 | | enum map_def_parts parts; |
270 | | __u32 map_type; |
271 | | __u32 key_type_id; |
272 | | __u32 key_size; |
273 | | __u32 value_type_id; |
274 | | __u32 value_size; |
275 | | __u32 max_entries; |
276 | | __u32 map_flags; |
277 | | __u32 numa_node; |
278 | | __u32 pinning; |
279 | | __u64 map_extra; |
280 | | }; |
281 | | |
282 | | int parse_btf_map_def(const char *map_name, struct btf *btf, |
283 | | const struct btf_type *def_t, bool strict, |
284 | | struct btf_map_def *map_def, struct btf_map_def *inner_def); |
285 | | |
286 | | void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz, |
287 | | size_t cur_cnt, size_t max_cnt, size_t add_cnt); |
288 | | int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt); |
289 | | |
290 | | static inline bool libbpf_is_mem_zeroed(const char *p, ssize_t len) |
291 | 10.3k | { |
292 | 10.3k | while (len > 0) { |
293 | 0 | if (*p) |
294 | 0 | return false; |
295 | 0 | p++; |
296 | 0 | len--; |
297 | 0 | } |
298 | 10.3k | return true; |
299 | 10.3k | } libbpf.c:libbpf_is_mem_zeroed Line | Count | Source | 291 | 10.3k | { | 292 | 10.3k | while (len > 0) { | 293 | 0 | if (*p) | 294 | 0 | return false; | 295 | 0 | p++; | 296 | 0 | len--; | 297 | 0 | } | 298 | 10.3k | return true; | 299 | 10.3k | } |
Unexecuted instantiation: libbpf_probes.c:libbpf_is_mem_zeroed Unexecuted instantiation: gen_loader.c:libbpf_is_mem_zeroed Unexecuted instantiation: relo_core.c:libbpf_is_mem_zeroed Unexecuted instantiation: usdt.c:libbpf_is_mem_zeroed Unexecuted instantiation: zip.c:libbpf_is_mem_zeroed Unexecuted instantiation: elf.c:libbpf_is_mem_zeroed Unexecuted instantiation: features.c:libbpf_is_mem_zeroed Unexecuted instantiation: bpf.c:libbpf_is_mem_zeroed Unexecuted instantiation: btf.c:libbpf_is_mem_zeroed Unexecuted instantiation: strset.c:libbpf_is_mem_zeroed Unexecuted instantiation: btf_iter.c:libbpf_is_mem_zeroed Unexecuted instantiation: btf_relocate.c:libbpf_is_mem_zeroed |
300 | | |
301 | | static inline bool libbpf_validate_opts(const char *opts, |
302 | | size_t opts_sz, size_t user_sz, |
303 | | const char *type_name) |
304 | 10.3k | { |
305 | 10.3k | if (user_sz < sizeof(size_t)) { |
306 | 0 | pr_warn("%s size (%zu) is too small\n", type_name, user_sz); |
307 | 0 | return false; |
308 | 0 | } |
309 | 10.3k | if (!libbpf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) { |
310 | 0 | pr_warn("%s has non-zero extra bytes\n", type_name); |
311 | 0 | return false; |
312 | 0 | } |
313 | 10.3k | return true; |
314 | 10.3k | } libbpf.c:libbpf_validate_opts Line | Count | Source | 304 | 10.3k | { | 305 | 10.3k | if (user_sz < sizeof(size_t)) { | 306 | 0 | pr_warn("%s size (%zu) is too small\n", type_name, user_sz); | 307 | 0 | return false; | 308 | 0 | } | 309 | 10.3k | if (!libbpf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) { | 310 | 0 | pr_warn("%s has non-zero extra bytes\n", type_name); | 311 | 0 | return false; | 312 | 0 | } | 313 | 10.3k | return true; | 314 | 10.3k | } |
Unexecuted instantiation: libbpf_probes.c:libbpf_validate_opts Unexecuted instantiation: gen_loader.c:libbpf_validate_opts Unexecuted instantiation: relo_core.c:libbpf_validate_opts Unexecuted instantiation: usdt.c:libbpf_validate_opts Unexecuted instantiation: zip.c:libbpf_validate_opts Unexecuted instantiation: elf.c:libbpf_validate_opts Unexecuted instantiation: features.c:libbpf_validate_opts Unexecuted instantiation: bpf.c:libbpf_validate_opts Unexecuted instantiation: btf.c:libbpf_validate_opts Unexecuted instantiation: strset.c:libbpf_validate_opts Unexecuted instantiation: btf_iter.c:libbpf_validate_opts Unexecuted instantiation: btf_relocate.c:libbpf_validate_opts |
315 | | |
316 | | #define OPTS_VALID(opts, type) \ |
317 | 10.3k | (!(opts) || libbpf_validate_opts((const char *)opts, \ |
318 | 10.3k | offsetofend(struct type, \ |
319 | 10.3k | type##__last_field), \ |
320 | 10.3k | (opts)->sz, #type)) |
321 | | #define OPTS_HAS(opts, field) \ |
322 | 77.6k | ((opts) && opts->sz >= offsetofend(typeof(*(opts)), field)) |
323 | | #define OPTS_GET(opts, field, fallback_value) \ |
324 | 18.4E | (OPTS_HAS(opts, field) ? (opts)->field : fallback_value) |
325 | | #define OPTS_SET(opts, field, value) \ |
326 | 0 | do { \ |
327 | 0 | if (OPTS_HAS(opts, field)) \ |
328 | 0 | (opts)->field = value; \ |
329 | 0 | } while (0) |
330 | | |
331 | 0 | #define OPTS_ZEROED(opts, last_nonzero_field) \ |
332 | 0 | ({ \ |
333 | 0 | ssize_t __off = offsetofend(typeof(*(opts)), last_nonzero_field); \ |
334 | 0 | !(opts) || libbpf_is_mem_zeroed((const void *)opts + __off, \ |
335 | 0 | (opts)->sz - __off); \ |
336 | 0 | }) |
337 | | |
338 | | enum kern_feature_id { |
339 | | /* v4.14: kernel support for program & map names. */ |
340 | | FEAT_PROG_NAME, |
341 | | /* v5.2: kernel support for global data sections. */ |
342 | | FEAT_GLOBAL_DATA, |
343 | | /* BTF support */ |
344 | | FEAT_BTF, |
345 | | /* BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO support */ |
346 | | FEAT_BTF_FUNC, |
347 | | /* BTF_KIND_VAR and BTF_KIND_DATASEC support */ |
348 | | FEAT_BTF_DATASEC, |
349 | | /* BTF_FUNC_GLOBAL is supported */ |
350 | | FEAT_BTF_GLOBAL_FUNC, |
351 | | /* BPF_F_MMAPABLE is supported for arrays */ |
352 | | FEAT_ARRAY_MMAP, |
353 | | /* kernel support for expected_attach_type in BPF_PROG_LOAD */ |
354 | | FEAT_EXP_ATTACH_TYPE, |
355 | | /* bpf_probe_read_{kernel,user}[_str] helpers */ |
356 | | FEAT_PROBE_READ_KERN, |
357 | | /* BPF_PROG_BIND_MAP is supported */ |
358 | | FEAT_PROG_BIND_MAP, |
359 | | /* Kernel support for module BTFs */ |
360 | | FEAT_MODULE_BTF, |
361 | | /* BTF_KIND_FLOAT support */ |
362 | | FEAT_BTF_FLOAT, |
363 | | /* BPF perf link support */ |
364 | | FEAT_PERF_LINK, |
365 | | /* BTF_KIND_DECL_TAG support */ |
366 | | FEAT_BTF_DECL_TAG, |
367 | | /* BTF_KIND_TYPE_TAG support */ |
368 | | FEAT_BTF_TYPE_TAG, |
369 | | /* memcg-based accounting for BPF maps and progs */ |
370 | | FEAT_MEMCG_ACCOUNT, |
371 | | /* BPF cookie (bpf_get_attach_cookie() BPF helper) support */ |
372 | | FEAT_BPF_COOKIE, |
373 | | /* BTF_KIND_ENUM64 support and BTF_KIND_ENUM kflag support */ |
374 | | FEAT_BTF_ENUM64, |
375 | | /* Kernel uses syscall wrapper (CONFIG_ARCH_HAS_SYSCALL_WRAPPER) */ |
376 | | FEAT_SYSCALL_WRAPPER, |
377 | | /* BPF multi-uprobe link support */ |
378 | | FEAT_UPROBE_MULTI_LINK, |
379 | | /* Kernel supports arg:ctx tag (__arg_ctx) for global subprogs natively */ |
380 | | FEAT_ARG_CTX_TAG, |
381 | | /* Kernel supports '?' at the front of datasec names */ |
382 | | FEAT_BTF_QMARK_DATASEC, |
383 | | __FEAT_CNT, |
384 | | }; |
385 | | |
386 | | enum kern_feature_result { |
387 | | FEAT_UNKNOWN = 0, |
388 | | FEAT_SUPPORTED = 1, |
389 | | FEAT_MISSING = 2, |
390 | | }; |
391 | | |
392 | | struct kern_feature_cache { |
393 | | enum kern_feature_result res[__FEAT_CNT]; |
394 | | int token_fd; |
395 | | }; |
396 | | |
397 | | bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_id); |
398 | | bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id); |
399 | | |
400 | | int probe_kern_syscall_wrapper(int token_fd); |
401 | | int probe_memcg_account(int token_fd); |
402 | | int bump_rlimit_memlock(void); |
403 | | |
404 | | int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz); |
405 | | int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz); |
406 | | int libbpf__load_raw_btf(const char *raw_types, size_t types_len, |
407 | | const char *str_sec, size_t str_len, |
408 | | int token_fd); |
409 | | int btf_load_into_kernel(struct btf *btf, |
410 | | char *log_buf, size_t log_sz, __u32 log_level, |
411 | | int token_fd); |
412 | | struct btf *btf_load_from_kernel(__u32 id, struct btf *base_btf, int token_fd); |
413 | | |
414 | | struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf); |
415 | | void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type, |
416 | | const char **prefix, int *kind); |
417 | | |
418 | | struct btf_ext_info { |
419 | | /* |
420 | | * info points to the individual info section (e.g. func_info and |
421 | | * line_info) from the .BTF.ext. It does not include the __u32 rec_size. |
422 | | */ |
423 | | void *info; |
424 | | __u32 rec_size; |
425 | | __u32 len; |
426 | | /* optional (maintained internally by libbpf) mapping between .BTF.ext |
427 | | * section and corresponding ELF section. This is used to join |
428 | | * information like CO-RE relocation records with corresponding BPF |
429 | | * programs defined in ELF sections |
430 | | */ |
431 | | __u32 *sec_idxs; |
432 | | int sec_cnt; |
433 | | }; |
434 | | |
435 | | #define for_each_btf_ext_sec(seg, sec) \ |
436 | 155 | for (sec = (seg)->info; \ |
437 | 403 | (void *)sec < (seg)->info + (seg)->len; \ |
438 | 248 | sec = (void *)sec + sizeof(struct btf_ext_info_sec) + \ |
439 | 248 | (seg)->rec_size * sec->num_info) |
440 | | |
441 | | #define for_each_btf_ext_rec(seg, sec, i, rec) \ |
442 | 0 | for (i = 0, rec = (void *)&(sec)->data; \ |
443 | 0 | i < (sec)->num_info; \ |
444 | 0 | i++, rec = (void *)rec + (seg)->rec_size) |
445 | | |
446 | | /* |
447 | | * The .BTF.ext ELF section layout defined as |
448 | | * struct btf_ext_header |
449 | | * func_info subsection |
450 | | * |
451 | | * The func_info subsection layout: |
452 | | * record size for struct bpf_func_info in the func_info subsection |
453 | | * struct btf_ext_info_sec for section #1 |
454 | | * a list of bpf_func_info records for section #1 |
455 | | * where struct bpf_func_info mimics one in include/uapi/linux/bpf.h |
456 | | * but may not be identical |
457 | | * struct btf_ext_info_sec for section #2 |
458 | | * a list of bpf_func_info records for section #2 |
459 | | * ...... |
460 | | * |
461 | | * Note that the bpf_func_info record size in .BTF.ext may not |
462 | | * be the same as the one defined in include/uapi/linux/bpf.h. |
463 | | * The loader should ensure that record_size meets minimum |
464 | | * requirement and pass the record as is to the kernel. The |
465 | | * kernel will handle the func_info properly based on its contents. |
466 | | */ |
467 | | struct btf_ext_header { |
468 | | __u16 magic; |
469 | | __u8 version; |
470 | | __u8 flags; |
471 | | __u32 hdr_len; |
472 | | |
473 | | /* All offsets are in bytes relative to the end of this header */ |
474 | | __u32 func_info_off; |
475 | | __u32 func_info_len; |
476 | | __u32 line_info_off; |
477 | | __u32 line_info_len; |
478 | | |
479 | | /* optional part of .BTF.ext header */ |
480 | | __u32 core_relo_off; |
481 | | __u32 core_relo_len; |
482 | | }; |
483 | | |
484 | | struct btf_ext { |
485 | | union { |
486 | | struct btf_ext_header *hdr; |
487 | | void *data; |
488 | | }; |
489 | | void *data_swapped; |
490 | | bool swapped_endian; |
491 | | struct btf_ext_info func_info; |
492 | | struct btf_ext_info line_info; |
493 | | struct btf_ext_info core_relo_info; |
494 | | __u32 data_size; |
495 | | }; |
496 | | |
497 | | struct btf_ext_info_sec { |
498 | | __u32 sec_name_off; |
499 | | __u32 num_info; |
500 | | /* Followed by num_info * record_size number of bytes */ |
501 | | __u8 data[]; |
502 | | }; |
503 | | |
504 | | /* The minimum bpf_func_info checked by the loader */ |
505 | | struct bpf_func_info_min { |
506 | | __u32 insn_off; |
507 | | __u32 type_id; |
508 | | }; |
509 | | |
510 | | /* The minimum bpf_line_info checked by the loader */ |
511 | | struct bpf_line_info_min { |
512 | | __u32 insn_off; |
513 | | __u32 file_name_off; |
514 | | __u32 line_off; |
515 | | __u32 line_col; |
516 | | }; |
517 | | |
518 | | /* Functions to byte-swap info records */ |
519 | | |
520 | | typedef void (*info_rec_bswap_fn)(void *); |
521 | | |
522 | | static inline void bpf_func_info_bswap(struct bpf_func_info *i) |
523 | 34 | { |
524 | 34 | i->insn_off = bswap_32(i->insn_off); |
525 | 34 | i->type_id = bswap_32(i->type_id); |
526 | 34 | } Unexecuted instantiation: libbpf.c:bpf_func_info_bswap Unexecuted instantiation: libbpf_probes.c:bpf_func_info_bswap Unexecuted instantiation: gen_loader.c:bpf_func_info_bswap Unexecuted instantiation: relo_core.c:bpf_func_info_bswap Unexecuted instantiation: usdt.c:bpf_func_info_bswap Unexecuted instantiation: zip.c:bpf_func_info_bswap Unexecuted instantiation: elf.c:bpf_func_info_bswap Unexecuted instantiation: features.c:bpf_func_info_bswap Unexecuted instantiation: bpf.c:bpf_func_info_bswap btf.c:bpf_func_info_bswap Line | Count | Source | 523 | 34 | { | 524 | 34 | i->insn_off = bswap_32(i->insn_off); | 525 | 34 | i->type_id = bswap_32(i->type_id); | 526 | 34 | } |
Unexecuted instantiation: strset.c:bpf_func_info_bswap Unexecuted instantiation: btf_iter.c:bpf_func_info_bswap Unexecuted instantiation: btf_relocate.c:bpf_func_info_bswap |
527 | | |
528 | | static inline void bpf_line_info_bswap(struct bpf_line_info *i) |
529 | 0 | { |
530 | 0 | i->insn_off = bswap_32(i->insn_off); |
531 | 0 | i->file_name_off = bswap_32(i->file_name_off); |
532 | 0 | i->line_off = bswap_32(i->line_off); |
533 | 0 | i->line_col = bswap_32(i->line_col); |
534 | 0 | } Unexecuted instantiation: libbpf.c:bpf_line_info_bswap Unexecuted instantiation: libbpf_probes.c:bpf_line_info_bswap Unexecuted instantiation: gen_loader.c:bpf_line_info_bswap Unexecuted instantiation: relo_core.c:bpf_line_info_bswap Unexecuted instantiation: usdt.c:bpf_line_info_bswap Unexecuted instantiation: zip.c:bpf_line_info_bswap Unexecuted instantiation: elf.c:bpf_line_info_bswap Unexecuted instantiation: features.c:bpf_line_info_bswap Unexecuted instantiation: bpf.c:bpf_line_info_bswap Unexecuted instantiation: btf.c:bpf_line_info_bswap Unexecuted instantiation: strset.c:bpf_line_info_bswap Unexecuted instantiation: btf_iter.c:bpf_line_info_bswap Unexecuted instantiation: btf_relocate.c:bpf_line_info_bswap |
535 | | |
536 | | static inline void bpf_core_relo_bswap(struct bpf_core_relo *i) |
537 | 0 | { |
538 | 0 | i->insn_off = bswap_32(i->insn_off); |
539 | 0 | i->type_id = bswap_32(i->type_id); |
540 | 0 | i->access_str_off = bswap_32(i->access_str_off); |
541 | 0 | i->kind = bswap_32(i->kind); |
542 | 0 | } Unexecuted instantiation: libbpf.c:bpf_core_relo_bswap Unexecuted instantiation: libbpf_probes.c:bpf_core_relo_bswap Unexecuted instantiation: gen_loader.c:bpf_core_relo_bswap Unexecuted instantiation: relo_core.c:bpf_core_relo_bswap Unexecuted instantiation: usdt.c:bpf_core_relo_bswap Unexecuted instantiation: zip.c:bpf_core_relo_bswap Unexecuted instantiation: elf.c:bpf_core_relo_bswap Unexecuted instantiation: features.c:bpf_core_relo_bswap Unexecuted instantiation: bpf.c:bpf_core_relo_bswap Unexecuted instantiation: btf.c:bpf_core_relo_bswap Unexecuted instantiation: strset.c:bpf_core_relo_bswap Unexecuted instantiation: btf_iter.c:bpf_core_relo_bswap Unexecuted instantiation: btf_relocate.c:bpf_core_relo_bswap |
543 | | |
544 | | enum btf_field_iter_kind { |
545 | | BTF_FIELD_ITER_IDS, |
546 | | BTF_FIELD_ITER_STRS, |
547 | | }; |
548 | | |
549 | | struct btf_field_desc { |
550 | | /* once-per-type offsets */ |
551 | | int t_off_cnt, t_offs[2]; |
552 | | /* member struct size, or zero, if no members */ |
553 | | int m_sz; |
554 | | /* repeated per-member offsets */ |
555 | | int m_off_cnt, m_offs[1]; |
556 | | }; |
557 | | |
558 | | struct btf_field_iter { |
559 | | struct btf_field_desc desc; |
560 | | void *p; |
561 | | int m_idx; |
562 | | int off_idx; |
563 | | int vlen; |
564 | | }; |
565 | | |
566 | | int btf_field_iter_init(struct btf_field_iter *it, struct btf_type *t, enum btf_field_iter_kind iter_kind); |
567 | | __u32 *btf_field_iter_next(struct btf_field_iter *it); |
568 | | |
569 | | typedef int (*type_id_visit_fn)(__u32 *type_id, void *ctx); |
570 | | typedef int (*str_off_visit_fn)(__u32 *str_off, void *ctx); |
571 | | int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx); |
572 | | int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx); |
573 | | __s32 btf__find_by_name_kind_own(const struct btf *btf, const char *type_name, |
574 | | __u32 kind); |
575 | | |
576 | | /* handle direct returned errors */ |
577 | | static inline int libbpf_err(int ret) |
578 | 2.62k | { |
579 | 2.62k | if (ret < 0) |
580 | 2.61k | errno = -ret; |
581 | 2.62k | return ret; |
582 | 2.62k | } Unexecuted instantiation: libbpf.c:libbpf_err Unexecuted instantiation: libbpf_probes.c:libbpf_err Unexecuted instantiation: gen_loader.c:libbpf_err Unexecuted instantiation: relo_core.c:libbpf_err Unexecuted instantiation: usdt.c:libbpf_err Unexecuted instantiation: zip.c:libbpf_err Unexecuted instantiation: elf.c:libbpf_err Unexecuted instantiation: features.c:libbpf_err Unexecuted instantiation: bpf.c:libbpf_err Line | Count | Source | 578 | 2.62k | { | 579 | 2.62k | if (ret < 0) | 580 | 2.61k | errno = -ret; | 581 | 2.62k | return ret; | 582 | 2.62k | } |
Unexecuted instantiation: strset.c:libbpf_err Unexecuted instantiation: btf_iter.c:libbpf_err Unexecuted instantiation: btf_relocate.c:libbpf_err |
583 | | |
584 | | /* handle errno-based (e.g., syscall or libc) errors according to libbpf's |
585 | | * strict mode settings |
586 | | */ |
587 | | static inline int libbpf_err_errno(int ret) |
588 | 0 | { |
589 | | /* errno is already assumed to be set on error */ |
590 | 0 | return ret < 0 ? -errno : ret; |
591 | 0 | } Unexecuted instantiation: libbpf.c:libbpf_err_errno Unexecuted instantiation: libbpf_probes.c:libbpf_err_errno Unexecuted instantiation: gen_loader.c:libbpf_err_errno Unexecuted instantiation: relo_core.c:libbpf_err_errno Unexecuted instantiation: usdt.c:libbpf_err_errno Unexecuted instantiation: zip.c:libbpf_err_errno Unexecuted instantiation: elf.c:libbpf_err_errno Unexecuted instantiation: features.c:libbpf_err_errno Unexecuted instantiation: bpf.c:libbpf_err_errno Unexecuted instantiation: btf.c:libbpf_err_errno Unexecuted instantiation: strset.c:libbpf_err_errno Unexecuted instantiation: btf_iter.c:libbpf_err_errno Unexecuted instantiation: btf_relocate.c:libbpf_err_errno |
592 | | |
593 | | /* handle error for pointer-returning APIs, err is assumed to be < 0 always */ |
594 | | static inline void *libbpf_err_ptr(int err) |
595 | 378 | { |
596 | | /* set errno on error, this doesn't break anything */ |
597 | 378 | errno = -err; |
598 | 378 | return NULL; |
599 | 378 | } Unexecuted instantiation: libbpf.c:libbpf_err_ptr Unexecuted instantiation: libbpf_probes.c:libbpf_err_ptr Unexecuted instantiation: gen_loader.c:libbpf_err_ptr Unexecuted instantiation: relo_core.c:libbpf_err_ptr Unexecuted instantiation: usdt.c:libbpf_err_ptr Unexecuted instantiation: zip.c:libbpf_err_ptr Unexecuted instantiation: elf.c:libbpf_err_ptr Unexecuted instantiation: features.c:libbpf_err_ptr Unexecuted instantiation: bpf.c:libbpf_err_ptr Line | Count | Source | 595 | 378 | { | 596 | | /* set errno on error, this doesn't break anything */ | 597 | 378 | errno = -err; | 598 | 378 | return NULL; | 599 | 378 | } |
Unexecuted instantiation: strset.c:libbpf_err_ptr Unexecuted instantiation: btf_iter.c:libbpf_err_ptr Unexecuted instantiation: btf_relocate.c:libbpf_err_ptr |
600 | | |
601 | | /* handle pointer-returning APIs' error handling */ |
602 | | static inline void *libbpf_ptr(void *ret) |
603 | 13.9k | { |
604 | | /* set errno on error, this doesn't break anything */ |
605 | 13.9k | if (IS_ERR(ret)) |
606 | 9.58k | errno = -PTR_ERR(ret); |
607 | | |
608 | 13.9k | return IS_ERR(ret) ? NULL : ret; |
609 | 13.9k | } Line | Count | Source | 603 | 10.3k | { | 604 | | /* set errno on error, this doesn't break anything */ | 605 | 10.3k | if (IS_ERR(ret)) | 606 | 8.79k | errno = -PTR_ERR(ret); | 607 | | | 608 | 10.3k | return IS_ERR(ret) ? NULL : ret; | 609 | 10.3k | } |
Unexecuted instantiation: libbpf_probes.c:libbpf_ptr Unexecuted instantiation: gen_loader.c:libbpf_ptr Unexecuted instantiation: relo_core.c:libbpf_ptr Unexecuted instantiation: usdt.c:libbpf_ptr Unexecuted instantiation: zip.c:libbpf_ptr Unexecuted instantiation: elf.c:libbpf_ptr Unexecuted instantiation: features.c:libbpf_ptr Unexecuted instantiation: bpf.c:libbpf_ptr Line | Count | Source | 603 | 3.60k | { | 604 | | /* set errno on error, this doesn't break anything */ | 605 | 3.60k | if (IS_ERR(ret)) | 606 | 796 | errno = -PTR_ERR(ret); | 607 | | | 608 | 3.60k | return IS_ERR(ret) ? NULL : ret; | 609 | 3.60k | } |
Unexecuted instantiation: strset.c:libbpf_ptr Unexecuted instantiation: btf_iter.c:libbpf_ptr Unexecuted instantiation: btf_relocate.c:libbpf_ptr |
610 | | |
611 | | static inline bool str_is_empty(const char *s) |
612 | 248 | { |
613 | 248 | return !s || !s[0]; |
614 | 248 | } Line | Count | Source | 612 | 248 | { | 613 | 248 | return !s || !s[0]; | 614 | 248 | } |
Unexecuted instantiation: libbpf_probes.c:str_is_empty Unexecuted instantiation: gen_loader.c:str_is_empty Unexecuted instantiation: relo_core.c:str_is_empty Unexecuted instantiation: usdt.c:str_is_empty Unexecuted instantiation: zip.c:str_is_empty Unexecuted instantiation: elf.c:str_is_empty Unexecuted instantiation: features.c:str_is_empty Unexecuted instantiation: bpf.c:str_is_empty Unexecuted instantiation: btf.c:str_is_empty Unexecuted instantiation: strset.c:str_is_empty Unexecuted instantiation: btf_iter.c:str_is_empty Unexecuted instantiation: btf_relocate.c:str_is_empty |
615 | | |
616 | | static inline bool is_ldimm64_insn(struct bpf_insn *insn) |
617 | 1.04k | { |
618 | 1.04k | return insn->code == (BPF_LD | BPF_IMM | BPF_DW); |
619 | 1.04k | } Line | Count | Source | 617 | 1.04k | { | 618 | 1.04k | return insn->code == (BPF_LD | BPF_IMM | BPF_DW); | 619 | 1.04k | } |
Unexecuted instantiation: libbpf_probes.c:is_ldimm64_insn Unexecuted instantiation: gen_loader.c:is_ldimm64_insn Unexecuted instantiation: relo_core.c:is_ldimm64_insn Unexecuted instantiation: usdt.c:is_ldimm64_insn Unexecuted instantiation: zip.c:is_ldimm64_insn Unexecuted instantiation: elf.c:is_ldimm64_insn Unexecuted instantiation: features.c:is_ldimm64_insn Unexecuted instantiation: bpf.c:is_ldimm64_insn Unexecuted instantiation: btf.c:is_ldimm64_insn Unexecuted instantiation: strset.c:is_ldimm64_insn Unexecuted instantiation: btf_iter.c:is_ldimm64_insn Unexecuted instantiation: btf_relocate.c:is_ldimm64_insn |
620 | | |
621 | | static inline void bpf_insn_bswap(struct bpf_insn *insn) |
622 | 3.52k | { |
623 | 3.52k | __u8 tmp_reg = insn->dst_reg; |
624 | | |
625 | 3.52k | insn->dst_reg = insn->src_reg; |
626 | 3.52k | insn->src_reg = tmp_reg; |
627 | 3.52k | insn->off = bswap_16(insn->off); |
628 | 3.52k | insn->imm = bswap_32(insn->imm); |
629 | 3.52k | } Line | Count | Source | 622 | 3.52k | { | 623 | 3.52k | __u8 tmp_reg = insn->dst_reg; | 624 | | | 625 | 3.52k | insn->dst_reg = insn->src_reg; | 626 | 3.52k | insn->src_reg = tmp_reg; | 627 | 3.52k | insn->off = bswap_16(insn->off); | 628 | 3.52k | insn->imm = bswap_32(insn->imm); | 629 | 3.52k | } |
Unexecuted instantiation: libbpf_probes.c:bpf_insn_bswap Unexecuted instantiation: gen_loader.c:bpf_insn_bswap Unexecuted instantiation: relo_core.c:bpf_insn_bswap Unexecuted instantiation: usdt.c:bpf_insn_bswap Unexecuted instantiation: zip.c:bpf_insn_bswap Unexecuted instantiation: elf.c:bpf_insn_bswap Unexecuted instantiation: features.c:bpf_insn_bswap Unexecuted instantiation: bpf.c:bpf_insn_bswap Unexecuted instantiation: btf.c:bpf_insn_bswap Unexecuted instantiation: strset.c:bpf_insn_bswap Unexecuted instantiation: btf_iter.c:bpf_insn_bswap Unexecuted instantiation: btf_relocate.c:bpf_insn_bswap |
630 | | |
631 | | /* Unconditionally dup FD, ensuring it doesn't use [0, 2] range. |
632 | | * Original FD is not closed or altered in any other way. |
633 | | * Preserves original FD value, if it's invalid (negative). |
634 | | */ |
635 | | static inline int dup_good_fd(int fd) |
636 | 0 | { |
637 | 0 | if (fd < 0) |
638 | 0 | return fd; |
639 | 0 | return fcntl(fd, F_DUPFD_CLOEXEC, 3); |
640 | 0 | } Unexecuted instantiation: libbpf.c:dup_good_fd Unexecuted instantiation: libbpf_probes.c:dup_good_fd Unexecuted instantiation: gen_loader.c:dup_good_fd Unexecuted instantiation: relo_core.c:dup_good_fd Unexecuted instantiation: usdt.c:dup_good_fd Unexecuted instantiation: zip.c:dup_good_fd Unexecuted instantiation: elf.c:dup_good_fd Unexecuted instantiation: features.c:dup_good_fd Unexecuted instantiation: bpf.c:dup_good_fd Unexecuted instantiation: btf.c:dup_good_fd Unexecuted instantiation: strset.c:dup_good_fd Unexecuted instantiation: btf_iter.c:dup_good_fd Unexecuted instantiation: btf_relocate.c:dup_good_fd |
641 | | |
642 | | /* if fd is stdin, stdout, or stderr, dup to a fd greater than 2 |
643 | | * Takes ownership of the fd passed in, and closes it if calling |
644 | | * fcntl(fd, F_DUPFD_CLOEXEC, 3). |
645 | | */ |
646 | | static inline int ensure_good_fd(int fd) |
647 | 4.67k | { |
648 | 4.67k | int old_fd = fd, saved_errno; |
649 | | |
650 | 4.67k | if (fd < 0) |
651 | 2.33k | return fd; |
652 | 2.33k | if (fd < 3) { |
653 | 0 | fd = dup_good_fd(fd); |
654 | 0 | saved_errno = errno; |
655 | 0 | close(old_fd); |
656 | 0 | errno = saved_errno; |
657 | 0 | if (fd < 0) { |
658 | 0 | pr_warn("failed to dup FD %d to FD > 2: %d\n", old_fd, -saved_errno); |
659 | 0 | errno = saved_errno; |
660 | 0 | } |
661 | 0 | } |
662 | 2.33k | return fd; |
663 | 4.67k | } Line | Count | Source | 647 | 4.67k | { | 648 | 4.67k | int old_fd = fd, saved_errno; | 649 | | | 650 | 4.67k | if (fd < 0) | 651 | 2.33k | return fd; | 652 | 2.33k | if (fd < 3) { | 653 | 0 | fd = dup_good_fd(fd); | 654 | 0 | saved_errno = errno; | 655 | 0 | close(old_fd); | 656 | 0 | errno = saved_errno; | 657 | 0 | if (fd < 0) { | 658 | 0 | pr_warn("failed to dup FD %d to FD > 2: %d\n", old_fd, -saved_errno); | 659 | 0 | errno = saved_errno; | 660 | 0 | } | 661 | 0 | } | 662 | 2.33k | return fd; | 663 | 4.67k | } |
Unexecuted instantiation: libbpf_probes.c:ensure_good_fd Unexecuted instantiation: gen_loader.c:ensure_good_fd Unexecuted instantiation: relo_core.c:ensure_good_fd Unexecuted instantiation: usdt.c:ensure_good_fd Unexecuted instantiation: zip.c:ensure_good_fd Unexecuted instantiation: elf.c:ensure_good_fd Unexecuted instantiation: features.c:ensure_good_fd Unexecuted instantiation: bpf.c:ensure_good_fd Unexecuted instantiation: btf.c:ensure_good_fd Unexecuted instantiation: strset.c:ensure_good_fd Unexecuted instantiation: btf_iter.c:ensure_good_fd Unexecuted instantiation: btf_relocate.c:ensure_good_fd |
664 | | |
665 | | static inline int sys_dup3(int oldfd, int newfd, int flags) |
666 | 0 | { |
667 | 0 | return syscall(__NR_dup3, oldfd, newfd, flags); |
668 | 0 | } Unexecuted instantiation: libbpf.c:sys_dup3 Unexecuted instantiation: libbpf_probes.c:sys_dup3 Unexecuted instantiation: gen_loader.c:sys_dup3 Unexecuted instantiation: relo_core.c:sys_dup3 Unexecuted instantiation: usdt.c:sys_dup3 Unexecuted instantiation: zip.c:sys_dup3 Unexecuted instantiation: elf.c:sys_dup3 Unexecuted instantiation: features.c:sys_dup3 Unexecuted instantiation: bpf.c:sys_dup3 Unexecuted instantiation: btf.c:sys_dup3 Unexecuted instantiation: strset.c:sys_dup3 Unexecuted instantiation: btf_iter.c:sys_dup3 Unexecuted instantiation: btf_relocate.c:sys_dup3 |
669 | | |
670 | | /* Some versions of Android don't provide memfd_create() in their libc |
671 | | * implementation, so avoid complications and just go straight to Linux |
672 | | * syscall. |
673 | | */ |
674 | | static inline int sys_memfd_create(const char *name, unsigned flags) |
675 | 4.67k | { |
676 | 4.67k | return syscall(__NR_memfd_create, name, flags); |
677 | 4.67k | } libbpf.c:sys_memfd_create Line | Count | Source | 675 | 4.67k | { | 676 | 4.67k | return syscall(__NR_memfd_create, name, flags); | 677 | 4.67k | } |
Unexecuted instantiation: libbpf_probes.c:sys_memfd_create Unexecuted instantiation: gen_loader.c:sys_memfd_create Unexecuted instantiation: relo_core.c:sys_memfd_create Unexecuted instantiation: usdt.c:sys_memfd_create Unexecuted instantiation: zip.c:sys_memfd_create Unexecuted instantiation: elf.c:sys_memfd_create Unexecuted instantiation: features.c:sys_memfd_create Unexecuted instantiation: bpf.c:sys_memfd_create Unexecuted instantiation: btf.c:sys_memfd_create Unexecuted instantiation: strset.c:sys_memfd_create Unexecuted instantiation: btf_iter.c:sys_memfd_create Unexecuted instantiation: btf_relocate.c:sys_memfd_create |
678 | | |
679 | | /* Point *fixed_fd* to the same file that *tmp_fd* points to. |
680 | | * Regardless of success, *tmp_fd* is closed. |
681 | | * Whatever *fixed_fd* pointed to is closed silently. |
682 | | */ |
683 | | static inline int reuse_fd(int fixed_fd, int tmp_fd) |
684 | 0 | { |
685 | 0 | int err; |
686 | |
|
687 | 0 | err = sys_dup3(tmp_fd, fixed_fd, O_CLOEXEC); |
688 | 0 | err = err < 0 ? -errno : 0; |
689 | 0 | close(tmp_fd); /* clean up temporary FD */ |
690 | 0 | return err; |
691 | 0 | } Unexecuted instantiation: libbpf.c:reuse_fd Unexecuted instantiation: libbpf_probes.c:reuse_fd Unexecuted instantiation: gen_loader.c:reuse_fd Unexecuted instantiation: relo_core.c:reuse_fd Unexecuted instantiation: usdt.c:reuse_fd Unexecuted instantiation: zip.c:reuse_fd Unexecuted instantiation: elf.c:reuse_fd Unexecuted instantiation: features.c:reuse_fd Unexecuted instantiation: bpf.c:reuse_fd Unexecuted instantiation: btf.c:reuse_fd Unexecuted instantiation: strset.c:reuse_fd Unexecuted instantiation: btf_iter.c:reuse_fd Unexecuted instantiation: btf_relocate.c:reuse_fd |
692 | | |
693 | | /* The following two functions are exposed to bpftool */ |
694 | | int bpf_core_add_cands(struct bpf_core_cand *local_cand, |
695 | | size_t local_essent_len, |
696 | | const struct btf *targ_btf, |
697 | | const char *targ_btf_name, |
698 | | int targ_start_id, |
699 | | struct bpf_core_cand_list *cands); |
700 | | void bpf_core_free_cands(struct bpf_core_cand_list *cands); |
701 | | |
702 | | struct usdt_manager *usdt_manager_new(struct bpf_object *obj); |
703 | | void usdt_manager_free(struct usdt_manager *man); |
704 | | struct bpf_link * usdt_manager_attach_usdt(struct usdt_manager *man, |
705 | | const struct bpf_program *prog, |
706 | | pid_t pid, const char *path, |
707 | | const char *usdt_provider, const char *usdt_name, |
708 | | __u64 usdt_cookie); |
709 | | |
710 | | static inline bool is_pow_of_2(size_t x) |
711 | 6 | { |
712 | 6 | return x && (x & (x - 1)) == 0; |
713 | 6 | } Line | Count | Source | 711 | 6 | { | 712 | 6 | return x && (x & (x - 1)) == 0; | 713 | 6 | } |
Unexecuted instantiation: libbpf_probes.c:is_pow_of_2 Unexecuted instantiation: gen_loader.c:is_pow_of_2 Unexecuted instantiation: relo_core.c:is_pow_of_2 Unexecuted instantiation: usdt.c:is_pow_of_2 Unexecuted instantiation: zip.c:is_pow_of_2 Unexecuted instantiation: elf.c:is_pow_of_2 Unexecuted instantiation: features.c:is_pow_of_2 Unexecuted instantiation: bpf.c:is_pow_of_2 Unexecuted instantiation: btf.c:is_pow_of_2 Unexecuted instantiation: strset.c:is_pow_of_2 Unexecuted instantiation: btf_iter.c:is_pow_of_2 Unexecuted instantiation: btf_relocate.c:is_pow_of_2 |
714 | | |
715 | 0 | #define PROG_LOAD_ATTEMPTS 5 |
716 | | int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts); |
717 | | |
718 | | bool glob_match(const char *str, const char *pat); |
719 | | |
720 | | long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name); |
721 | | long elf_find_func_offset_from_file(const char *binary_path, const char *name); |
722 | | |
723 | | struct elf_fd { |
724 | | Elf *elf; |
725 | | int fd; |
726 | | }; |
727 | | |
728 | | int elf_open(const char *binary_path, struct elf_fd *elf_fd); |
729 | | void elf_close(struct elf_fd *elf_fd); |
730 | | |
731 | | int elf_resolve_syms_offsets(const char *binary_path, int cnt, |
732 | | const char **syms, unsigned long **poffsets, |
733 | | int st_type); |
734 | | int elf_resolve_pattern_offsets(const char *binary_path, const char *pattern, |
735 | | unsigned long **poffsets, size_t *pcnt); |
736 | | |
737 | | int probe_fd(int fd); |
738 | | |
739 | | #endif /* __LIBBPF_LIBBPF_INTERNAL_H */ |