]>
Commit | Line | Data |
---|---|---|
d7c4b398 AN |
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 | ||
029258d7 | 12 | #include <stdlib.h> |
dda1ec9f | 13 | #include <limits.h> |
85367030 AN |
14 | |
15 | /* make sure libbpf doesn't use kernel-only integer typedefs */ | |
16 | #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 | |
17 | ||
18 | /* prevent accidental re-addition of reallocarray() */ | |
19 | #pragma GCC poison reallocarray | |
20 | ||
1d7a08b3 | 21 | #include "libbpf.h" |
aea28a60 | 22 | #include "btf.h" |
1d7a08b3 | 23 | |
faf6ed32 AN |
24 | #ifndef EM_BPF |
25 | #define EM_BPF 247 | |
26 | #endif | |
27 | ||
28 | #ifndef R_BPF_64_64 | |
29 | #define R_BPF_64_64 1 | |
30 | #endif | |
31 | #ifndef R_BPF_64_32 | |
32 | #define R_BPF_64_32 10 | |
33 | #endif | |
34 | ||
35 | #ifndef SHT_LLVM_ADDRSIG | |
36 | #define SHT_LLVM_ADDRSIG 0x6FFF4C03 | |
37 | #endif | |
38 | ||
39 | /* if libelf is old and doesn't support mmap(), fall back to read() */ | |
40 | #ifndef ELF_C_READ_MMAP | |
41 | #define ELF_C_READ_MMAP ELF_C_READ | |
42 | #endif | |
43 | ||
d7c4b398 AN |
44 | #define BTF_INFO_ENC(kind, kind_flag, vlen) \ |
45 | ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN)) | |
46 | #define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type) | |
47 | #define BTF_INT_ENC(encoding, bits_offset, nr_bits) \ | |
48 | ((encoding) << 24 | (bits_offset) << 16 | (nr_bits)) | |
49 | #define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \ | |
50 | BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \ | |
51 | BTF_INT_ENC(encoding, bits_offset, bits) | |
52 | #define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset) | |
53 | #define BTF_PARAM_ENC(name, type) (name), (type) | |
54 | #define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size) | |
22541a9e IL |
55 | #define BTF_TYPE_FLOAT_ENC(name, sz) \ |
56 | BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_FLOAT, 0, 0), sz) | |
d7c4b398 | 57 | |
029258d7 AN |
58 | #ifndef likely |
59 | #define likely(x) __builtin_expect(!!(x), 1) | |
60 | #endif | |
61 | #ifndef unlikely | |
62 | #define unlikely(x) __builtin_expect(!!(x), 0) | |
63 | #endif | |
d7fe74f9 AN |
64 | #ifndef min |
65 | # define min(x, y) ((x) < (y) ? (x) : (y)) | |
66 | #endif | |
67 | #ifndef max | |
68 | # define max(x, y) ((x) < (y) ? (y) : (x)) | |
69 | #endif | |
4cedc0da AN |
70 | #ifndef offsetofend |
71 | # define offsetofend(TYPE, FIELD) \ | |
72 | (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD)) | |
73 | #endif | |
d7fe74f9 | 74 | |
1bd63524 YS |
75 | /* Symbol versioning is different between static and shared library. |
76 | * Properly versioned symbols are needed for shared library, but | |
77 | * only the symbol of the new version is needed for static library. | |
78 | */ | |
79 | #ifdef SHARED | |
80 | # define COMPAT_VERSION(internal_name, api_name, version) \ | |
81 | asm(".symver " #internal_name "," #api_name "@" #version); | |
82 | # define DEFAULT_VERSION(internal_name, api_name, version) \ | |
83 | asm(".symver " #internal_name "," #api_name "@@" #version); | |
84 | #else | |
85 | # define COMPAT_VERSION(internal_name, api_name, version) | |
86 | # define DEFAULT_VERSION(internal_name, api_name, version) \ | |
87 | extern typeof(internal_name) api_name \ | |
88 | __attribute__((alias(#internal_name))); | |
89 | #endif | |
90 | ||
d72386fe AN |
91 | extern void libbpf_print(enum libbpf_print_level level, |
92 | const char *format, ...) | |
93 | __attribute__((format(printf, 2, 3))); | |
94 | ||
95 | #define __pr(level, fmt, ...) \ | |
96 | do { \ | |
97 | libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__); \ | |
98 | } while (0) | |
99 | ||
be18010e | 100 | #define pr_warn(fmt, ...) __pr(LIBBPF_WARN, fmt, ##__VA_ARGS__) |
d72386fe AN |
101 | #define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__) |
102 | #define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__) | |
103 | ||
dda1ec9f AN |
104 | #ifndef __has_builtin |
105 | #define __has_builtin(x) 0 | |
106 | #endif | |
029258d7 AN |
107 | /* |
108 | * Re-implement glibc's reallocarray() for libbpf internal-only use. | |
109 | * reallocarray(), unfortunately, is not available in all versions of glibc, | |
110 | * so requires extra feature detection and using reallocarray() stub from | |
111 | * <tools/libc_compat.h> and COMPAT_NEED_REALLOCARRAY. All this complicates | |
112 | * build of libbpf unnecessarily and is just a maintenance burden. Instead, | |
113 | * it's trivial to implement libbpf-specific internal version and use it | |
114 | * throughout libbpf. | |
115 | */ | |
116 | static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size) | |
117 | { | |
118 | size_t total; | |
119 | ||
dda1ec9f | 120 | #if __has_builtin(__builtin_mul_overflow) |
029258d7 AN |
121 | if (unlikely(__builtin_mul_overflow(nmemb, size, &total))) |
122 | return NULL; | |
dda1ec9f AN |
123 | #else |
124 | if (size == 0 || nmemb > ULONG_MAX / size) | |
125 | return NULL; | |
126 | total = nmemb * size; | |
127 | #endif | |
029258d7 AN |
128 | return realloc(ptr, total); |
129 | } | |
130 | ||
e14ef4bf AN |
131 | struct btf; |
132 | struct btf_type; | |
133 | ||
134 | struct btf_type *btf_type_by_id(struct btf *btf, __u32 type_id); | |
135 | ||
aea28a60 AN |
136 | static inline __u32 btf_type_info(int kind, int vlen, int kflag) |
137 | { | |
138 | return (kflag << 31) | (kind << 24) | vlen; | |
139 | } | |
140 | ||
c7ef5ec9 AN |
141 | enum map_def_parts { |
142 | MAP_DEF_MAP_TYPE = 0x001, | |
143 | MAP_DEF_KEY_TYPE = 0x002, | |
144 | MAP_DEF_KEY_SIZE = 0x004, | |
145 | MAP_DEF_VALUE_TYPE = 0x008, | |
146 | MAP_DEF_VALUE_SIZE = 0x010, | |
147 | MAP_DEF_MAX_ENTRIES = 0x020, | |
148 | MAP_DEF_MAP_FLAGS = 0x040, | |
149 | MAP_DEF_NUMA_NODE = 0x080, | |
150 | MAP_DEF_PINNING = 0x100, | |
151 | MAP_DEF_INNER_MAP = 0x200, | |
152 | ||
153 | MAP_DEF_ALL = 0x3ff, /* combination of all above */ | |
154 | }; | |
155 | ||
156 | struct btf_map_def { | |
157 | enum map_def_parts parts; | |
158 | __u32 map_type; | |
159 | __u32 key_type_id; | |
160 | __u32 key_size; | |
161 | __u32 value_type_id; | |
162 | __u32 value_size; | |
163 | __u32 max_entries; | |
164 | __u32 map_flags; | |
165 | __u32 numa_node; | |
166 | __u32 pinning; | |
167 | }; | |
168 | ||
169 | int parse_btf_map_def(const char *map_name, struct btf *btf, | |
170 | const struct btf_type *def_t, bool strict, | |
171 | struct btf_map_def *map_def, struct btf_map_def *inner_def); | |
172 | ||
3b029e06 AN |
173 | void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz, |
174 | size_t cur_cnt, size_t max_cnt, size_t add_cnt); | |
175 | int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt); | |
192f5a1f | 176 | |
2ce8450e AN |
177 | static inline bool libbpf_validate_opts(const char *opts, |
178 | size_t opts_sz, size_t user_sz, | |
179 | const char *type_name) | |
180 | { | |
181 | if (user_sz < sizeof(size_t)) { | |
be18010e | 182 | pr_warn("%s size (%zu) is too small\n", type_name, user_sz); |
2ce8450e AN |
183 | return false; |
184 | } | |
185 | if (user_sz > opts_sz) { | |
186 | size_t i; | |
187 | ||
188 | for (i = opts_sz; i < user_sz; i++) { | |
189 | if (opts[i]) { | |
12dd14b2 | 190 | pr_warn("%s has non-zero extra bytes\n", |
be18010e | 191 | type_name); |
2ce8450e AN |
192 | return false; |
193 | } | |
194 | } | |
195 | } | |
196 | return true; | |
197 | } | |
198 | ||
199 | #define OPTS_VALID(opts, type) \ | |
200 | (!(opts) || libbpf_validate_opts((const char *)opts, \ | |
201 | offsetofend(struct type, \ | |
202 | type##__last_field), \ | |
203 | (opts)->sz, #type)) | |
204 | #define OPTS_HAS(opts, field) \ | |
205 | ((opts) && opts->sz >= offsetofend(typeof(*(opts)), field)) | |
206 | #define OPTS_GET(opts, field, fallback_value) \ | |
207 | (OPTS_HAS(opts, field) ? (opts)->field : fallback_value) | |
88f7fe72 SL |
208 | #define OPTS_SET(opts, field, value) \ |
209 | do { \ | |
210 | if (OPTS_HAS(opts, field)) \ | |
211 | (opts)->field = value; \ | |
212 | } while (0) | |
2ce8450e | 213 | |
6803ee25 AN |
214 | int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz); |
215 | int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz); | |
cfd49210 MR |
216 | int libbpf__load_raw_btf(const char *raw_types, size_t types_len, |
217 | const char *str_sec, size_t str_len); | |
d7c4b398 | 218 | |
6aef10a4 AN |
219 | struct bpf_prog_load_params { |
220 | enum bpf_prog_type prog_type; | |
221 | enum bpf_attach_type expected_attach_type; | |
222 | const char *name; | |
223 | const struct bpf_insn *insns; | |
224 | size_t insn_cnt; | |
225 | const char *license; | |
226 | __u32 kern_version; | |
227 | __u32 attach_prog_fd; | |
91abb4a6 | 228 | __u32 attach_btf_obj_fd; |
6aef10a4 AN |
229 | __u32 attach_btf_id; |
230 | __u32 prog_ifindex; | |
231 | __u32 prog_btf_fd; | |
232 | __u32 prog_flags; | |
233 | ||
234 | __u32 func_info_rec_size; | |
235 | const void *func_info; | |
236 | __u32 func_info_cnt; | |
237 | ||
238 | __u32 line_info_rec_size; | |
239 | const void *line_info; | |
240 | __u32 line_info_cnt; | |
241 | ||
242 | __u32 log_level; | |
243 | char *log_buf; | |
244 | size_t log_buf_sz; | |
245 | }; | |
246 | ||
247 | int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr); | |
248 | ||
612d05be AN |
249 | int bpf_object__section_size(const struct bpf_object *obj, const char *name, |
250 | __u32 *size); | |
251 | int bpf_object__variable_offset(const struct bpf_object *obj, const char *name, | |
252 | __u32 *off); | |
a19f93cf | 253 | struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf); |
612d05be | 254 | |
4cedc0da AN |
255 | struct btf_ext_info { |
256 | /* | |
257 | * info points to the individual info section (e.g. func_info and | |
258 | * line_info) from the .BTF.ext. It does not include the __u32 rec_size. | |
259 | */ | |
260 | void *info; | |
261 | __u32 rec_size; | |
262 | __u32 len; | |
263 | }; | |
264 | ||
265 | #define for_each_btf_ext_sec(seg, sec) \ | |
266 | for (sec = (seg)->info; \ | |
267 | (void *)sec < (seg)->info + (seg)->len; \ | |
268 | sec = (void *)sec + sizeof(struct btf_ext_info_sec) + \ | |
269 | (seg)->rec_size * sec->num_info) | |
270 | ||
271 | #define for_each_btf_ext_rec(seg, sec, i, rec) \ | |
272 | for (i = 0, rec = (void *)&(sec)->data; \ | |
273 | i < (sec)->num_info; \ | |
274 | i++, rec = (void *)rec + (seg)->rec_size) | |
275 | ||
28b93c64 AN |
276 | /* |
277 | * The .BTF.ext ELF section layout defined as | |
278 | * struct btf_ext_header | |
279 | * func_info subsection | |
280 | * | |
281 | * The func_info subsection layout: | |
282 | * record size for struct bpf_func_info in the func_info subsection | |
283 | * struct btf_sec_func_info for section #1 | |
284 | * a list of bpf_func_info records for section #1 | |
285 | * where struct bpf_func_info mimics one in include/uapi/linux/bpf.h | |
286 | * but may not be identical | |
287 | * struct btf_sec_func_info for section #2 | |
288 | * a list of bpf_func_info records for section #2 | |
289 | * ...... | |
290 | * | |
291 | * Note that the bpf_func_info record size in .BTF.ext may not | |
292 | * be the same as the one defined in include/uapi/linux/bpf.h. | |
293 | * The loader should ensure that record_size meets minimum | |
294 | * requirement and pass the record as is to the kernel. The | |
295 | * kernel will handle the func_info properly based on its contents. | |
296 | */ | |
297 | struct btf_ext_header { | |
298 | __u16 magic; | |
299 | __u8 version; | |
300 | __u8 flags; | |
301 | __u32 hdr_len; | |
302 | ||
303 | /* All offsets are in bytes relative to the end of this header */ | |
304 | __u32 func_info_off; | |
305 | __u32 func_info_len; | |
306 | __u32 line_info_off; | |
307 | __u32 line_info_len; | |
308 | ||
309 | /* optional part of .BTF.ext header */ | |
310 | __u32 core_relo_off; | |
311 | __u32 core_relo_len; | |
312 | }; | |
313 | ||
4cedc0da AN |
314 | struct btf_ext { |
315 | union { | |
316 | struct btf_ext_header *hdr; | |
317 | void *data; | |
318 | }; | |
319 | struct btf_ext_info func_info; | |
320 | struct btf_ext_info line_info; | |
28b93c64 | 321 | struct btf_ext_info core_relo_info; |
4cedc0da AN |
322 | __u32 data_size; |
323 | }; | |
324 | ||
325 | struct btf_ext_info_sec { | |
326 | __u32 sec_name_off; | |
327 | __u32 num_info; | |
328 | /* Followed by num_info * record_size number of bytes */ | |
385bbf7b | 329 | __u8 data[]; |
4cedc0da AN |
330 | }; |
331 | ||
332 | /* The minimum bpf_func_info checked by the loader */ | |
333 | struct bpf_func_info_min { | |
334 | __u32 insn_off; | |
335 | __u32 type_id; | |
336 | }; | |
337 | ||
338 | /* The minimum bpf_line_info checked by the loader */ | |
339 | struct bpf_line_info_min { | |
340 | __u32 insn_off; | |
341 | __u32 file_name_off; | |
342 | __u32 line_off; | |
343 | __u32 line_col; | |
344 | }; | |
345 | ||
28b93c64 AN |
346 | /* bpf_core_relo_kind encodes which aspect of captured field/type/enum value |
347 | * has to be adjusted by relocations. | |
511bb008 | 348 | */ |
28b93c64 | 349 | enum bpf_core_relo_kind { |
511bb008 | 350 | BPF_FIELD_BYTE_OFFSET = 0, /* field byte offset */ |
28b93c64 | 351 | BPF_FIELD_BYTE_SIZE = 1, /* field size in bytes */ |
511bb008 | 352 | BPF_FIELD_EXISTS = 2, /* field existence in target kernel */ |
28b93c64 AN |
353 | BPF_FIELD_SIGNED = 3, /* field signedness (0 - unsigned, 1 - signed) */ |
354 | BPF_FIELD_LSHIFT_U64 = 4, /* bitfield-specific left bitshift */ | |
355 | BPF_FIELD_RSHIFT_U64 = 5, /* bitfield-specific right bitshift */ | |
3fc32f40 AN |
356 | BPF_TYPE_ID_LOCAL = 6, /* type ID in local BPF object */ |
357 | BPF_TYPE_ID_TARGET = 7, /* type ID in target kernel */ | |
358 | BPF_TYPE_EXISTS = 8, /* type existence in target kernel */ | |
359 | BPF_TYPE_SIZE = 9, /* type size in bytes */ | |
eacaaed7 AN |
360 | BPF_ENUMVAL_EXISTS = 10, /* enum value existence in target kernel */ |
361 | BPF_ENUMVAL_VALUE = 11, /* enum value integer value */ | |
511bb008 AN |
362 | }; |
363 | ||
28b93c64 | 364 | /* The minimum bpf_core_relo checked by the loader |
4cedc0da | 365 | * |
28b93c64 | 366 | * CO-RE relocation captures the following data: |
4cedc0da | 367 | * - insn_off - instruction offset (in bytes) within a BPF program that needs |
511bb008 | 368 | * its insn->imm field to be relocated with actual field info; |
4cedc0da | 369 | * - type_id - BTF type ID of the "root" (containing) entity of a relocatable |
28b93c64 | 370 | * type or field; |
4cedc0da | 371 | * - access_str_off - offset into corresponding .BTF string section. String |
28b93c64 AN |
372 | * interpretation depends on specific relocation kind: |
373 | * - for field-based relocations, string encodes an accessed field using | |
374 | * a sequence of field and array indices, separated by colon (:). It's | |
375 | * conceptually very close to LLVM's getelementptr ([0]) instruction's | |
376 | * arguments for identifying offset to a field. | |
377 | * - for type-based relocations, strings is expected to be just "0"; | |
378 | * - for enum value-based relocations, string contains an index of enum | |
379 | * value within its enum type; | |
4cedc0da AN |
380 | * |
381 | * Example to provide a better feel. | |
382 | * | |
383 | * struct sample { | |
384 | * int a; | |
385 | * struct { | |
386 | * int b[10]; | |
387 | * }; | |
388 | * }; | |
389 | * | |
390 | * struct sample *s = ...; | |
391 | * int x = &s->a; // encoded as "0:0" (a is field #0) | |
392 | * int y = &s->b[5]; // encoded as "0:1:0:5" (anon struct is field #1, | |
393 | * // b is field #0 inside anon struct, accessing elem #5) | |
394 | * int z = &s[10]->b; // encoded as "10:1" (ptr is used as an array) | |
395 | * | |
396 | * type_id for all relocs in this example will capture BTF type id of | |
397 | * `struct sample`. | |
398 | * | |
399 | * Such relocation is emitted when using __builtin_preserve_access_index() | |
400 | * Clang built-in, passing expression that captures field address, e.g.: | |
401 | * | |
402 | * bpf_probe_read(&dst, sizeof(dst), | |
403 | * __builtin_preserve_access_index(&src->a.b.c)); | |
404 | * | |
511bb008 | 405 | * In this case Clang will emit field relocation recording necessary data to |
4cedc0da AN |
406 | * be able to find offset of embedded `a.b.c` field within `src` struct. |
407 | * | |
408 | * [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction | |
409 | */ | |
28b93c64 | 410 | struct bpf_core_relo { |
4cedc0da AN |
411 | __u32 insn_off; |
412 | __u32 type_id; | |
413 | __u32 access_str_off; | |
28b93c64 | 414 | enum bpf_core_relo_kind kind; |
4cedc0da AN |
415 | }; |
416 | ||
f36e99a4 AN |
417 | typedef int (*type_id_visit_fn)(__u32 *type_id, void *ctx); |
418 | typedef int (*str_off_visit_fn)(__u32 *str_off, void *ctx); | |
419 | int btf_type_visit_type_ids(struct btf_type *t, type_id_visit_fn visit, void *ctx); | |
420 | int btf_type_visit_str_offs(struct btf_type *t, str_off_visit_fn visit, void *ctx); | |
421 | int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx); | |
422 | int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx); | |
423 | ||
d7c4b398 | 424 | #endif /* __LIBBPF_LIBBPF_INTERNAL_H */ |