xref: /openbmc/linux/tools/lib/bpf/libbpf_internal.h (revision 67234743)
1d7c4b398SAndrii Nakryiko /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2d7c4b398SAndrii Nakryiko 
3d7c4b398SAndrii Nakryiko /*
4d7c4b398SAndrii Nakryiko  * Internal libbpf helpers.
5d7c4b398SAndrii Nakryiko  *
6d7c4b398SAndrii Nakryiko  * Copyright (c) 2019 Facebook
7d7c4b398SAndrii Nakryiko  */
8d7c4b398SAndrii Nakryiko 
9d7c4b398SAndrii Nakryiko #ifndef __LIBBPF_LIBBPF_INTERNAL_H
10d7c4b398SAndrii Nakryiko #define __LIBBPF_LIBBPF_INTERNAL_H
11d7c4b398SAndrii Nakryiko 
12029258d7SAndrii Nakryiko #include <stdlib.h>
13dda1ec9fSAndrii Nakryiko #include <limits.h>
1485367030SAndrii Nakryiko 
1585367030SAndrii Nakryiko /* make sure libbpf doesn't use kernel-only integer typedefs */
1685367030SAndrii Nakryiko #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
1785367030SAndrii Nakryiko 
1885367030SAndrii Nakryiko /* prevent accidental re-addition of reallocarray() */
1985367030SAndrii Nakryiko #pragma GCC poison reallocarray
2085367030SAndrii Nakryiko 
211d7a08b3SAndrii Nakryiko #include "libbpf.h"
22aea28a60SAndrii Nakryiko #include "btf.h"
231d7a08b3SAndrii Nakryiko 
24faf6ed32SAndrii Nakryiko #ifndef EM_BPF
25faf6ed32SAndrii Nakryiko #define EM_BPF 247
26faf6ed32SAndrii Nakryiko #endif
27faf6ed32SAndrii Nakryiko 
28faf6ed32SAndrii Nakryiko #ifndef R_BPF_64_64
29faf6ed32SAndrii Nakryiko #define R_BPF_64_64 1
30faf6ed32SAndrii Nakryiko #endif
31faf6ed32SAndrii Nakryiko #ifndef R_BPF_64_32
32faf6ed32SAndrii Nakryiko #define R_BPF_64_32 10
33faf6ed32SAndrii Nakryiko #endif
34faf6ed32SAndrii Nakryiko 
35faf6ed32SAndrii Nakryiko #ifndef SHT_LLVM_ADDRSIG
36faf6ed32SAndrii Nakryiko #define SHT_LLVM_ADDRSIG 0x6FFF4C03
37faf6ed32SAndrii Nakryiko #endif
38faf6ed32SAndrii Nakryiko 
39faf6ed32SAndrii Nakryiko /* if libelf is old and doesn't support mmap(), fall back to read() */
40faf6ed32SAndrii Nakryiko #ifndef ELF_C_READ_MMAP
41faf6ed32SAndrii Nakryiko #define ELF_C_READ_MMAP ELF_C_READ
42faf6ed32SAndrii Nakryiko #endif
43faf6ed32SAndrii Nakryiko 
44d7c4b398SAndrii Nakryiko #define BTF_INFO_ENC(kind, kind_flag, vlen) \
45d7c4b398SAndrii Nakryiko 	((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
46d7c4b398SAndrii Nakryiko #define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
47d7c4b398SAndrii Nakryiko #define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
48d7c4b398SAndrii Nakryiko 	((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
49d7c4b398SAndrii Nakryiko #define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
50d7c4b398SAndrii Nakryiko 	BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
51d7c4b398SAndrii Nakryiko 	BTF_INT_ENC(encoding, bits_offset, bits)
52d7c4b398SAndrii Nakryiko #define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset)
53d7c4b398SAndrii Nakryiko #define BTF_PARAM_ENC(name, type) (name), (type)
54d7c4b398SAndrii Nakryiko #define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size)
5522541a9eSIlya Leoshkevich #define BTF_TYPE_FLOAT_ENC(name, sz) \
5622541a9eSIlya Leoshkevich 	BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_FLOAT, 0, 0), sz)
57d7c4b398SAndrii Nakryiko 
58029258d7SAndrii Nakryiko #ifndef likely
59029258d7SAndrii Nakryiko #define likely(x) __builtin_expect(!!(x), 1)
60029258d7SAndrii Nakryiko #endif
61029258d7SAndrii Nakryiko #ifndef unlikely
62029258d7SAndrii Nakryiko #define unlikely(x) __builtin_expect(!!(x), 0)
63029258d7SAndrii Nakryiko #endif
64d7fe74f9SAndrii Nakryiko #ifndef min
65d7fe74f9SAndrii Nakryiko # define min(x, y) ((x) < (y) ? (x) : (y))
66d7fe74f9SAndrii Nakryiko #endif
67d7fe74f9SAndrii Nakryiko #ifndef max
68d7fe74f9SAndrii Nakryiko # define max(x, y) ((x) < (y) ? (y) : (x))
69d7fe74f9SAndrii Nakryiko #endif
704cedc0daSAndrii Nakryiko #ifndef offsetofend
714cedc0daSAndrii Nakryiko # define offsetofend(TYPE, FIELD) \
724cedc0daSAndrii Nakryiko 	(offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
734cedc0daSAndrii Nakryiko #endif
74d7fe74f9SAndrii Nakryiko 
751bd63524SYonghong Song /* Symbol versioning is different between static and shared library.
761bd63524SYonghong Song  * Properly versioned symbols are needed for shared library, but
771bd63524SYonghong Song  * only the symbol of the new version is needed for static library.
781bd63524SYonghong Song  */
791bd63524SYonghong Song #ifdef SHARED
801bd63524SYonghong Song # define COMPAT_VERSION(internal_name, api_name, version) \
811bd63524SYonghong Song 	asm(".symver " #internal_name "," #api_name "@" #version);
821bd63524SYonghong Song # define DEFAULT_VERSION(internal_name, api_name, version) \
831bd63524SYonghong Song 	asm(".symver " #internal_name "," #api_name "@@" #version);
841bd63524SYonghong Song #else
851bd63524SYonghong Song # define COMPAT_VERSION(internal_name, api_name, version)
861bd63524SYonghong Song # define DEFAULT_VERSION(internal_name, api_name, version) \
871bd63524SYonghong Song 	extern typeof(internal_name) api_name \
881bd63524SYonghong Song 	__attribute__((alias(#internal_name)));
891bd63524SYonghong Song #endif
901bd63524SYonghong Song 
91d72386feSAndrii Nakryiko extern void libbpf_print(enum libbpf_print_level level,
92d72386feSAndrii Nakryiko 			 const char *format, ...)
93d72386feSAndrii Nakryiko 	__attribute__((format(printf, 2, 3)));
94d72386feSAndrii Nakryiko 
95d72386feSAndrii Nakryiko #define __pr(level, fmt, ...)	\
96d72386feSAndrii Nakryiko do {				\
97d72386feSAndrii Nakryiko 	libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__);	\
98d72386feSAndrii Nakryiko } while (0)
99d72386feSAndrii Nakryiko 
100be18010eSKefeng Wang #define pr_warn(fmt, ...)	__pr(LIBBPF_WARN, fmt, ##__VA_ARGS__)
101d72386feSAndrii Nakryiko #define pr_info(fmt, ...)	__pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
102d72386feSAndrii Nakryiko #define pr_debug(fmt, ...)	__pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
103d72386feSAndrii Nakryiko 
104dda1ec9fSAndrii Nakryiko #ifndef __has_builtin
105dda1ec9fSAndrii Nakryiko #define __has_builtin(x) 0
106dda1ec9fSAndrii Nakryiko #endif
107029258d7SAndrii Nakryiko /*
108029258d7SAndrii Nakryiko  * Re-implement glibc's reallocarray() for libbpf internal-only use.
109029258d7SAndrii Nakryiko  * reallocarray(), unfortunately, is not available in all versions of glibc,
110029258d7SAndrii Nakryiko  * so requires extra feature detection and using reallocarray() stub from
111029258d7SAndrii Nakryiko  * <tools/libc_compat.h> and COMPAT_NEED_REALLOCARRAY. All this complicates
112029258d7SAndrii Nakryiko  * build of libbpf unnecessarily and is just a maintenance burden. Instead,
113029258d7SAndrii Nakryiko  * it's trivial to implement libbpf-specific internal version and use it
114029258d7SAndrii Nakryiko  * throughout libbpf.
115029258d7SAndrii Nakryiko  */
116029258d7SAndrii Nakryiko static inline void *libbpf_reallocarray(void *ptr, size_t nmemb, size_t size)
117029258d7SAndrii Nakryiko {
118029258d7SAndrii Nakryiko 	size_t total;
119029258d7SAndrii Nakryiko 
120dda1ec9fSAndrii Nakryiko #if __has_builtin(__builtin_mul_overflow)
121029258d7SAndrii Nakryiko 	if (unlikely(__builtin_mul_overflow(nmemb, size, &total)))
122029258d7SAndrii Nakryiko 		return NULL;
123dda1ec9fSAndrii Nakryiko #else
124dda1ec9fSAndrii Nakryiko 	if (size == 0 || nmemb > ULONG_MAX / size)
125dda1ec9fSAndrii Nakryiko 		return NULL;
126dda1ec9fSAndrii Nakryiko 	total = nmemb * size;
127dda1ec9fSAndrii Nakryiko #endif
128029258d7SAndrii Nakryiko 	return realloc(ptr, total);
129029258d7SAndrii Nakryiko }
130029258d7SAndrii Nakryiko 
131e14ef4bfSAndrii Nakryiko struct btf;
132e14ef4bfSAndrii Nakryiko struct btf_type;
133e14ef4bfSAndrii Nakryiko 
134e14ef4bfSAndrii Nakryiko struct btf_type *btf_type_by_id(struct btf *btf, __u32 type_id);
13542869d28SAndrii Nakryiko const char *btf_kind_str(const struct btf_type *t);
13642869d28SAndrii Nakryiko const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, __u32 id, __u32 *res_id);
13742869d28SAndrii Nakryiko 
13842869d28SAndrii Nakryiko static inline enum btf_func_linkage btf_func_linkage(const struct btf_type *t)
13942869d28SAndrii Nakryiko {
14042869d28SAndrii Nakryiko 	return (enum btf_func_linkage)(int)btf_vlen(t);
14142869d28SAndrii Nakryiko }
142e14ef4bfSAndrii Nakryiko 
143aea28a60SAndrii Nakryiko static inline __u32 btf_type_info(int kind, int vlen, int kflag)
144aea28a60SAndrii Nakryiko {
145aea28a60SAndrii Nakryiko 	return (kflag << 31) | (kind << 24) | vlen;
146aea28a60SAndrii Nakryiko }
147aea28a60SAndrii Nakryiko 
148c7ef5ec9SAndrii Nakryiko enum map_def_parts {
149c7ef5ec9SAndrii Nakryiko 	MAP_DEF_MAP_TYPE	= 0x001,
150c7ef5ec9SAndrii Nakryiko 	MAP_DEF_KEY_TYPE	= 0x002,
151c7ef5ec9SAndrii Nakryiko 	MAP_DEF_KEY_SIZE	= 0x004,
152c7ef5ec9SAndrii Nakryiko 	MAP_DEF_VALUE_TYPE	= 0x008,
153c7ef5ec9SAndrii Nakryiko 	MAP_DEF_VALUE_SIZE	= 0x010,
154c7ef5ec9SAndrii Nakryiko 	MAP_DEF_MAX_ENTRIES	= 0x020,
155c7ef5ec9SAndrii Nakryiko 	MAP_DEF_MAP_FLAGS	= 0x040,
156c7ef5ec9SAndrii Nakryiko 	MAP_DEF_NUMA_NODE	= 0x080,
157c7ef5ec9SAndrii Nakryiko 	MAP_DEF_PINNING		= 0x100,
158c7ef5ec9SAndrii Nakryiko 	MAP_DEF_INNER_MAP	= 0x200,
159c7ef5ec9SAndrii Nakryiko 
160c7ef5ec9SAndrii Nakryiko 	MAP_DEF_ALL		= 0x3ff, /* combination of all above */
161c7ef5ec9SAndrii Nakryiko };
162c7ef5ec9SAndrii Nakryiko 
163c7ef5ec9SAndrii Nakryiko struct btf_map_def {
164c7ef5ec9SAndrii Nakryiko 	enum map_def_parts parts;
165c7ef5ec9SAndrii Nakryiko 	__u32 map_type;
166c7ef5ec9SAndrii Nakryiko 	__u32 key_type_id;
167c7ef5ec9SAndrii Nakryiko 	__u32 key_size;
168c7ef5ec9SAndrii Nakryiko 	__u32 value_type_id;
169c7ef5ec9SAndrii Nakryiko 	__u32 value_size;
170c7ef5ec9SAndrii Nakryiko 	__u32 max_entries;
171c7ef5ec9SAndrii Nakryiko 	__u32 map_flags;
172c7ef5ec9SAndrii Nakryiko 	__u32 numa_node;
173c7ef5ec9SAndrii Nakryiko 	__u32 pinning;
174c7ef5ec9SAndrii Nakryiko };
175c7ef5ec9SAndrii Nakryiko 
176c7ef5ec9SAndrii Nakryiko int parse_btf_map_def(const char *map_name, struct btf *btf,
177c7ef5ec9SAndrii Nakryiko 		      const struct btf_type *def_t, bool strict,
178c7ef5ec9SAndrii Nakryiko 		      struct btf_map_def *map_def, struct btf_map_def *inner_def);
179c7ef5ec9SAndrii Nakryiko 
1803b029e06SAndrii Nakryiko void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz,
181192f5a1fSAndrii Nakryiko 		     size_t cur_cnt, size_t max_cnt, size_t add_cnt);
1823b029e06SAndrii Nakryiko int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt);
183192f5a1fSAndrii Nakryiko 
1842ce8450eSAndrii Nakryiko static inline bool libbpf_validate_opts(const char *opts,
1852ce8450eSAndrii Nakryiko 					size_t opts_sz, size_t user_sz,
1862ce8450eSAndrii Nakryiko 					const char *type_name)
1872ce8450eSAndrii Nakryiko {
1882ce8450eSAndrii Nakryiko 	if (user_sz < sizeof(size_t)) {
189be18010eSKefeng Wang 		pr_warn("%s size (%zu) is too small\n", type_name, user_sz);
1902ce8450eSAndrii Nakryiko 		return false;
1912ce8450eSAndrii Nakryiko 	}
1922ce8450eSAndrii Nakryiko 	if (user_sz > opts_sz) {
1932ce8450eSAndrii Nakryiko 		size_t i;
1942ce8450eSAndrii Nakryiko 
1952ce8450eSAndrii Nakryiko 		for (i = opts_sz; i < user_sz; i++) {
1962ce8450eSAndrii Nakryiko 			if (opts[i]) {
19712dd14b2SToke Høiland-Jørgensen 				pr_warn("%s has non-zero extra bytes\n",
1982ce8450eSAndrii Nakryiko 					type_name);
1992ce8450eSAndrii Nakryiko 				return false;
2002ce8450eSAndrii Nakryiko 			}
2012ce8450eSAndrii Nakryiko 		}
2022ce8450eSAndrii Nakryiko 	}
2032ce8450eSAndrii Nakryiko 	return true;
2042ce8450eSAndrii Nakryiko }
2052ce8450eSAndrii Nakryiko 
2062ce8450eSAndrii Nakryiko #define OPTS_VALID(opts, type)						      \
2072ce8450eSAndrii Nakryiko 	(!(opts) || libbpf_validate_opts((const char *)opts,		      \
2082ce8450eSAndrii Nakryiko 					 offsetofend(struct type,	      \
2092ce8450eSAndrii Nakryiko 						     type##__last_field),     \
2102ce8450eSAndrii Nakryiko 					 (opts)->sz, #type))
2112ce8450eSAndrii Nakryiko #define OPTS_HAS(opts, field) \
2122ce8450eSAndrii Nakryiko 	((opts) && opts->sz >= offsetofend(typeof(*(opts)), field))
2132ce8450eSAndrii Nakryiko #define OPTS_GET(opts, field, fallback_value) \
2142ce8450eSAndrii Nakryiko 	(OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
21588f7fe72SSong Liu #define OPTS_SET(opts, field, value)		\
21688f7fe72SSong Liu 	do {					\
21788f7fe72SSong Liu 		if (OPTS_HAS(opts, field))	\
21888f7fe72SSong Liu 			(opts)->field = value;	\
21988f7fe72SSong Liu 	} while (0)
2202ce8450eSAndrii Nakryiko 
2216803ee25SAndrii Nakryiko int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);
2226803ee25SAndrii Nakryiko int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);
223cfd49210SMichal Rostecki int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
224d7c4b398SAndrii Nakryiko 			 const char *str_sec, size_t str_len);
225d7c4b398SAndrii Nakryiko 
2266aef10a4SAndrii Nakryiko struct bpf_prog_load_params {
2276aef10a4SAndrii Nakryiko 	enum bpf_prog_type prog_type;
2286aef10a4SAndrii Nakryiko 	enum bpf_attach_type expected_attach_type;
2296aef10a4SAndrii Nakryiko 	const char *name;
2306aef10a4SAndrii Nakryiko 	const struct bpf_insn *insns;
2316aef10a4SAndrii Nakryiko 	size_t insn_cnt;
2326aef10a4SAndrii Nakryiko 	const char *license;
2336aef10a4SAndrii Nakryiko 	__u32 kern_version;
2346aef10a4SAndrii Nakryiko 	__u32 attach_prog_fd;
23591abb4a6SAndrii Nakryiko 	__u32 attach_btf_obj_fd;
2366aef10a4SAndrii Nakryiko 	__u32 attach_btf_id;
2376aef10a4SAndrii Nakryiko 	__u32 prog_ifindex;
2386aef10a4SAndrii Nakryiko 	__u32 prog_btf_fd;
2396aef10a4SAndrii Nakryiko 	__u32 prog_flags;
2406aef10a4SAndrii Nakryiko 
2416aef10a4SAndrii Nakryiko 	__u32 func_info_rec_size;
2426aef10a4SAndrii Nakryiko 	const void *func_info;
2436aef10a4SAndrii Nakryiko 	__u32 func_info_cnt;
2446aef10a4SAndrii Nakryiko 
2456aef10a4SAndrii Nakryiko 	__u32 line_info_rec_size;
2466aef10a4SAndrii Nakryiko 	const void *line_info;
2476aef10a4SAndrii Nakryiko 	__u32 line_info_cnt;
2486aef10a4SAndrii Nakryiko 
2496aef10a4SAndrii Nakryiko 	__u32 log_level;
2506aef10a4SAndrii Nakryiko 	char *log_buf;
2516aef10a4SAndrii Nakryiko 	size_t log_buf_sz;
2526aef10a4SAndrii Nakryiko };
2536aef10a4SAndrii Nakryiko 
2546aef10a4SAndrii Nakryiko int libbpf__bpf_prog_load(const struct bpf_prog_load_params *load_attr);
2556aef10a4SAndrii Nakryiko 
256612d05beSAndrii Nakryiko int bpf_object__section_size(const struct bpf_object *obj, const char *name,
257612d05beSAndrii Nakryiko 			     __u32 *size);
258612d05beSAndrii Nakryiko int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
259612d05beSAndrii Nakryiko 				__u32 *off);
260a19f93cfSAndrii Nakryiko struct btf *btf_get_from_fd(int btf_fd, struct btf *base_btf);
261*67234743SAlexei Starovoitov void btf_get_kernel_prefix_kind(enum bpf_attach_type attach_type,
262*67234743SAlexei Starovoitov 				const char **prefix, int *kind);
263612d05beSAndrii Nakryiko 
2644cedc0daSAndrii Nakryiko struct btf_ext_info {
2654cedc0daSAndrii Nakryiko 	/*
2664cedc0daSAndrii Nakryiko 	 * info points to the individual info section (e.g. func_info and
2674cedc0daSAndrii Nakryiko 	 * line_info) from the .BTF.ext. It does not include the __u32 rec_size.
2684cedc0daSAndrii Nakryiko 	 */
2694cedc0daSAndrii Nakryiko 	void *info;
2704cedc0daSAndrii Nakryiko 	__u32 rec_size;
2714cedc0daSAndrii Nakryiko 	__u32 len;
2724cedc0daSAndrii Nakryiko };
2734cedc0daSAndrii Nakryiko 
2744cedc0daSAndrii Nakryiko #define for_each_btf_ext_sec(seg, sec)					\
2754cedc0daSAndrii Nakryiko 	for (sec = (seg)->info;						\
2764cedc0daSAndrii Nakryiko 	     (void *)sec < (seg)->info + (seg)->len;			\
2774cedc0daSAndrii Nakryiko 	     sec = (void *)sec + sizeof(struct btf_ext_info_sec) +	\
2784cedc0daSAndrii Nakryiko 		   (seg)->rec_size * sec->num_info)
2794cedc0daSAndrii Nakryiko 
2804cedc0daSAndrii Nakryiko #define for_each_btf_ext_rec(seg, sec, i, rec)				\
2814cedc0daSAndrii Nakryiko 	for (i = 0, rec = (void *)&(sec)->data;				\
2824cedc0daSAndrii Nakryiko 	     i < (sec)->num_info;					\
2834cedc0daSAndrii Nakryiko 	     i++, rec = (void *)rec + (seg)->rec_size)
2844cedc0daSAndrii Nakryiko 
28528b93c64SAndrii Nakryiko /*
28628b93c64SAndrii Nakryiko  * The .BTF.ext ELF section layout defined as
28728b93c64SAndrii Nakryiko  *   struct btf_ext_header
28828b93c64SAndrii Nakryiko  *   func_info subsection
28928b93c64SAndrii Nakryiko  *
29028b93c64SAndrii Nakryiko  * The func_info subsection layout:
29128b93c64SAndrii Nakryiko  *   record size for struct bpf_func_info in the func_info subsection
29228b93c64SAndrii Nakryiko  *   struct btf_sec_func_info for section #1
29328b93c64SAndrii Nakryiko  *   a list of bpf_func_info records for section #1
29428b93c64SAndrii Nakryiko  *     where struct bpf_func_info mimics one in include/uapi/linux/bpf.h
29528b93c64SAndrii Nakryiko  *     but may not be identical
29628b93c64SAndrii Nakryiko  *   struct btf_sec_func_info for section #2
29728b93c64SAndrii Nakryiko  *   a list of bpf_func_info records for section #2
29828b93c64SAndrii Nakryiko  *   ......
29928b93c64SAndrii Nakryiko  *
30028b93c64SAndrii Nakryiko  * Note that the bpf_func_info record size in .BTF.ext may not
30128b93c64SAndrii Nakryiko  * be the same as the one defined in include/uapi/linux/bpf.h.
30228b93c64SAndrii Nakryiko  * The loader should ensure that record_size meets minimum
30328b93c64SAndrii Nakryiko  * requirement and pass the record as is to the kernel. The
30428b93c64SAndrii Nakryiko  * kernel will handle the func_info properly based on its contents.
30528b93c64SAndrii Nakryiko  */
30628b93c64SAndrii Nakryiko struct btf_ext_header {
30728b93c64SAndrii Nakryiko 	__u16	magic;
30828b93c64SAndrii Nakryiko 	__u8	version;
30928b93c64SAndrii Nakryiko 	__u8	flags;
31028b93c64SAndrii Nakryiko 	__u32	hdr_len;
31128b93c64SAndrii Nakryiko 
31228b93c64SAndrii Nakryiko 	/* All offsets are in bytes relative to the end of this header */
31328b93c64SAndrii Nakryiko 	__u32	func_info_off;
31428b93c64SAndrii Nakryiko 	__u32	func_info_len;
31528b93c64SAndrii Nakryiko 	__u32	line_info_off;
31628b93c64SAndrii Nakryiko 	__u32	line_info_len;
31728b93c64SAndrii Nakryiko 
31828b93c64SAndrii Nakryiko 	/* optional part of .BTF.ext header */
31928b93c64SAndrii Nakryiko 	__u32	core_relo_off;
32028b93c64SAndrii Nakryiko 	__u32	core_relo_len;
32128b93c64SAndrii Nakryiko };
32228b93c64SAndrii Nakryiko 
3234cedc0daSAndrii Nakryiko struct btf_ext {
3244cedc0daSAndrii Nakryiko 	union {
3254cedc0daSAndrii Nakryiko 		struct btf_ext_header *hdr;
3264cedc0daSAndrii Nakryiko 		void *data;
3274cedc0daSAndrii Nakryiko 	};
3284cedc0daSAndrii Nakryiko 	struct btf_ext_info func_info;
3294cedc0daSAndrii Nakryiko 	struct btf_ext_info line_info;
33028b93c64SAndrii Nakryiko 	struct btf_ext_info core_relo_info;
3314cedc0daSAndrii Nakryiko 	__u32 data_size;
3324cedc0daSAndrii Nakryiko };
3334cedc0daSAndrii Nakryiko 
3344cedc0daSAndrii Nakryiko struct btf_ext_info_sec {
3354cedc0daSAndrii Nakryiko 	__u32	sec_name_off;
3364cedc0daSAndrii Nakryiko 	__u32	num_info;
3374cedc0daSAndrii Nakryiko 	/* Followed by num_info * record_size number of bytes */
338385bbf7bSGustavo A. R. Silva 	__u8	data[];
3394cedc0daSAndrii Nakryiko };
3404cedc0daSAndrii Nakryiko 
3414cedc0daSAndrii Nakryiko /* The minimum bpf_func_info checked by the loader */
3424cedc0daSAndrii Nakryiko struct bpf_func_info_min {
3434cedc0daSAndrii Nakryiko 	__u32   insn_off;
3444cedc0daSAndrii Nakryiko 	__u32   type_id;
3454cedc0daSAndrii Nakryiko };
3464cedc0daSAndrii Nakryiko 
3474cedc0daSAndrii Nakryiko /* The minimum bpf_line_info checked by the loader */
3484cedc0daSAndrii Nakryiko struct bpf_line_info_min {
3494cedc0daSAndrii Nakryiko 	__u32	insn_off;
3504cedc0daSAndrii Nakryiko 	__u32	file_name_off;
3514cedc0daSAndrii Nakryiko 	__u32	line_off;
3524cedc0daSAndrii Nakryiko 	__u32	line_col;
3534cedc0daSAndrii Nakryiko };
3544cedc0daSAndrii Nakryiko 
35528b93c64SAndrii Nakryiko /* bpf_core_relo_kind encodes which aspect of captured field/type/enum value
35628b93c64SAndrii Nakryiko  * has to be adjusted by relocations.
357511bb008SAndrii Nakryiko  */
35828b93c64SAndrii Nakryiko enum bpf_core_relo_kind {
359511bb008SAndrii Nakryiko 	BPF_FIELD_BYTE_OFFSET = 0,	/* field byte offset */
36028b93c64SAndrii Nakryiko 	BPF_FIELD_BYTE_SIZE = 1,	/* field size in bytes */
361511bb008SAndrii Nakryiko 	BPF_FIELD_EXISTS = 2,		/* field existence in target kernel */
36228b93c64SAndrii Nakryiko 	BPF_FIELD_SIGNED = 3,		/* field signedness (0 - unsigned, 1 - signed) */
36328b93c64SAndrii Nakryiko 	BPF_FIELD_LSHIFT_U64 = 4,	/* bitfield-specific left bitshift */
36428b93c64SAndrii Nakryiko 	BPF_FIELD_RSHIFT_U64 = 5,	/* bitfield-specific right bitshift */
3653fc32f40SAndrii Nakryiko 	BPF_TYPE_ID_LOCAL = 6,		/* type ID in local BPF object */
3663fc32f40SAndrii Nakryiko 	BPF_TYPE_ID_TARGET = 7,		/* type ID in target kernel */
3673fc32f40SAndrii Nakryiko 	BPF_TYPE_EXISTS = 8,		/* type existence in target kernel */
3683fc32f40SAndrii Nakryiko 	BPF_TYPE_SIZE = 9,		/* type size in bytes */
369eacaaed7SAndrii Nakryiko 	BPF_ENUMVAL_EXISTS = 10,	/* enum value existence in target kernel */
370eacaaed7SAndrii Nakryiko 	BPF_ENUMVAL_VALUE = 11,		/* enum value integer value */
371511bb008SAndrii Nakryiko };
372511bb008SAndrii Nakryiko 
37328b93c64SAndrii Nakryiko /* The minimum bpf_core_relo checked by the loader
3744cedc0daSAndrii Nakryiko  *
37528b93c64SAndrii Nakryiko  * CO-RE relocation captures the following data:
3764cedc0daSAndrii Nakryiko  * - insn_off - instruction offset (in bytes) within a BPF program that needs
377511bb008SAndrii Nakryiko  *   its insn->imm field to be relocated with actual field info;
3784cedc0daSAndrii Nakryiko  * - type_id - BTF type ID of the "root" (containing) entity of a relocatable
37928b93c64SAndrii Nakryiko  *   type or field;
3804cedc0daSAndrii Nakryiko  * - access_str_off - offset into corresponding .BTF string section. String
38128b93c64SAndrii Nakryiko  *   interpretation depends on specific relocation kind:
38228b93c64SAndrii Nakryiko  *     - for field-based relocations, string encodes an accessed field using
38328b93c64SAndrii Nakryiko  *     a sequence of field and array indices, separated by colon (:). It's
38428b93c64SAndrii Nakryiko  *     conceptually very close to LLVM's getelementptr ([0]) instruction's
38528b93c64SAndrii Nakryiko  *     arguments for identifying offset to a field.
38628b93c64SAndrii Nakryiko  *     - for type-based relocations, strings is expected to be just "0";
38728b93c64SAndrii Nakryiko  *     - for enum value-based relocations, string contains an index of enum
38828b93c64SAndrii Nakryiko  *     value within its enum type;
3894cedc0daSAndrii Nakryiko  *
3904cedc0daSAndrii Nakryiko  * Example to provide a better feel.
3914cedc0daSAndrii Nakryiko  *
3924cedc0daSAndrii Nakryiko  *   struct sample {
3934cedc0daSAndrii Nakryiko  *       int a;
3944cedc0daSAndrii Nakryiko  *       struct {
3954cedc0daSAndrii Nakryiko  *           int b[10];
3964cedc0daSAndrii Nakryiko  *       };
3974cedc0daSAndrii Nakryiko  *   };
3984cedc0daSAndrii Nakryiko  *
3994cedc0daSAndrii Nakryiko  *   struct sample *s = ...;
4004cedc0daSAndrii Nakryiko  *   int x = &s->a;     // encoded as "0:0" (a is field #0)
4014cedc0daSAndrii Nakryiko  *   int y = &s->b[5];  // encoded as "0:1:0:5" (anon struct is field #1,
4024cedc0daSAndrii Nakryiko  *                      // b is field #0 inside anon struct, accessing elem #5)
4034cedc0daSAndrii Nakryiko  *   int z = &s[10]->b; // encoded as "10:1" (ptr is used as an array)
4044cedc0daSAndrii Nakryiko  *
4054cedc0daSAndrii Nakryiko  * type_id for all relocs in this example  will capture BTF type id of
4064cedc0daSAndrii Nakryiko  * `struct sample`.
4074cedc0daSAndrii Nakryiko  *
4084cedc0daSAndrii Nakryiko  * Such relocation is emitted when using __builtin_preserve_access_index()
4094cedc0daSAndrii Nakryiko  * Clang built-in, passing expression that captures field address, e.g.:
4104cedc0daSAndrii Nakryiko  *
4114cedc0daSAndrii Nakryiko  * bpf_probe_read(&dst, sizeof(dst),
4124cedc0daSAndrii Nakryiko  *		  __builtin_preserve_access_index(&src->a.b.c));
4134cedc0daSAndrii Nakryiko  *
414511bb008SAndrii Nakryiko  * In this case Clang will emit field relocation recording necessary data to
4154cedc0daSAndrii Nakryiko  * be able to find offset of embedded `a.b.c` field within `src` struct.
4164cedc0daSAndrii Nakryiko  *
4174cedc0daSAndrii Nakryiko  *   [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction
4184cedc0daSAndrii Nakryiko  */
41928b93c64SAndrii Nakryiko struct bpf_core_relo {
4204cedc0daSAndrii Nakryiko 	__u32   insn_off;
4214cedc0daSAndrii Nakryiko 	__u32   type_id;
4224cedc0daSAndrii Nakryiko 	__u32   access_str_off;
42328b93c64SAndrii Nakryiko 	enum bpf_core_relo_kind kind;
4244cedc0daSAndrii Nakryiko };
4254cedc0daSAndrii Nakryiko 
426f36e99a4SAndrii Nakryiko typedef int (*type_id_visit_fn)(__u32 *type_id, void *ctx);
427f36e99a4SAndrii Nakryiko typedef int (*str_off_visit_fn)(__u32 *str_off, void *ctx);
428f36e99a4SAndrii Nakryiko int btf_type_visit_type_ids(struct btf_type *t, type_id_visit_fn visit, void *ctx);
429f36e99a4SAndrii Nakryiko int btf_type_visit_str_offs(struct btf_type *t, str_off_visit_fn visit, void *ctx);
430f36e99a4SAndrii Nakryiko int btf_ext_visit_type_ids(struct btf_ext *btf_ext, type_id_visit_fn visit, void *ctx);
431f36e99a4SAndrii Nakryiko int btf_ext_visit_str_offs(struct btf_ext *btf_ext, str_off_visit_fn visit, void *ctx);
432f36e99a4SAndrii Nakryiko 
433d7c4b398SAndrii Nakryiko #endif /* __LIBBPF_LIBBPF_INTERNAL_H */
434