diff options
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r-- | tools/lib/bpf/libbpf.c | 87 |
1 files changed, 46 insertions, 41 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 955f8eafbf41..26e9527ee464 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/err.h> | 37 | #include <linux/err.h> |
38 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
39 | #include <linux/bpf.h> | 39 | #include <linux/bpf.h> |
40 | #include <linux/btf.h> | ||
40 | #include <linux/list.h> | 41 | #include <linux/list.h> |
41 | #include <linux/limits.h> | 42 | #include <linux/limits.h> |
42 | #include <sys/stat.h> | 43 | #include <sys/stat.h> |
@@ -170,8 +171,8 @@ struct bpf_map { | |||
170 | size_t offset; | 171 | size_t offset; |
171 | int map_ifindex; | 172 | int map_ifindex; |
172 | struct bpf_map_def def; | 173 | struct bpf_map_def def; |
173 | uint32_t btf_key_type_id; | 174 | __u32 btf_key_type_id; |
174 | uint32_t btf_value_type_id; | 175 | __u32 btf_value_type_id; |
175 | void *priv; | 176 | void *priv; |
176 | bpf_map_clear_priv_t clear_priv; | 177 | bpf_map_clear_priv_t clear_priv; |
177 | }; | 178 | }; |
@@ -969,68 +970,72 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr, | |||
969 | 970 | ||
970 | static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) | 971 | static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) |
971 | { | 972 | { |
973 | const struct btf_type *container_type; | ||
974 | const struct btf_member *key, *value; | ||
972 | struct bpf_map_def *def = &map->def; | 975 | struct bpf_map_def *def = &map->def; |
973 | const size_t max_name = 256; | 976 | const size_t max_name = 256; |
974 | int64_t key_size, value_size; | 977 | char container_name[max_name]; |
975 | int32_t key_id, value_id; | 978 | __s64 key_size, value_size; |
976 | char name[max_name]; | 979 | __s32 container_id; |
977 | 980 | ||
978 | /* Find key type by name from BTF */ | 981 | if (snprintf(container_name, max_name, "____btf_map_%s", map->name) == |
979 | if (snprintf(name, max_name, "%s_key", map->name) == max_name) { | 982 | max_name) { |
980 | pr_warning("map:%s length of BTF key_type:%s_key is too long\n", | 983 | pr_warning("map:%s length of '____btf_map_%s' is too long\n", |
981 | map->name, map->name); | 984 | map->name, map->name); |
982 | return -EINVAL; | 985 | return -EINVAL; |
983 | } | 986 | } |
984 | 987 | ||
985 | key_id = btf__find_by_name(btf, name); | 988 | container_id = btf__find_by_name(btf, container_name); |
986 | if (key_id < 0) { | 989 | if (container_id < 0) { |
987 | pr_debug("map:%s key_type:%s cannot be found in BTF\n", | 990 | pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n", |
988 | map->name, name); | 991 | map->name, container_name); |
989 | return key_id; | 992 | return container_id; |
990 | } | 993 | } |
991 | 994 | ||
992 | key_size = btf__resolve_size(btf, key_id); | 995 | container_type = btf__type_by_id(btf, container_id); |
993 | if (key_size < 0) { | 996 | if (!container_type) { |
994 | pr_warning("map:%s key_type:%s cannot get the BTF type_size\n", | 997 | pr_warning("map:%s cannot find BTF type for container_id:%u\n", |
995 | map->name, name); | 998 | map->name, container_id); |
996 | return key_size; | 999 | return -EINVAL; |
997 | } | 1000 | } |
998 | 1001 | ||
999 | if (def->key_size != key_size) { | 1002 | if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT || |
1000 | pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n", | 1003 | BTF_INFO_VLEN(container_type->info) < 2) { |
1001 | map->name, name, (unsigned int)key_size, def->key_size); | 1004 | pr_warning("map:%s container_name:%s is an invalid container struct\n", |
1005 | map->name, container_name); | ||
1002 | return -EINVAL; | 1006 | return -EINVAL; |
1003 | } | 1007 | } |
1004 | 1008 | ||
1005 | /* Find value type from BTF */ | 1009 | key = (struct btf_member *)(container_type + 1); |
1006 | if (snprintf(name, max_name, "%s_value", map->name) == max_name) { | 1010 | value = key + 1; |
1007 | pr_warning("map:%s length of BTF value_type:%s_value is too long\n", | 1011 | |
1008 | map->name, map->name); | 1012 | key_size = btf__resolve_size(btf, key->type); |
1009 | return -EINVAL; | 1013 | if (key_size < 0) { |
1014 | pr_warning("map:%s invalid BTF key_type_size\n", | ||
1015 | map->name); | ||
1016 | return key_size; | ||
1010 | } | 1017 | } |
1011 | 1018 | ||
1012 | value_id = btf__find_by_name(btf, name); | 1019 | if (def->key_size != key_size) { |
1013 | if (value_id < 0) { | 1020 | pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n", |
1014 | pr_debug("map:%s value_type:%s cannot be found in BTF\n", | 1021 | map->name, (__u32)key_size, def->key_size); |
1015 | map->name, name); | 1022 | return -EINVAL; |
1016 | return value_id; | ||
1017 | } | 1023 | } |
1018 | 1024 | ||
1019 | value_size = btf__resolve_size(btf, value_id); | 1025 | value_size = btf__resolve_size(btf, value->type); |
1020 | if (value_size < 0) { | 1026 | if (value_size < 0) { |
1021 | pr_warning("map:%s value_type:%s cannot get the BTF type_size\n", | 1027 | pr_warning("map:%s invalid BTF value_type_size\n", map->name); |
1022 | map->name, name); | ||
1023 | return value_size; | 1028 | return value_size; |
1024 | } | 1029 | } |
1025 | 1030 | ||
1026 | if (def->value_size != value_size) { | 1031 | if (def->value_size != value_size) { |
1027 | pr_warning("map:%s value_type:%s has BTF type_size:%u != value_size:%u\n", | 1032 | pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n", |
1028 | map->name, name, (unsigned int)value_size, def->value_size); | 1033 | map->name, (__u32)value_size, def->value_size); |
1029 | return -EINVAL; | 1034 | return -EINVAL; |
1030 | } | 1035 | } |
1031 | 1036 | ||
1032 | map->btf_key_type_id = key_id; | 1037 | map->btf_key_type_id = key->type; |
1033 | map->btf_value_type_id = value_id; | 1038 | map->btf_value_type_id = value->type; |
1034 | 1039 | ||
1035 | return 0; | 1040 | return 0; |
1036 | } | 1041 | } |
@@ -2141,12 +2146,12 @@ const char *bpf_map__name(struct bpf_map *map) | |||
2141 | return map ? map->name : NULL; | 2146 | return map ? map->name : NULL; |
2142 | } | 2147 | } |
2143 | 2148 | ||
2144 | uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map) | 2149 | __u32 bpf_map__btf_key_type_id(const struct bpf_map *map) |
2145 | { | 2150 | { |
2146 | return map ? map->btf_key_type_id : 0; | 2151 | return map ? map->btf_key_type_id : 0; |
2147 | } | 2152 | } |
2148 | 2153 | ||
2149 | uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map) | 2154 | __u32 bpf_map__btf_value_type_id(const struct bpf_map *map) |
2150 | { | 2155 | { |
2151 | return map ? map->btf_value_type_id : 0; | 2156 | return map ? map->btf_value_type_id : 0; |
2152 | } | 2157 | } |
@@ -2333,8 +2338,8 @@ bpf_perf_event_read_simple(void *mem, unsigned long size, | |||
2333 | volatile struct perf_event_mmap_page *header = mem; | 2338 | volatile struct perf_event_mmap_page *header = mem; |
2334 | __u64 data_tail = header->data_tail; | 2339 | __u64 data_tail = header->data_tail; |
2335 | __u64 data_head = header->data_head; | 2340 | __u64 data_head = header->data_head; |
2341 | int ret = LIBBPF_PERF_EVENT_ERROR; | ||
2336 | void *base, *begin, *end; | 2342 | void *base, *begin, *end; |
2337 | int ret; | ||
2338 | 2343 | ||
2339 | asm volatile("" ::: "memory"); /* in real code it should be smp_rmb() */ | 2344 | asm volatile("" ::: "memory"); /* in real code it should be smp_rmb() */ |
2340 | if (data_head == data_tail) | 2345 | if (data_head == data_tail) |