blob: aeb79e3a8ff994b985cb2b08d3103fb261b2f309 [file] [log] [blame]
Andrii Nakryikod7c4b392019-05-10 14:13:15 -07001/* 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
Andrii Nakryiko029258d2020-08-18 18:36:04 -070012#include <stdlib.h>
Andrii Nakryikodda1ec92020-08-19 23:14:09 -070013#include <limits.h>
Andrii Nakryikof12b6542021-05-24 20:59:33 -070014#include <errno.h>
15#include <linux/err.h>
Kumar Kartikeya Dwivedi549a6322021-10-28 12:04:57 +053016#include <fcntl.h>
17#include <unistd.h>
Andrii Nakryikof12b6542021-05-24 20:59:33 -070018#include "libbpf_legacy.h"
Alexei Starovoitov301ba4d2021-07-20 17:08:21 -070019#include "relo_core.h"
Andrii Nakryiko85367032020-08-18 18:36:06 -070020
21/* make sure libbpf doesn't use kernel-only integer typedefs */
22#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
23
24/* prevent accidental re-addition of reallocarray() */
25#pragma GCC poison reallocarray
26
Andrii Nakryiko1d7a08b2019-05-24 11:58:56 -070027#include "libbpf.h"
Andrii Nakryikoaea28a62021-04-23 11:13:34 -070028#include "btf.h"
Andrii Nakryiko1d7a08b2019-05-24 11:58:56 -070029
Andrii Nakryikofaf6ed32021-03-18 12:40:30 -070030#ifndef EM_BPF
31#define EM_BPF 247
32#endif
33
34#ifndef R_BPF_64_64
35#define R_BPF_64_64 1
36#endif
Yonghong Song9f0c3172021-05-22 09:23:41 -070037#ifndef R_BPF_64_ABS64
38#define R_BPF_64_ABS64 2
39#endif
40#ifndef R_BPF_64_ABS32
41#define R_BPF_64_ABS32 3
42#endif
Andrii Nakryikofaf6ed32021-03-18 12:40:30 -070043#ifndef R_BPF_64_32
44#define R_BPF_64_32 10
45#endif
46
47#ifndef SHT_LLVM_ADDRSIG
48#define SHT_LLVM_ADDRSIG 0x6FFF4C03
49#endif
50
51/* if libelf is old and doesn't support mmap(), fall back to read() */
52#ifndef ELF_C_READ_MMAP
53#define ELF_C_READ_MMAP ELF_C_READ
54#endif
55
Arnaldo Carvalho de Melo67e7ec02021-05-08 12:22:12 -030056/* Older libelf all end up in this expression, for both 32 and 64 bit */
Andrii Nakryikoad23b722021-10-20 18:43:57 -070057#ifndef ELF64_ST_VISIBILITY
58#define ELF64_ST_VISIBILITY(o) ((o) & 0x03)
Arnaldo Carvalho de Melo67e7ec02021-05-08 12:22:12 -030059#endif
60
Andrii Nakryikod7c4b392019-05-10 14:13:15 -070061#define BTF_INFO_ENC(kind, kind_flag, vlen) \
62 ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
63#define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
64#define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
65 ((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
66#define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
67 BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
68 BTF_INT_ENC(encoding, bits_offset, bits)
69#define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset)
70#define BTF_PARAM_ENC(name, type) (name), (type)
71#define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size)
Ilya Leoshkevich22541a92021-02-26 21:22:49 +010072#define BTF_TYPE_FLOAT_ENC(name, sz) \
73 BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_FLOAT, 0, 0), sz)
Yonghong Song223f9032021-10-12 09:48:38 -070074#define BTF_TYPE_DECL_TAG_ENC(value, type, component_idx) \
75 BTF_TYPE_ENC(value, BTF_INFO_ENC(BTF_KIND_DECL_TAG, 0, 0), type), (component_idx)
Andrii Nakryikod7c4b392019-05-10 14:13:15 -070076
Andrii Nakryiko029258d2020-08-18 18:36:04 -070077#ifndef likely
78#define likely(x) __builtin_expect(!!(x), 1)
79#endif
80#ifndef unlikely
81#define unlikely(x) __builtin_expect(!!(x), 0)
82#endif
Andrii Nakryikod7fe74f2019-06-17 12:26:50 -070083#ifndef min
84# define min(x, y) ((x) < (y) ? (x) : (y))
85#endif
86#ifndef max
87# define max(x, y) ((x) < (y) ? (y) : (x))
88#endif
Andrii Nakryiko4cedc0d2019-08-07 14:39:50 -070089#ifndef offsetofend
90# define offsetofend(TYPE, FIELD) \
91 (offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
92#endif
Andrii Nakryikod7fe74f2019-06-17 12:26:50 -070093
Andrii Nakryiko13d35a02021-09-28 09:19:42 -070094/* Check whether a string `str` has prefix `pfx`, regardless if `pfx` is
95 * a string literal known at compilation time or char * pointer known only at
96 * runtime.
97 */
98#define str_has_pfx(str, pfx) \
99 (strncmp(str, pfx, __builtin_constant_p(pfx) ? sizeof(pfx) - 1 : strlen(pfx)) == 0)
100
Yonghong Song1bd63522019-09-30 14:02:03 -0700101/* Symbol versioning is different between static and shared library.
102 * Properly versioned symbols are needed for shared library, but
103 * only the symbol of the new version is needed for static library.
Andrii Nakryiko006a5092021-09-07 15:10:23 -0700104 * Starting with GNU C 10, use symver attribute instead of .symver assembler
105 * directive, which works better with GCC LTO builds.
Yonghong Song1bd63522019-09-30 14:02:03 -0700106 */
Andrii Nakryiko006a5092021-09-07 15:10:23 -0700107#if defined(SHARED) && defined(__GNUC__) && __GNUC__ >= 10
108
109#define DEFAULT_VERSION(internal_name, api_name, version) \
110 __attribute__((symver(#api_name "@@" #version)))
111#define COMPAT_VERSION(internal_name, api_name, version) \
112 __attribute__((symver(#api_name "@" #version)))
113
114#elif defined(SHARED)
115
116#define COMPAT_VERSION(internal_name, api_name, version) \
Yonghong Song1bd63522019-09-30 14:02:03 -0700117 asm(".symver " #internal_name "," #api_name "@" #version);
Andrii Nakryiko006a5092021-09-07 15:10:23 -0700118#define DEFAULT_VERSION(internal_name, api_name, version) \
Yonghong Song1bd63522019-09-30 14:02:03 -0700119 asm(".symver " #internal_name "," #api_name "@@" #version);
Andrii Nakryiko006a5092021-09-07 15:10:23 -0700120
121#else /* !SHARED */
122
123#define COMPAT_VERSION(internal_name, api_name, version)
124#define DEFAULT_VERSION(internal_name, api_name, version) \
Yonghong Song1bd63522019-09-30 14:02:03 -0700125 extern typeof(internal_name) api_name \
126 __attribute__((alias(#internal_name)));
Andrii Nakryiko006a5092021-09-07 15:10:23 -0700127
Yonghong Song1bd63522019-09-30 14:02:03 -0700128#endif
129
Andrii Nakryikod72386f2019-05-15 20:39:27 -0700130extern void libbpf_print(enum libbpf_print_level level,
131 const char *format, ...)
132 __attribute__((format(printf, 2, 3)));
133
134#define __pr(level, fmt, ...) \
135do { \
136 libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__); \
137} while (0)
138
Kefeng Wangbe180102019-10-21 13:55:32 +0800139#define pr_warn(fmt, ...) __pr(LIBBPF_WARN, fmt, ##__VA_ARGS__)
Andrii Nakryikod72386f2019-05-15 20:39:27 -0700140#define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
141#define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
142
Andrii Nakryikodda1ec92020-08-19 23:14:09 -0700143#ifndef __has_builtin
144#define __has_builtin(x) 0
145#endif
Andrii Nakryiko029258d2020-08-18 18:36:04 -0700146/*
147 * Re-implement glibc's reallocarray() for libbpf internal-only use.
148 * reallocarray(), unfortunately, is not available in all versions of glibc,
149 * so requires extra feature detection and using reallocarray() stub from
150 * <tools/libc_compat.h> and COMPAT_NEED_REALLOCARRAY. All this complicates
151 * build of libbpf unnecessarily and is just a maintenance burden. Instead,
152 * it's trivial to implement libbpf-specific internal version and use it
153 * throughout libbpf.
154 */
155static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size)
156{
157 size_t total;
158
Andrii Nakryikodda1ec92020-08-19 23:14:09 -0700159#if __has_builtin(__builtin_mul_overflow)
Andrii Nakryiko029258d2020-08-18 18:36:04 -0700160 if (unlikely(__builtin_mul_overflow(nmemb, size, &total)))
161 return NULL;
Andrii Nakryikodda1ec92020-08-19 23:14:09 -0700162#else
163 if (size == 0 || nmemb > ULONG_MAX / size)
164 return NULL;
165 total = nmemb * size;
166#endif
Andrii Nakryiko029258d2020-08-18 18:36:04 -0700167 return realloc(ptr, total);
168}
169
Andrii Nakryikoe14ef4b2021-03-18 12:40:25 -0700170struct btf;
171struct btf_type;
172
173struct btf_type *btf_type_by_id(struct btf *btf, __u32 type_id);
Andrii Nakryiko42869d22021-04-23 11:13:38 -0700174const char *btf_kind_str(const struct btf_type *t);
175const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id);
176
177static inline enum btf_func_linkage btf_func_linkage(const struct btf_type *t)
178{
179 return (enum btf_func_linkage)(int)btf_vlen(t);
180}
Andrii Nakryikoe14ef4b2021-03-18 12:40:25 -0700181
Andrii Nakryikoaea28a62021-04-23 11:13:34 -0700182static inline __u32 btf_type_info(int kind, int vlen, int kflag)
183{
184 return (kflag << 31) | (kind << 24) | vlen;
185}
186
Andrii Nakryikoc7ef5ec2021-04-23 11:13:36 -0700187enum map_def_parts {
188 MAP_DEF_MAP_TYPE = 0x001,
189 MAP_DEF_KEY_TYPE = 0x002,
190 MAP_DEF_KEY_SIZE = 0x004,
191 MAP_DEF_VALUE_TYPE = 0x008,
192 MAP_DEF_VALUE_SIZE = 0x010,
193 MAP_DEF_MAX_ENTRIES = 0x020,
194 MAP_DEF_MAP_FLAGS = 0x040,
195 MAP_DEF_NUMA_NODE = 0x080,
196 MAP_DEF_PINNING = 0x100,
197 MAP_DEF_INNER_MAP = 0x200,
Joanne Koong47512102021-10-27 16:45:01 -0700198 MAP_DEF_MAP_EXTRA = 0x400,
Andrii Nakryikoc7ef5ec2021-04-23 11:13:36 -0700199
Joanne Koong47512102021-10-27 16:45:01 -0700200 MAP_DEF_ALL = 0x7ff, /* combination of all above */
Andrii Nakryikoc7ef5ec2021-04-23 11:13:36 -0700201};
202
203struct btf_map_def {
204 enum map_def_parts parts;
205 __u32 map_type;
206 __u32 key_type_id;
207 __u32 key_size;
208 __u32 value_type_id;
209 __u32 value_size;
210 __u32 max_entries;
211 __u32 map_flags;
212 __u32 numa_node;
213 __u32 pinning;
Joanne Koong47512102021-10-27 16:45:01 -0700214 __u64 map_extra;
Andrii Nakryikoc7ef5ec2021-04-23 11:13:36 -0700215};
216
217int parse_btf_map_def(const char *map_name, struct btf *btf,
218 const struct btf_type *def_t, bool strict,
219 struct btf_map_def *map_def, struct btf_map_def *inner_def);
220
Andrii Nakryiko3b029e02021-03-18 12:40:27 -0700221void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz,
222 size_t cur_cnt, size_t max_cnt, size_t add_cnt);
223int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt);
Andrii Nakryiko192f5a12020-09-25 18:13:51 -0700224
Andrii Nakryiko3ec84f42021-08-15 00:06:03 -0700225static inline bool libbpf_is_mem_zeroed(const char *p, ssize_t len)
226{
227 while (len > 0) {
228 if (*p)
229 return false;
230 p++;
231 len--;
232 }
233 return true;
234}
235
Andrii Nakryiko2ce84502019-10-04 15:40:35 -0700236static inline bool libbpf_validate_opts(const char *opts,
237 size_t opts_sz, size_t user_sz,
238 const char *type_name)
239{
240 if (user_sz < sizeof(size_t)) {
Kefeng Wangbe180102019-10-21 13:55:32 +0800241 pr_warn("%s size (%zu) is too small\n", type_name, user_sz);
Andrii Nakryiko2ce84502019-10-04 15:40:35 -0700242 return false;
243 }
Andrii Nakryiko3ec84f42021-08-15 00:06:03 -0700244 if (!libbpf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) {
245 pr_warn("%s has non-zero extra bytes\n", type_name);
246 return false;
Andrii Nakryiko2ce84502019-10-04 15:40:35 -0700247 }
248 return true;
249}
250
251#define OPTS_VALID(opts, type) \
252 (!(opts) || libbpf_validate_opts((const char *)opts, \
253 offsetofend(struct type, \
254 type##__last_field), \
255 (opts)->sz, #type))
256#define OPTS_HAS(opts, field) \
257 ((opts) && opts->sz >= offsetofend(typeof(*(opts)), field))
258#define OPTS_GET(opts, field, fallback_value) \
259 (OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
Song Liu88f7fe72020-09-25 13:54:30 -0700260#define OPTS_SET(opts, field, value) \
261 do { \
262 if (OPTS_HAS(opts, field)) \
263 (opts)->field = value; \
264 } while (0)
Andrii Nakryiko2ce84502019-10-04 15:40:35 -0700265
Andrii Nakryiko3ec84f42021-08-15 00:06:03 -0700266#define OPTS_ZEROED(opts, last_nonzero_field) \
267({ \
268 ssize_t __off = offsetofend(typeof(*(opts)), last_nonzero_field); \
269 !(opts) || libbpf_is_mem_zeroed((const void *)opts + __off, \
270 (opts)->sz - __off); \
271})
272
273
Andrii Nakryiko6803ee22019-12-11 17:35:48 -0800274int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);
275int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);
Michal Rosteckicfd49212019-05-29 20:31:09 +0200276int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
277 const char *str_sec, size_t str_len);
Andrii Nakryikod7c4b392019-05-10 14:13:15 -0700278
Andrii Nakryiko6aef10a2020-12-03 12:46:31 -0800279struct bpf_prog_load_params {
280 enum bpf_prog_type prog_type;
281 enum bpf_attach_type expected_attach_type;
282 const char *name;
283 const struct bpf_insn *insns;
284 size_t insn_cnt;
285 const char *license;
286 __u32 kern_version;
287 __u32 attach_prog_fd;
Andrii Nakryiko91abb4a2020-12-03 12:46:32 -0800288 __u32 attach_btf_obj_fd;
Andrii Nakryiko6aef10a2020-12-03 12:46:31 -0800289 __u32 attach_btf_id;
290 __u32 prog_ifindex;
291 __u32 prog_btf_fd;
292 __u32 prog_flags;
293
294 __u32 func_info_rec_size;
295 const void *func_info;
296 __u32 func_info_cnt;
297
298 __u32 line_info_rec_size;
299 const void *line_info;
300 __u32 line_info_cnt;
301
302 __u32 log_level;
303 char *log_buf;
304 size_t log_buf_sz;
Kumar Kartikeya Dwivedi9dbe6012021-10-02 06:47:54 +0530305 int *fd_array;
Andrii Nakryiko6aef10a2020-12-03 12:46:31 -0800306};
307
308int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr);
309
Joanne Koong47512102021-10-27 16:45:01 -0700310struct bpf_create_map_params {
311 const char *name;
312 enum bpf_map_type map_type;
313 __u32 map_flags;
314 __u32 key_size;
315 __u32 value_size;
316 __u32 max_entries;
317 __u32 numa_node;
318 __u32 btf_fd;
319 __u32 btf_key_type_id;
320 __u32 btf_value_type_id;
321 __u32 map_ifindex;
322 union {
323 __u32 inner_map_fd;
324 __u32 btf_vmlinux_value_type_id;
325 };
326 __u64 map_extra;
327};
328
329int libbpf__bpf_create_map_xattr(const struct bpf_create_map_params *create_attr);
330
Andrii Nakryikoa19f93c2020-12-03 12:46:23 -0800331struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf);
Alexei Starovoitov67234742021-05-13 17:36:16 -0700332void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type,
333 const char **prefix, int *kind);
Andrii Nakryiko612d05b2019-12-13 17:43:27 -0800334
Andrii Nakryiko4cedc0d2019-08-07 14:39:50 -0700335struct btf_ext_info {
336 /*
337 * info points to the individual info section (e.g. func_info and
338 * line_info) from the .BTF.ext. It does not include the __u32 rec_size.
339 */
340 void *info;
341 __u32 rec_size;
342 __u32 len;
343};
344
345#define for_each_btf_ext_sec(seg, sec) \
346 for (sec = (seg)->info; \
347 (void *)sec < (seg)->info + (seg)->len; \
348 sec = (void *)sec + sizeof(struct btf_ext_info_sec) + \
349 (seg)->rec_size * sec->num_info)
350
351#define for_each_btf_ext_rec(seg, sec, i, rec) \
352 for (i = 0, rec = (void *)&(sec)->data; \
353 i < (sec)->num_info; \
354 i++, rec = (void *)rec + (seg)->rec_size)
355
Andrii Nakryiko28b93c62020-08-18 15:39:14 -0700356/*
357 * The .BTF.ext ELF section layout defined as
358 * struct btf_ext_header
359 * func_info subsection
360 *
361 * The func_info subsection layout:
362 * record size for struct bpf_func_info in the func_info subsection
363 * struct btf_sec_func_info for section #1
364 * a list of bpf_func_info records for section #1
365 * where struct bpf_func_info mimics one in include/uapi/linux/bpf.h
366 * but may not be identical
367 * struct btf_sec_func_info for section #2
368 * a list of bpf_func_info records for section #2
369 * ......
370 *
371 * Note that the bpf_func_info record size in .BTF.ext may not
372 * be the same as the one defined in include/uapi/linux/bpf.h.
373 * The loader should ensure that record_size meets minimum
374 * requirement and pass the record as is to the kernel. The
375 * kernel will handle the func_info properly based on its contents.
376 */
377struct btf_ext_header {
378 __u16 magic;
379 __u8 version;
380 __u8 flags;
381 __u32 hdr_len;
382
383 /* All offsets are in bytes relative to the end of this header */
384 __u32 func_info_off;
385 __u32 func_info_len;
386 __u32 line_info_off;
387 __u32 line_info_len;
388
389 /* optional part of .BTF.ext header */
390 __u32 core_relo_off;
391 __u32 core_relo_len;
392};
393
Andrii Nakryiko4cedc0d2019-08-07 14:39:50 -0700394struct btf_ext {
395 union {
396 struct btf_ext_header *hdr;
397 void *data;
398 };
399 struct btf_ext_info func_info;
400 struct btf_ext_info line_info;
Andrii Nakryiko28b93c62020-08-18 15:39:14 -0700401 struct btf_ext_info core_relo_info;
Andrii Nakryiko4cedc0d2019-08-07 14:39:50 -0700402 __u32 data_size;
403};
404
405struct btf_ext_info_sec {
406 __u32 sec_name_off;
407 __u32 num_info;
408 /* Followed by num_info * record_size number of bytes */
Gustavo A. R. Silva385bbf72020-05-07 13:50:57 -0500409 __u8 data[];
Andrii Nakryiko4cedc0d2019-08-07 14:39:50 -0700410};
411
412/* The minimum bpf_func_info checked by the loader */
413struct bpf_func_info_min {
414 __u32 insn_off;
415 __u32 type_id;
416};
417
418/* The minimum bpf_line_info checked by the loader */
419struct bpf_line_info_min {
420 __u32 insn_off;
421 __u32 file_name_off;
422 __u32 line_off;
423 __u32 line_col;
424};
425
Andrii Nakryiko4cedc0d2019-08-07 14:39:50 -0700426
Andrii Nakryikof36e99a2021-03-18 12:40:26 -0700427typedef int (*type_id_visit_fn)(__u32 *type_id, void *ctx);
428typedef int (*str_off_visit_fn)(__u32 *str_off, void *ctx);
429int btf_type_visit_type_ids(struct btf_type *t, type_id_visit_fn visit, void *ctx);
430int btf_type_visit_str_offs(struct btf_type *t, str_off_visit_fn visit, void *ctx);
431int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx);
432int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx);
Kumar Kartikeya Dwivedi9dbe6012021-10-02 06:47:54 +0530433__s32 btf__find_by_name_kind_own(const struct btf *btf, const char *type_name,
434 __u32 kind);
Andrii Nakryikof36e99a2021-03-18 12:40:26 -0700435
Andrii Nakryikof12b6542021-05-24 20:59:33 -0700436extern enum libbpf_strict_mode libbpf_mode;
437
438/* handle direct returned errors */
439static inline int libbpf_err(int ret)
440{
441 if (ret < 0)
442 errno = -ret;
443 return ret;
444}
445
446/* handle errno-based (e.g., syscall or libc) errors according to libbpf's
447 * strict mode settings
448 */
449static inline int libbpf_err_errno(int ret)
450{
451 if (libbpf_mode & LIBBPF_STRICT_DIRECT_ERRS)
452 /* errno is already assumed to be set on error */
453 return ret < 0 ? -errno : ret;
454
455 /* legacy: on error return -1 directly and don't touch errno */
456 return ret;
457}
458
Andrii Nakryikoe9fc3ce2021-05-24 20:59:34 -0700459/* handle error for pointer-returning APIs, err is assumed to be < 0 always */
460static inline void *libbpf_err_ptr(int err)
461{
462 /* set errno on error, this doesn't break anything */
463 errno = -err;
464
465 if (libbpf_mode & LIBBPF_STRICT_CLEAN_PTRS)
466 return NULL;
467
468 /* legacy: encode err as ptr */
469 return ERR_PTR(err);
470}
471
472/* handle pointer-returning APIs' error handling */
473static inline void *libbpf_ptr(void *ret)
474{
475 /* set errno on error, this doesn't break anything */
476 if (IS_ERR(ret))
477 errno = -PTR_ERR(ret);
478
479 if (libbpf_mode & LIBBPF_STRICT_CLEAN_PTRS)
480 return IS_ERR(ret) ? NULL : ret;
481
482 /* legacy: pass-through original pointer */
483 return ret;
484}
485
Alexei Starovoitovb0588392021-07-20 17:08:22 -0700486static inline bool str_is_empty(const char *s)
487{
488 return !s || !s[0];
489}
490
491static inline bool is_ldimm64_insn(struct bpf_insn *insn)
492{
493 return insn->code == (BPF_LD | BPF_IMM | BPF_DW);
494}
495
Kumar Kartikeya Dwivedi549a6322021-10-28 12:04:57 +0530496/* if fd is stdin, stdout, or stderr, dup to a fd greater than 2
497 * Takes ownership of the fd passed in, and closes it if calling
498 * fcntl(fd, F_DUPFD_CLOEXEC, 3).
499 */
500static inline int ensure_good_fd(int fd)
501{
502 int old_fd = fd, saved_errno;
503
504 if (fd < 0)
505 return fd;
506 if (fd < 3) {
507 fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
508 saved_errno = errno;
509 close(old_fd);
510 if (fd < 0) {
511 pr_warn("failed to dup FD %d to FD > 2: %d\n", old_fd, -saved_errno);
512 errno = saved_errno;
513 }
514 }
515 return fd;
516}
517
Andrii Nakryikod7c4b392019-05-10 14:13:15 -0700518#endif /* __LIBBPF_LIBBPF_INTERNAL_H */