xref: /openbmc/linux/tools/lib/bpf/libbpf_internal.h (revision 12dd14b2)
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 
121d7a08b3SAndrii Nakryiko #include "libbpf.h"
131d7a08b3SAndrii Nakryiko 
14d7c4b398SAndrii Nakryiko #define BTF_INFO_ENC(kind, kind_flag, vlen) \
15d7c4b398SAndrii Nakryiko 	((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
16d7c4b398SAndrii Nakryiko #define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
17d7c4b398SAndrii Nakryiko #define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
18d7c4b398SAndrii Nakryiko 	((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
19d7c4b398SAndrii Nakryiko #define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
20d7c4b398SAndrii Nakryiko 	BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
21d7c4b398SAndrii Nakryiko 	BTF_INT_ENC(encoding, bits_offset, bits)
22d7c4b398SAndrii Nakryiko #define BTF_MEMBER_ENC(name, type, bits_offset) (name), (type), (bits_offset)
23d7c4b398SAndrii Nakryiko #define BTF_PARAM_ENC(name, type) (name), (type)
24d7c4b398SAndrii Nakryiko #define BTF_VAR_SECINFO_ENC(type, offset, size) (type), (offset), (size)
25d7c4b398SAndrii Nakryiko 
26d7fe74f9SAndrii Nakryiko #ifndef min
27d7fe74f9SAndrii Nakryiko # define min(x, y) ((x) < (y) ? (x) : (y))
28d7fe74f9SAndrii Nakryiko #endif
29d7fe74f9SAndrii Nakryiko #ifndef max
30d7fe74f9SAndrii Nakryiko # define max(x, y) ((x) < (y) ? (y) : (x))
31d7fe74f9SAndrii Nakryiko #endif
324cedc0daSAndrii Nakryiko #ifndef offsetofend
334cedc0daSAndrii Nakryiko # define offsetofend(TYPE, FIELD) \
344cedc0daSAndrii Nakryiko 	(offsetof(TYPE, FIELD) + sizeof(((TYPE *)0)->FIELD))
354cedc0daSAndrii Nakryiko #endif
36d7fe74f9SAndrii Nakryiko 
371bd63524SYonghong Song /* Symbol versioning is different between static and shared library.
381bd63524SYonghong Song  * Properly versioned symbols are needed for shared library, but
391bd63524SYonghong Song  * only the symbol of the new version is needed for static library.
401bd63524SYonghong Song  */
411bd63524SYonghong Song #ifdef SHARED
421bd63524SYonghong Song # define COMPAT_VERSION(internal_name, api_name, version) \
431bd63524SYonghong Song 	asm(".symver " #internal_name "," #api_name "@" #version);
441bd63524SYonghong Song # define DEFAULT_VERSION(internal_name, api_name, version) \
451bd63524SYonghong Song 	asm(".symver " #internal_name "," #api_name "@@" #version);
461bd63524SYonghong Song #else
471bd63524SYonghong Song # define COMPAT_VERSION(internal_name, api_name, version)
481bd63524SYonghong Song # define DEFAULT_VERSION(internal_name, api_name, version) \
491bd63524SYonghong Song 	extern typeof(internal_name) api_name \
501bd63524SYonghong Song 	__attribute__((alias(#internal_name)));
511bd63524SYonghong Song #endif
521bd63524SYonghong Song 
53d72386feSAndrii Nakryiko extern void libbpf_print(enum libbpf_print_level level,
54d72386feSAndrii Nakryiko 			 const char *format, ...)
55d72386feSAndrii Nakryiko 	__attribute__((format(printf, 2, 3)));
56d72386feSAndrii Nakryiko 
57d72386feSAndrii Nakryiko #define __pr(level, fmt, ...)	\
58d72386feSAndrii Nakryiko do {				\
59d72386feSAndrii Nakryiko 	libbpf_print(level, "libbpf: " fmt, ##__VA_ARGS__);	\
60d72386feSAndrii Nakryiko } while (0)
61d72386feSAndrii Nakryiko 
62be18010eSKefeng Wang #define pr_warn(fmt, ...)	__pr(LIBBPF_WARN, fmt, ##__VA_ARGS__)
63d72386feSAndrii Nakryiko #define pr_info(fmt, ...)	__pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
64d72386feSAndrii Nakryiko #define pr_debug(fmt, ...)	__pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
65d72386feSAndrii Nakryiko 
662ce8450eSAndrii Nakryiko static inline bool libbpf_validate_opts(const char *opts,
672ce8450eSAndrii Nakryiko 					size_t opts_sz, size_t user_sz,
682ce8450eSAndrii Nakryiko 					const char *type_name)
692ce8450eSAndrii Nakryiko {
702ce8450eSAndrii Nakryiko 	if (user_sz < sizeof(size_t)) {
71be18010eSKefeng Wang 		pr_warn("%s size (%zu) is too small\n", type_name, user_sz);
722ce8450eSAndrii Nakryiko 		return false;
732ce8450eSAndrii Nakryiko 	}
742ce8450eSAndrii Nakryiko 	if (user_sz > opts_sz) {
752ce8450eSAndrii Nakryiko 		size_t i;
762ce8450eSAndrii Nakryiko 
772ce8450eSAndrii Nakryiko 		for (i = opts_sz; i < user_sz; i++) {
782ce8450eSAndrii Nakryiko 			if (opts[i]) {
7912dd14b2SToke Høiland-Jørgensen 				pr_warn("%s has non-zero extra bytes\n",
802ce8450eSAndrii Nakryiko 					type_name);
812ce8450eSAndrii Nakryiko 				return false;
822ce8450eSAndrii Nakryiko 			}
832ce8450eSAndrii Nakryiko 		}
842ce8450eSAndrii Nakryiko 	}
852ce8450eSAndrii Nakryiko 	return true;
862ce8450eSAndrii Nakryiko }
872ce8450eSAndrii Nakryiko 
882ce8450eSAndrii Nakryiko #define OPTS_VALID(opts, type)						      \
892ce8450eSAndrii Nakryiko 	(!(opts) || libbpf_validate_opts((const char *)opts,		      \
902ce8450eSAndrii Nakryiko 					 offsetofend(struct type,	      \
912ce8450eSAndrii Nakryiko 						     type##__last_field),     \
922ce8450eSAndrii Nakryiko 					 (opts)->sz, #type))
932ce8450eSAndrii Nakryiko #define OPTS_HAS(opts, field) \
942ce8450eSAndrii Nakryiko 	((opts) && opts->sz >= offsetofend(typeof(*(opts)), field))
952ce8450eSAndrii Nakryiko #define OPTS_GET(opts, field, fallback_value) \
962ce8450eSAndrii Nakryiko 	(OPTS_HAS(opts, field) ? (opts)->field : fallback_value)
972ce8450eSAndrii Nakryiko 
986803ee25SAndrii Nakryiko int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);
996803ee25SAndrii Nakryiko int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);
100cfd49210SMichal Rostecki int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
101d7c4b398SAndrii Nakryiko 			 const char *str_sec, size_t str_len);
102d7c4b398SAndrii Nakryiko 
103612d05beSAndrii Nakryiko int bpf_object__section_size(const struct bpf_object *obj, const char *name,
104612d05beSAndrii Nakryiko 			     __u32 *size);
105612d05beSAndrii Nakryiko int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
106612d05beSAndrii Nakryiko 				__u32 *off);
107612d05beSAndrii Nakryiko 
108612d05beSAndrii Nakryiko struct nlattr;
109612d05beSAndrii Nakryiko typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
110612d05beSAndrii Nakryiko int libbpf_netlink_open(unsigned int *nl_pid);
111612d05beSAndrii Nakryiko int libbpf_nl_get_link(int sock, unsigned int nl_pid,
112612d05beSAndrii Nakryiko 		       libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie);
113612d05beSAndrii Nakryiko int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex,
114612d05beSAndrii Nakryiko 			libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie);
115612d05beSAndrii Nakryiko int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
116612d05beSAndrii Nakryiko 			libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie);
117612d05beSAndrii Nakryiko int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
118612d05beSAndrii Nakryiko 			 libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie);
119612d05beSAndrii Nakryiko 
1204cedc0daSAndrii Nakryiko struct btf_ext_info {
1214cedc0daSAndrii Nakryiko 	/*
1224cedc0daSAndrii Nakryiko 	 * info points to the individual info section (e.g. func_info and
1234cedc0daSAndrii Nakryiko 	 * line_info) from the .BTF.ext. It does not include the __u32 rec_size.
1244cedc0daSAndrii Nakryiko 	 */
1254cedc0daSAndrii Nakryiko 	void *info;
1264cedc0daSAndrii Nakryiko 	__u32 rec_size;
1274cedc0daSAndrii Nakryiko 	__u32 len;
1284cedc0daSAndrii Nakryiko };
1294cedc0daSAndrii Nakryiko 
1304cedc0daSAndrii Nakryiko #define for_each_btf_ext_sec(seg, sec)					\
1314cedc0daSAndrii Nakryiko 	for (sec = (seg)->info;						\
1324cedc0daSAndrii Nakryiko 	     (void *)sec < (seg)->info + (seg)->len;			\
1334cedc0daSAndrii Nakryiko 	     sec = (void *)sec + sizeof(struct btf_ext_info_sec) +	\
1344cedc0daSAndrii Nakryiko 		   (seg)->rec_size * sec->num_info)
1354cedc0daSAndrii Nakryiko 
1364cedc0daSAndrii Nakryiko #define for_each_btf_ext_rec(seg, sec, i, rec)				\
1374cedc0daSAndrii Nakryiko 	for (i = 0, rec = (void *)&(sec)->data;				\
1384cedc0daSAndrii Nakryiko 	     i < (sec)->num_info;					\
1394cedc0daSAndrii Nakryiko 	     i++, rec = (void *)rec + (seg)->rec_size)
1404cedc0daSAndrii Nakryiko 
1414cedc0daSAndrii Nakryiko struct btf_ext {
1424cedc0daSAndrii Nakryiko 	union {
1434cedc0daSAndrii Nakryiko 		struct btf_ext_header *hdr;
1444cedc0daSAndrii Nakryiko 		void *data;
1454cedc0daSAndrii Nakryiko 	};
1464cedc0daSAndrii Nakryiko 	struct btf_ext_info func_info;
1474cedc0daSAndrii Nakryiko 	struct btf_ext_info line_info;
148511bb008SAndrii Nakryiko 	struct btf_ext_info field_reloc_info;
1494cedc0daSAndrii Nakryiko 	__u32 data_size;
1504cedc0daSAndrii Nakryiko };
1514cedc0daSAndrii Nakryiko 
1524cedc0daSAndrii Nakryiko struct btf_ext_info_sec {
1534cedc0daSAndrii Nakryiko 	__u32	sec_name_off;
1544cedc0daSAndrii Nakryiko 	__u32	num_info;
1554cedc0daSAndrii Nakryiko 	/* Followed by num_info * record_size number of bytes */
1564cedc0daSAndrii Nakryiko 	__u8	data[0];
1574cedc0daSAndrii Nakryiko };
1584cedc0daSAndrii Nakryiko 
1594cedc0daSAndrii Nakryiko /* The minimum bpf_func_info checked by the loader */
1604cedc0daSAndrii Nakryiko struct bpf_func_info_min {
1614cedc0daSAndrii Nakryiko 	__u32   insn_off;
1624cedc0daSAndrii Nakryiko 	__u32   type_id;
1634cedc0daSAndrii Nakryiko };
1644cedc0daSAndrii Nakryiko 
1654cedc0daSAndrii Nakryiko /* The minimum bpf_line_info checked by the loader */
1664cedc0daSAndrii Nakryiko struct bpf_line_info_min {
1674cedc0daSAndrii Nakryiko 	__u32	insn_off;
1684cedc0daSAndrii Nakryiko 	__u32	file_name_off;
1694cedc0daSAndrii Nakryiko 	__u32	line_off;
1704cedc0daSAndrii Nakryiko 	__u32	line_col;
1714cedc0daSAndrii Nakryiko };
1724cedc0daSAndrii Nakryiko 
173511bb008SAndrii Nakryiko /* bpf_field_info_kind encodes which aspect of captured field has to be
174511bb008SAndrii Nakryiko  * adjusted by relocations. Currently supported values are:
175511bb008SAndrii Nakryiko  *   - BPF_FIELD_BYTE_OFFSET: field offset (in bytes);
176511bb008SAndrii Nakryiko  *   - BPF_FIELD_EXISTS: field existence (1, if field exists; 0, otherwise);
177511bb008SAndrii Nakryiko  */
178511bb008SAndrii Nakryiko enum bpf_field_info_kind {
179511bb008SAndrii Nakryiko 	BPF_FIELD_BYTE_OFFSET = 0,	/* field byte offset */
180ee26dadeSAndrii Nakryiko 	BPF_FIELD_BYTE_SIZE = 1,
181511bb008SAndrii Nakryiko 	BPF_FIELD_EXISTS = 2,		/* field existence in target kernel */
182ee26dadeSAndrii Nakryiko 	BPF_FIELD_SIGNED = 3,
183ee26dadeSAndrii Nakryiko 	BPF_FIELD_LSHIFT_U64 = 4,
184ee26dadeSAndrii Nakryiko 	BPF_FIELD_RSHIFT_U64 = 5,
185511bb008SAndrii Nakryiko };
186511bb008SAndrii Nakryiko 
187511bb008SAndrii Nakryiko /* The minimum bpf_field_reloc checked by the loader
1884cedc0daSAndrii Nakryiko  *
189511bb008SAndrii Nakryiko  * Field relocation captures the following data:
1904cedc0daSAndrii Nakryiko  * - insn_off - instruction offset (in bytes) within a BPF program that needs
191511bb008SAndrii Nakryiko  *   its insn->imm field to be relocated with actual field info;
1924cedc0daSAndrii Nakryiko  * - type_id - BTF type ID of the "root" (containing) entity of a relocatable
193511bb008SAndrii Nakryiko  *   field;
1944cedc0daSAndrii Nakryiko  * - access_str_off - offset into corresponding .BTF string section. String
1954cedc0daSAndrii Nakryiko  *   itself encodes an accessed field using a sequence of field and array
1964cedc0daSAndrii Nakryiko  *   indicies, separated by colon (:). It's conceptually very close to LLVM's
1974cedc0daSAndrii Nakryiko  *   getelementptr ([0]) instruction's arguments for identifying offset to
1984cedc0daSAndrii Nakryiko  *   a field.
1994cedc0daSAndrii Nakryiko  *
2004cedc0daSAndrii Nakryiko  * Example to provide a better feel.
2014cedc0daSAndrii Nakryiko  *
2024cedc0daSAndrii Nakryiko  *   struct sample {
2034cedc0daSAndrii Nakryiko  *       int a;
2044cedc0daSAndrii Nakryiko  *       struct {
2054cedc0daSAndrii Nakryiko  *           int b[10];
2064cedc0daSAndrii Nakryiko  *       };
2074cedc0daSAndrii Nakryiko  *   };
2084cedc0daSAndrii Nakryiko  *
2094cedc0daSAndrii Nakryiko  *   struct sample *s = ...;
2104cedc0daSAndrii Nakryiko  *   int x = &s->a;     // encoded as "0:0" (a is field #0)
2114cedc0daSAndrii Nakryiko  *   int y = &s->b[5];  // encoded as "0:1:0:5" (anon struct is field #1,
2124cedc0daSAndrii Nakryiko  *                      // b is field #0 inside anon struct, accessing elem #5)
2134cedc0daSAndrii Nakryiko  *   int z = &s[10]->b; // encoded as "10:1" (ptr is used as an array)
2144cedc0daSAndrii Nakryiko  *
2154cedc0daSAndrii Nakryiko  * type_id for all relocs in this example  will capture BTF type id of
2164cedc0daSAndrii Nakryiko  * `struct sample`.
2174cedc0daSAndrii Nakryiko  *
2184cedc0daSAndrii Nakryiko  * Such relocation is emitted when using __builtin_preserve_access_index()
2194cedc0daSAndrii Nakryiko  * Clang built-in, passing expression that captures field address, e.g.:
2204cedc0daSAndrii Nakryiko  *
2214cedc0daSAndrii Nakryiko  * bpf_probe_read(&dst, sizeof(dst),
2224cedc0daSAndrii Nakryiko  *		  __builtin_preserve_access_index(&src->a.b.c));
2234cedc0daSAndrii Nakryiko  *
224511bb008SAndrii Nakryiko  * In this case Clang will emit field relocation recording necessary data to
2254cedc0daSAndrii Nakryiko  * be able to find offset of embedded `a.b.c` field within `src` struct.
2264cedc0daSAndrii Nakryiko  *
2274cedc0daSAndrii Nakryiko  *   [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction
2284cedc0daSAndrii Nakryiko  */
229511bb008SAndrii Nakryiko struct bpf_field_reloc {
2304cedc0daSAndrii Nakryiko 	__u32   insn_off;
2314cedc0daSAndrii Nakryiko 	__u32   type_id;
2324cedc0daSAndrii Nakryiko 	__u32   access_str_off;
233511bb008SAndrii Nakryiko 	enum bpf_field_info_kind kind;
2344cedc0daSAndrii Nakryiko };
2354cedc0daSAndrii Nakryiko 
236d7c4b398SAndrii Nakryiko #endif /* __LIBBPF_LIBBPF_INTERNAL_H */
237