diff options
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r-- | tools/lib/bpf/libbpf.c | 148 |
1 files changed, 135 insertions, 13 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 3d35bacf656f..6513e0b08795 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -45,6 +45,7 @@ | |||
45 | 45 | ||
46 | #include "libbpf.h" | 46 | #include "libbpf.h" |
47 | #include "bpf.h" | 47 | #include "bpf.h" |
48 | #include "btf.h" | ||
48 | 49 | ||
49 | #ifndef EM_BPF | 50 | #ifndef EM_BPF |
50 | #define EM_BPF 247 | 51 | #define EM_BPF 247 |
@@ -212,6 +213,8 @@ struct bpf_map { | |||
212 | char *name; | 213 | char *name; |
213 | size_t offset; | 214 | size_t offset; |
214 | struct bpf_map_def def; | 215 | struct bpf_map_def def; |
216 | uint32_t btf_key_id; | ||
217 | uint32_t btf_value_id; | ||
215 | void *priv; | 218 | void *priv; |
216 | bpf_map_clear_priv_t clear_priv; | 219 | bpf_map_clear_priv_t clear_priv; |
217 | }; | 220 | }; |
@@ -256,6 +259,8 @@ struct bpf_object { | |||
256 | */ | 259 | */ |
257 | struct list_head list; | 260 | struct list_head list; |
258 | 261 | ||
262 | struct btf *btf; | ||
263 | |||
259 | void *priv; | 264 | void *priv; |
260 | bpf_object_clear_priv_t clear_priv; | 265 | bpf_object_clear_priv_t clear_priv; |
261 | 266 | ||
@@ -819,7 +824,15 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
819 | data->d_size); | 824 | data->d_size); |
820 | else if (strcmp(name, "maps") == 0) | 825 | else if (strcmp(name, "maps") == 0) |
821 | obj->efile.maps_shndx = idx; | 826 | obj->efile.maps_shndx = idx; |
822 | else if (sh.sh_type == SHT_SYMTAB) { | 827 | else if (strcmp(name, BTF_ELF_SEC) == 0) { |
828 | obj->btf = btf__new(data->d_buf, data->d_size, | ||
829 | __pr_debug); | ||
830 | if (IS_ERR(obj->btf)) { | ||
831 | pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n", | ||
832 | BTF_ELF_SEC, PTR_ERR(obj->btf)); | ||
833 | obj->btf = NULL; | ||
834 | } | ||
835 | } else if (sh.sh_type == SHT_SYMTAB) { | ||
823 | if (obj->efile.symbols) { | 836 | if (obj->efile.symbols) { |
824 | pr_warning("bpf: multiple SYMTAB in %s\n", | 837 | pr_warning("bpf: multiple SYMTAB in %s\n", |
825 | obj->path); | 838 | obj->path); |
@@ -996,33 +1009,126 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr, | |||
996 | return 0; | 1009 | return 0; |
997 | } | 1010 | } |
998 | 1011 | ||
1012 | static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) | ||
1013 | { | ||
1014 | struct bpf_map_def *def = &map->def; | ||
1015 | const size_t max_name = 256; | ||
1016 | int64_t key_size, value_size; | ||
1017 | int32_t key_id, value_id; | ||
1018 | char name[max_name]; | ||
1019 | |||
1020 | /* Find key type by name from BTF */ | ||
1021 | if (snprintf(name, max_name, "%s_key", map->name) == max_name) { | ||
1022 | pr_warning("map:%s length of BTF key_type:%s_key is too long\n", | ||
1023 | map->name, map->name); | ||
1024 | return -EINVAL; | ||
1025 | } | ||
1026 | |||
1027 | key_id = btf__find_by_name(btf, name); | ||
1028 | if (key_id < 0) { | ||
1029 | pr_debug("map:%s key_type:%s cannot be found in BTF\n", | ||
1030 | map->name, name); | ||
1031 | return key_id; | ||
1032 | } | ||
1033 | |||
1034 | key_size = btf__resolve_size(btf, key_id); | ||
1035 | if (key_size < 0) { | ||
1036 | pr_warning("map:%s key_type:%s cannot get the BTF type_size\n", | ||
1037 | map->name, name); | ||
1038 | return key_size; | ||
1039 | } | ||
1040 | |||
1041 | if (def->key_size != key_size) { | ||
1042 | pr_warning("map:%s key_type:%s has BTF type_size:%ld != key_size:%u\n", | ||
1043 | map->name, name, key_size, def->key_size); | ||
1044 | return -EINVAL; | ||
1045 | } | ||
1046 | |||
1047 | /* Find value type from BTF */ | ||
1048 | if (snprintf(name, max_name, "%s_value", map->name) == max_name) { | ||
1049 | pr_warning("map:%s length of BTF value_type:%s_value is too long\n", | ||
1050 | map->name, map->name); | ||
1051 | return -EINVAL; | ||
1052 | } | ||
1053 | |||
1054 | value_id = btf__find_by_name(btf, name); | ||
1055 | if (value_id < 0) { | ||
1056 | pr_debug("map:%s value_type:%s cannot be found in BTF\n", | ||
1057 | map->name, name); | ||
1058 | return value_id; | ||
1059 | } | ||
1060 | |||
1061 | value_size = btf__resolve_size(btf, value_id); | ||
1062 | if (value_size < 0) { | ||
1063 | pr_warning("map:%s value_type:%s cannot get the BTF type_size\n", | ||
1064 | map->name, name); | ||
1065 | return value_size; | ||
1066 | } | ||
1067 | |||
1068 | if (def->value_size != value_size) { | ||
1069 | pr_warning("map:%s value_type:%s has BTF type_size:%ld != value_size:%u\n", | ||
1070 | map->name, name, value_size, def->value_size); | ||
1071 | return -EINVAL; | ||
1072 | } | ||
1073 | |||
1074 | map->btf_key_id = key_id; | ||
1075 | map->btf_value_id = value_id; | ||
1076 | |||
1077 | return 0; | ||
1078 | } | ||
1079 | |||
999 | static int | 1080 | static int |
1000 | bpf_object__create_maps(struct bpf_object *obj) | 1081 | bpf_object__create_maps(struct bpf_object *obj) |
1001 | { | 1082 | { |
1083 | struct bpf_create_map_attr create_attr = {}; | ||
1002 | unsigned int i; | 1084 | unsigned int i; |
1085 | int err; | ||
1003 | 1086 | ||
1004 | for (i = 0; i < obj->nr_maps; i++) { | 1087 | for (i = 0; i < obj->nr_maps; i++) { |
1005 | struct bpf_map_def *def = &obj->maps[i].def; | 1088 | struct bpf_map *map = &obj->maps[i]; |
1006 | int *pfd = &obj->maps[i].fd; | 1089 | struct bpf_map_def *def = &map->def; |
1007 | 1090 | int *pfd = &map->fd; | |
1008 | *pfd = bpf_create_map_name(def->type, | 1091 | |
1009 | obj->maps[i].name, | 1092 | create_attr.name = map->name; |
1010 | def->key_size, | 1093 | create_attr.map_type = def->type; |
1011 | def->value_size, | 1094 | create_attr.map_flags = def->map_flags; |
1012 | def->max_entries, | 1095 | create_attr.key_size = def->key_size; |
1013 | def->map_flags); | 1096 | create_attr.value_size = def->value_size; |
1097 | create_attr.max_entries = def->max_entries; | ||
1098 | create_attr.btf_fd = 0; | ||
1099 | create_attr.btf_key_id = 0; | ||
1100 | create_attr.btf_value_id = 0; | ||
1101 | |||
1102 | if (obj->btf && !bpf_map_find_btf_info(map, obj->btf)) { | ||
1103 | create_attr.btf_fd = btf__fd(obj->btf); | ||
1104 | create_attr.btf_key_id = map->btf_key_id; | ||
1105 | create_attr.btf_value_id = map->btf_value_id; | ||
1106 | } | ||
1107 | |||
1108 | *pfd = bpf_create_map_xattr(&create_attr); | ||
1109 | if (*pfd < 0 && create_attr.btf_key_id) { | ||
1110 | pr_warning("Error in bpf_create_map_xattr(%s):%s(%d). Retrying without BTF.\n", | ||
1111 | map->name, strerror(errno), errno); | ||
1112 | create_attr.btf_fd = 0; | ||
1113 | create_attr.btf_key_id = 0; | ||
1114 | create_attr.btf_value_id = 0; | ||
1115 | map->btf_key_id = 0; | ||
1116 | map->btf_value_id = 0; | ||
1117 | *pfd = bpf_create_map_xattr(&create_attr); | ||
1118 | } | ||
1119 | |||
1014 | if (*pfd < 0) { | 1120 | if (*pfd < 0) { |
1015 | size_t j; | 1121 | size_t j; |
1016 | int err = *pfd; | ||
1017 | 1122 | ||
1123 | err = *pfd; | ||
1018 | pr_warning("failed to create map (name: '%s'): %s\n", | 1124 | pr_warning("failed to create map (name: '%s'): %s\n", |
1019 | obj->maps[i].name, | 1125 | map->name, |
1020 | strerror(errno)); | 1126 | strerror(errno)); |
1021 | for (j = 0; j < i; j++) | 1127 | for (j = 0; j < i; j++) |
1022 | zclose(obj->maps[j].fd); | 1128 | zclose(obj->maps[j].fd); |
1023 | return err; | 1129 | return err; |
1024 | } | 1130 | } |
1025 | pr_debug("create map %s: fd=%d\n", obj->maps[i].name, *pfd); | 1131 | pr_debug("create map %s: fd=%d\n", map->name, *pfd); |
1026 | } | 1132 | } |
1027 | 1133 | ||
1028 | return 0; | 1134 | return 0; |
@@ -1641,6 +1747,7 @@ void bpf_object__close(struct bpf_object *obj) | |||
1641 | 1747 | ||
1642 | bpf_object__elf_finish(obj); | 1748 | bpf_object__elf_finish(obj); |
1643 | bpf_object__unload(obj); | 1749 | bpf_object__unload(obj); |
1750 | btf__free(obj->btf); | ||
1644 | 1751 | ||
1645 | for (i = 0; i < obj->nr_maps; i++) { | 1752 | for (i = 0; i < obj->nr_maps; i++) { |
1646 | zfree(&obj->maps[i].name); | 1753 | zfree(&obj->maps[i].name); |
@@ -1692,6 +1799,11 @@ unsigned int bpf_object__kversion(struct bpf_object *obj) | |||
1692 | return obj ? obj->kern_version : 0; | 1799 | return obj ? obj->kern_version : 0; |
1693 | } | 1800 | } |
1694 | 1801 | ||
1802 | int bpf_object__btf_fd(const struct bpf_object *obj) | ||
1803 | { | ||
1804 | return obj->btf ? btf__fd(obj->btf) : -1; | ||
1805 | } | ||
1806 | |||
1695 | int bpf_object__set_priv(struct bpf_object *obj, void *priv, | 1807 | int bpf_object__set_priv(struct bpf_object *obj, void *priv, |
1696 | bpf_object_clear_priv_t clear_priv) | 1808 | bpf_object_clear_priv_t clear_priv) |
1697 | { | 1809 | { |
@@ -1937,6 +2049,16 @@ const char *bpf_map__name(struct bpf_map *map) | |||
1937 | return map ? map->name : NULL; | 2049 | return map ? map->name : NULL; |
1938 | } | 2050 | } |
1939 | 2051 | ||
2052 | uint32_t bpf_map__btf_key_id(const struct bpf_map *map) | ||
2053 | { | ||
2054 | return map ? map->btf_key_id : 0; | ||
2055 | } | ||
2056 | |||
2057 | uint32_t bpf_map__btf_value_id(const struct bpf_map *map) | ||
2058 | { | ||
2059 | return map ? map->btf_value_id : 0; | ||
2060 | } | ||
2061 | |||
1940 | int bpf_map__set_priv(struct bpf_map *map, void *priv, | 2062 | int bpf_map__set_priv(struct bpf_map *map, void *priv, |
1941 | bpf_map_clear_priv_t clear_priv) | 2063 | bpf_map_clear_priv_t clear_priv) |
1942 | { | 2064 | { |