diff options
Diffstat (limited to 'tools/lib/bpf')
| -rw-r--r-- | tools/lib/bpf/btf.c | 41 | ||||
| -rw-r--r-- | tools/lib/bpf/btf.h | 12 | ||||
| -rw-r--r-- | tools/lib/bpf/libbpf.c | 87 | ||||
| -rw-r--r-- | tools/lib/bpf/libbpf.h | 4 | 
4 files changed, 74 insertions, 70 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c index 8c54a4b6f187..c36a3a76986a 100644 --- a/tools/lib/bpf/btf.c +++ b/tools/lib/bpf/btf.c @@ -1,8 +1,7 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +// SPDX-License-Identifier: LGPL-2.1  /* Copyright (c) 2018 Facebook */  #include <stdlib.h> -#include <stdint.h>  #include <string.h>  #include <unistd.h>  #include <errno.h> @@ -27,13 +26,13 @@ struct btf {  	struct btf_type **types;  	const char *strings;  	void *nohdr_data; -	uint32_t nr_types; -	uint32_t types_size; -	uint32_t data_size; +	__u32 nr_types; +	__u32 types_size; +	__u32 data_size;  	int fd;  }; -static const char *btf_name_by_offset(const struct btf *btf, uint32_t offset) +static const char *btf_name_by_offset(const struct btf *btf, __u32 offset)  {  	if (offset < btf->hdr->str_len)  		return &btf->strings[offset]; @@ -45,7 +44,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)  {  	if (btf->types_size - btf->nr_types < 2) {  		struct btf_type **new_types; -		u32 expand_by, new_size; +		__u32 expand_by, new_size;  		if (btf->types_size == BTF_MAX_NR_TYPES)  			return -E2BIG; @@ -72,7 +71,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)  static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log)  {  	const struct btf_header *hdr = btf->hdr; -	u32 meta_left; +	__u32 meta_left;  	if (btf->data_size < sizeof(struct btf_header)) {  		elog("BTF header not found\n"); @@ -151,7 +150,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)  	while (next_type < end_type) {  		struct btf_type *t = next_type; -		uint16_t vlen = BTF_INFO_VLEN(t->info); +		__u16 vlen = BTF_INFO_VLEN(t->info);  		int err;  		next_type += sizeof(*t); @@ -190,8 +189,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)  	return 0;  } -static const struct btf_type *btf_type_by_id(const struct btf *btf, -					     uint32_t type_id) +const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 type_id)  {  	if (type_id > btf->nr_types)  		return NULL; @@ -209,7 +207,7 @@ static bool btf_type_is_void_or_null(const struct btf_type *t)  	return !t || btf_type_is_void(t);  } -static int64_t btf_type_size(const struct btf_type *t) +static __s64 btf_type_size(const struct btf_type *t)  {  	switch (BTF_INFO_KIND(t->info)) {  	case BTF_KIND_INT: @@ -226,15 +224,15 @@ static int64_t btf_type_size(const struct btf_type *t)  #define MAX_RESOLVE_DEPTH 32 -int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id) +__s64 btf__resolve_size(const struct btf *btf, __u32 type_id)  {  	const struct btf_array *array;  	const struct btf_type *t; -	uint32_t nelems = 1; -	int64_t size = -1; +	__u32 nelems = 1; +	__s64 size = -1;  	int i; -	t = btf_type_by_id(btf, type_id); +	t = btf__type_by_id(btf, type_id);  	for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t);  	     i++) {  		size = btf_type_size(t); @@ -259,7 +257,7 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)  			return -EINVAL;  		} -		t = btf_type_by_id(btf, type_id); +		t = btf__type_by_id(btf, type_id);  	}  	if (size < 0) @@ -271,9 +269,9 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)  	return nelems * size;  } -int32_t btf__find_by_name(const struct btf *btf, const char *type_name) +__s32 btf__find_by_name(const struct btf *btf, const char *type_name)  { -	uint32_t i; +	__u32 i;  	if (!strcmp(type_name, "void"))  		return 0; @@ -302,10 +300,9 @@ void btf__free(struct btf *btf)  	free(btf);  } -struct btf *btf__new(uint8_t *data, uint32_t size, -		     btf_print_fn_t err_log) +struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)  { -	uint32_t log_buf_size = 0; +	__u32 log_buf_size = 0;  	char *log_buf = NULL;  	struct btf *btf;  	int err; diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h index 74bb344035bb..caac3a404dc5 100644 --- a/tools/lib/bpf/btf.h +++ b/tools/lib/bpf/btf.h @@ -1,22 +1,24 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: LGPL-2.1 */  /* Copyright (c) 2018 Facebook */  #ifndef __BPF_BTF_H  #define __BPF_BTF_H -#include <stdint.h> +#include <linux/types.h>  #define BTF_ELF_SEC ".BTF"  struct btf; +struct btf_type;  typedef int (*btf_print_fn_t)(const char *, ...)  	__attribute__((format(printf, 1, 2)));  void btf__free(struct btf *btf); -struct btf *btf__new(uint8_t *data, uint32_t size, btf_print_fn_t err_log); -int32_t btf__find_by_name(const struct btf *btf, const char *type_name); -int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id); +struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log); +__s32 btf__find_by_name(const struct btf *btf, const char *type_name); +const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id); +__s64 btf__resolve_size(const struct btf *btf, __u32 type_id);  int btf__fd(const struct btf *btf);  #endif diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index a1e96b5de5ff..1aafdbe827fe 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -36,6 +36,7 @@  #include <linux/err.h>  #include <linux/kernel.h>  #include <linux/bpf.h> +#include <linux/btf.h>  #include <linux/list.h>  #include <linux/limits.h>  #include <sys/stat.h> @@ -216,8 +217,8 @@ struct bpf_map {  	size_t offset;  	int map_ifindex;  	struct bpf_map_def def; -	uint32_t btf_key_type_id; -	uint32_t btf_value_type_id; +	__u32 btf_key_type_id; +	__u32 btf_value_type_id;  	void *priv;  	bpf_map_clear_priv_t clear_priv;  }; @@ -1014,68 +1015,72 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,  static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)  { +	const struct btf_type *container_type; +	const struct btf_member *key, *value;  	struct bpf_map_def *def = &map->def;  	const size_t max_name = 256; -	int64_t key_size, value_size; -	int32_t key_id, value_id; -	char name[max_name]; +	char container_name[max_name]; +	__s64 key_size, value_size; +	__s32 container_id; -	/* Find key type by name from BTF */ -	if (snprintf(name, max_name, "%s_key", map->name) == max_name) { -		pr_warning("map:%s length of BTF key_type:%s_key is too long\n", +	if (snprintf(container_name, max_name, "____btf_map_%s", map->name) == +	    max_name) { +		pr_warning("map:%s length of '____btf_map_%s' is too long\n",  			   map->name, map->name);  		return -EINVAL;  	} -	key_id = btf__find_by_name(btf, name); -	if (key_id < 0) { -		pr_debug("map:%s key_type:%s cannot be found in BTF\n", -			 map->name, name); -		return key_id; +	container_id = btf__find_by_name(btf, container_name); +	if (container_id < 0) { +		pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n", +			 map->name, container_name); +		return container_id;  	} -	key_size = btf__resolve_size(btf, key_id); -	if (key_size < 0) { -		pr_warning("map:%s key_type:%s cannot get the BTF type_size\n", -			   map->name, name); -		return key_size; +	container_type = btf__type_by_id(btf, container_id); +	if (!container_type) { +		pr_warning("map:%s cannot find BTF type for container_id:%u\n", +			   map->name, container_id); +		return -EINVAL;  	} -	if (def->key_size != key_size) { -		pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n", -			   map->name, name, (unsigned int)key_size, def->key_size); +	if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT || +	    BTF_INFO_VLEN(container_type->info) < 2) { +		pr_warning("map:%s container_name:%s is an invalid container struct\n", +			   map->name, container_name);  		return -EINVAL;  	} -	/* Find value type from BTF */ -	if (snprintf(name, max_name, "%s_value", map->name) == max_name) { -		pr_warning("map:%s length of BTF value_type:%s_value is too long\n", -			  map->name, map->name); -		return -EINVAL; +	key = (struct btf_member *)(container_type + 1); +	value = key + 1; + +	key_size = btf__resolve_size(btf, key->type); +	if (key_size < 0) { +		pr_warning("map:%s invalid BTF key_type_size\n", +			   map->name); +		return key_size;  	} -	value_id = btf__find_by_name(btf, name); -	if (value_id < 0) { -		pr_debug("map:%s value_type:%s cannot be found in BTF\n", -			 map->name, name); -		return value_id; +	if (def->key_size != key_size) { +		pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n", +			   map->name, (__u32)key_size, def->key_size); +		return -EINVAL;  	} -	value_size = btf__resolve_size(btf, value_id); +	value_size = btf__resolve_size(btf, value->type);  	if (value_size < 0) { -		pr_warning("map:%s value_type:%s cannot get the BTF type_size\n", -			   map->name, name); +		pr_warning("map:%s invalid BTF value_type_size\n", map->name);  		return value_size;  	}  	if (def->value_size != value_size) { -		pr_warning("map:%s value_type:%s has BTF type_size:%u != value_size:%u\n", -			   map->name, name, (unsigned int)value_size, def->value_size); +		pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n", +			   map->name, (__u32)value_size, def->value_size);  		return -EINVAL;  	} -	map->btf_key_type_id = key_id; -	map->btf_value_type_id = value_id; +	map->btf_key_type_id = key->type; +	map->btf_value_type_id = value->type;  	return 0;  } @@ -2089,12 +2094,12 @@ const char *bpf_map__name(struct bpf_map *map)  	return map ? map->name : NULL;  } -uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map) +__u32 bpf_map__btf_key_type_id(const struct bpf_map *map)  {  	return map ? map->btf_key_type_id : 0;  } -uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map) +__u32 bpf_map__btf_value_type_id(const struct bpf_map *map)  {  	return map ? map->btf_value_type_id : 0;  } @@ -2268,8 +2273,8 @@ bpf_perf_event_read_simple(void *mem, unsigned long size,  	volatile struct perf_event_mmap_page *header = mem;  	__u64 data_tail = header->data_tail;  	__u64 data_head = header->data_head; +	int ret = LIBBPF_PERF_EVENT_ERROR;  	void *base, *begin, *end; -	int ret;  	asm volatile("" ::: "memory"); /* in real code it should be smp_rmb() */  	if (data_head == data_tail) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 09976531aa74..b33ae02f7d0e 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -244,8 +244,8 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);  int bpf_map__fd(struct bpf_map *map);  const struct bpf_map_def *bpf_map__def(struct bpf_map *map);  const char *bpf_map__name(struct bpf_map *map); -uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map); -uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map); +__u32 bpf_map__btf_key_type_id(const struct bpf_map *map); +__u32 bpf_map__btf_value_type_id(const struct bpf_map *map);  typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);  int bpf_map__set_priv(struct bpf_map *map, void *priv,  | 
