diff options
Diffstat (limited to 'tools/lib/bpf/libbpf_internal.h')
| -rw-r--r-- | tools/lib/bpf/libbpf_internal.h | 113 | 
1 files changed, 33 insertions, 80 deletions
| diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h index 016ca7cb4f8a..533b0211f40a 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -14,6 +14,7 @@  #include <errno.h>  #include <linux/err.h>  #include "libbpf_legacy.h" +#include "relo_core.h"  /* make sure libbpf doesn't use kernel-only integer typedefs */  #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 @@ -195,6 +196,17 @@ void *libbpf_add_mem(void **data, size_t *cap_cnt, size_t elem_sz,  		     size_t cur_cnt, size_t max_cnt, size_t add_cnt);  int libbpf_ensure_mem(void **data, size_t *cap_cnt, size_t elem_sz, size_t need_cnt); +static inline bool libbpf_is_mem_zeroed(const char *p, ssize_t len) +{ +	while (len > 0) { +		if (*p) +			return false; +		p++; +		len--; +	} +	return true; +} +  static inline bool libbpf_validate_opts(const char *opts,  					size_t opts_sz, size_t user_sz,  					const char *type_name) @@ -203,16 +215,9 @@ static inline bool libbpf_validate_opts(const char *opts,  		pr_warn("%s size (%zu) is too small\n", type_name, user_sz);  		return false;  	} -	if (user_sz > opts_sz) { -		size_t i; - -		for (i = opts_sz; i < user_sz; i++) { -			if (opts[i]) { -				pr_warn("%s has non-zero extra bytes\n", -					type_name); -				return false; -			} -		} +	if (!libbpf_is_mem_zeroed(opts + opts_sz, (ssize_t)user_sz - opts_sz)) { +		pr_warn("%s has non-zero extra bytes\n", type_name); +		return false;  	}  	return true;  } @@ -232,6 +237,14 @@ static inline bool libbpf_validate_opts(const char *opts,  			(opts)->field = value;	\  	} while (0) +#define OPTS_ZEROED(opts, last_nonzero_field)				      \ +({									      \ +	ssize_t __off = offsetofend(typeof(*(opts)), last_nonzero_field);     \ +	!(opts) || libbpf_is_mem_zeroed((const void *)opts + __off,	      \ +					(opts)->sz - __off);		      \ +}) + +  int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);  int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);  int libbpf__load_raw_btf(const char *raw_types, size_t types_len, @@ -366,76 +379,6 @@ struct bpf_line_info_min {  	__u32	line_col;  }; -/* bpf_core_relo_kind encodes which aspect of captured field/type/enum value - * has to be adjusted by relocations. - */ -enum bpf_core_relo_kind { -	BPF_FIELD_BYTE_OFFSET = 0,	/* field byte offset */ -	BPF_FIELD_BYTE_SIZE = 1,	/* field size in bytes */ -	BPF_FIELD_EXISTS = 2,		/* field existence in target kernel */ -	BPF_FIELD_SIGNED = 3,		/* field signedness (0 - unsigned, 1 - signed) */ -	BPF_FIELD_LSHIFT_U64 = 4,	/* bitfield-specific left bitshift */ -	BPF_FIELD_RSHIFT_U64 = 5,	/* bitfield-specific right bitshift */ -	BPF_TYPE_ID_LOCAL = 6,		/* type ID in local BPF object */ -	BPF_TYPE_ID_TARGET = 7,		/* type ID in target kernel */ -	BPF_TYPE_EXISTS = 8,		/* type existence in target kernel */ -	BPF_TYPE_SIZE = 9,		/* type size in bytes */ -	BPF_ENUMVAL_EXISTS = 10,	/* enum value existence in target kernel */ -	BPF_ENUMVAL_VALUE = 11,		/* enum value integer value */ -}; - -/* The minimum bpf_core_relo checked by the loader - * - * CO-RE relocation captures the following data: - * - insn_off - instruction offset (in bytes) within a BPF program that needs - *   its insn->imm field to be relocated with actual field info; - * - type_id - BTF type ID of the "root" (containing) entity of a relocatable - *   type or field; - * - access_str_off - offset into corresponding .BTF string section. String - *   interpretation depends on specific relocation kind: - *     - for field-based relocations, string encodes an accessed field using - *     a sequence of field and array indices, separated by colon (:). It's - *     conceptually very close to LLVM's getelementptr ([0]) instruction's - *     arguments for identifying offset to a field. - *     - for type-based relocations, strings is expected to be just "0"; - *     - for enum value-based relocations, string contains an index of enum - *     value within its enum type; - * - * Example to provide a better feel. - * - *   struct sample { - *       int a; - *       struct { - *           int b[10]; - *       }; - *   }; - * - *   struct sample *s = ...; - *   int x = &s->a;     // encoded as "0:0" (a is field #0) - *   int y = &s->b[5];  // encoded as "0:1:0:5" (anon struct is field #1,  - *                      // b is field #0 inside anon struct, accessing elem #5) - *   int z = &s[10]->b; // encoded as "10:1" (ptr is used as an array) - * - * type_id for all relocs in this example  will capture BTF type id of - * `struct sample`. - * - * Such relocation is emitted when using __builtin_preserve_access_index() - * Clang built-in, passing expression that captures field address, e.g.: - * - * bpf_probe_read(&dst, sizeof(dst), - *		  __builtin_preserve_access_index(&src->a.b.c)); - * - * In this case Clang will emit field relocation recording necessary data to - * be able to find offset of embedded `a.b.c` field within `src` struct. - * - *   [0] https://llvm.org/docs/LangRef.html#getelementptr-instruction - */ -struct bpf_core_relo { -	__u32   insn_off; -	__u32   type_id; -	__u32   access_str_off; -	enum bpf_core_relo_kind kind; -};  typedef int (*type_id_visit_fn)(__u32 *type_id, void *ctx);  typedef int (*str_off_visit_fn)(__u32 *str_off, void *ctx); @@ -494,4 +437,14 @@ static inline void *libbpf_ptr(void *ret)  	return ret;  } +static inline bool str_is_empty(const char *s) +{ +	return !s || !s[0]; +} + +static inline bool is_ldimm64_insn(struct bpf_insn *insn) +{ +	return insn->code == (BPF_LD | BPF_IMM | BPF_DW); +} +  #endif /* __LIBBPF_LIBBPF_INTERNAL_H */ | 
