diff options
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r-- | tools/lib/bpf/libbpf.c | 353 |
1 files changed, 344 insertions, 9 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index da942ab2f06a..585e3a2f1eb4 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -262,6 +262,7 @@ struct bpf_object { | |||
262 | } *reloc; | 262 | } *reloc; |
263 | int nr_reloc; | 263 | int nr_reloc; |
264 | int maps_shndx; | 264 | int maps_shndx; |
265 | int btf_maps_shndx; | ||
265 | int text_shndx; | 266 | int text_shndx; |
266 | int data_shndx; | 267 | int data_shndx; |
267 | int rodata_shndx; | 268 | int rodata_shndx; |
@@ -514,6 +515,7 @@ static struct bpf_object *bpf_object__new(const char *path, | |||
514 | obj->efile.obj_buf = obj_buf; | 515 | obj->efile.obj_buf = obj_buf; |
515 | obj->efile.obj_buf_sz = obj_buf_sz; | 516 | obj->efile.obj_buf_sz = obj_buf_sz; |
516 | obj->efile.maps_shndx = -1; | 517 | obj->efile.maps_shndx = -1; |
518 | obj->efile.btf_maps_shndx = -1; | ||
517 | obj->efile.data_shndx = -1; | 519 | obj->efile.data_shndx = -1; |
518 | obj->efile.rodata_shndx = -1; | 520 | obj->efile.rodata_shndx = -1; |
519 | obj->efile.bss_shndx = -1; | 521 | obj->efile.bss_shndx = -1; |
@@ -1007,6 +1009,312 @@ static int bpf_object__init_user_maps(struct bpf_object *obj, bool strict) | |||
1007 | return 0; | 1009 | return 0; |
1008 | } | 1010 | } |
1009 | 1011 | ||
1012 | static const struct btf_type *skip_mods_and_typedefs(const struct btf *btf, | ||
1013 | __u32 id) | ||
1014 | { | ||
1015 | const struct btf_type *t = btf__type_by_id(btf, id); | ||
1016 | |||
1017 | while (true) { | ||
1018 | switch (BTF_INFO_KIND(t->info)) { | ||
1019 | case BTF_KIND_VOLATILE: | ||
1020 | case BTF_KIND_CONST: | ||
1021 | case BTF_KIND_RESTRICT: | ||
1022 | case BTF_KIND_TYPEDEF: | ||
1023 | t = btf__type_by_id(btf, t->type); | ||
1024 | break; | ||
1025 | default: | ||
1026 | return t; | ||
1027 | } | ||
1028 | } | ||
1029 | } | ||
1030 | |||
1031 | static bool get_map_field_int(const char *map_name, | ||
1032 | const struct btf *btf, | ||
1033 | const struct btf_type *def, | ||
1034 | const struct btf_member *m, | ||
1035 | const void *data, __u32 *res) { | ||
1036 | const struct btf_type *t = skip_mods_and_typedefs(btf, m->type); | ||
1037 | const char *name = btf__name_by_offset(btf, m->name_off); | ||
1038 | __u32 int_info = *(const __u32 *)(const void *)(t + 1); | ||
1039 | |||
1040 | if (BTF_INFO_KIND(t->info) != BTF_KIND_INT) { | ||
1041 | pr_warning("map '%s': attr '%s': expected INT, got %u.\n", | ||
1042 | map_name, name, BTF_INFO_KIND(t->info)); | ||
1043 | return false; | ||
1044 | } | ||
1045 | if (t->size != 4 || BTF_INT_BITS(int_info) != 32 || | ||
1046 | BTF_INT_OFFSET(int_info)) { | ||
1047 | pr_warning("map '%s': attr '%s': expected 32-bit non-bitfield integer, " | ||
1048 | "got %u-byte (%d-bit) one with bit offset %d.\n", | ||
1049 | map_name, name, t->size, BTF_INT_BITS(int_info), | ||
1050 | BTF_INT_OFFSET(int_info)); | ||
1051 | return false; | ||
1052 | } | ||
1053 | if (BTF_INFO_KFLAG(def->info) && BTF_MEMBER_BITFIELD_SIZE(m->offset)) { | ||
1054 | pr_warning("map '%s': attr '%s': bitfield is not supported.\n", | ||
1055 | map_name, name); | ||
1056 | return false; | ||
1057 | } | ||
1058 | if (m->offset % 32) { | ||
1059 | pr_warning("map '%s': attr '%s': unaligned fields are not supported.\n", | ||
1060 | map_name, name); | ||
1061 | return false; | ||
1062 | } | ||
1063 | |||
1064 | *res = *(const __u32 *)(data + m->offset / 8); | ||
1065 | return true; | ||
1066 | } | ||
1067 | |||
1068 | static int bpf_object__init_user_btf_map(struct bpf_object *obj, | ||
1069 | const struct btf_type *sec, | ||
1070 | int var_idx, int sec_idx, | ||
1071 | const Elf_Data *data, bool strict) | ||
1072 | { | ||
1073 | const struct btf_type *var, *def, *t; | ||
1074 | const struct btf_var_secinfo *vi; | ||
1075 | const struct btf_var *var_extra; | ||
1076 | const struct btf_member *m; | ||
1077 | const void *def_data; | ||
1078 | const char *map_name; | ||
1079 | struct bpf_map *map; | ||
1080 | int vlen, i; | ||
1081 | |||
1082 | vi = (const struct btf_var_secinfo *)(const void *)(sec + 1) + var_idx; | ||
1083 | var = btf__type_by_id(obj->btf, vi->type); | ||
1084 | var_extra = (const void *)(var + 1); | ||
1085 | map_name = btf__name_by_offset(obj->btf, var->name_off); | ||
1086 | vlen = BTF_INFO_VLEN(var->info); | ||
1087 | |||
1088 | if (map_name == NULL || map_name[0] == '\0') { | ||
1089 | pr_warning("map #%d: empty name.\n", var_idx); | ||
1090 | return -EINVAL; | ||
1091 | } | ||
1092 | if ((__u64)vi->offset + vi->size > data->d_size) { | ||
1093 | pr_warning("map '%s' BTF data is corrupted.\n", map_name); | ||
1094 | return -EINVAL; | ||
1095 | } | ||
1096 | if (BTF_INFO_KIND(var->info) != BTF_KIND_VAR) { | ||
1097 | pr_warning("map '%s': unexpected var kind %u.\n", | ||
1098 | map_name, BTF_INFO_KIND(var->info)); | ||
1099 | return -EINVAL; | ||
1100 | } | ||
1101 | if (var_extra->linkage != BTF_VAR_GLOBAL_ALLOCATED && | ||
1102 | var_extra->linkage != BTF_VAR_STATIC) { | ||
1103 | pr_warning("map '%s': unsupported var linkage %u.\n", | ||
1104 | map_name, var_extra->linkage); | ||
1105 | return -EOPNOTSUPP; | ||
1106 | } | ||
1107 | |||
1108 | def = skip_mods_and_typedefs(obj->btf, var->type); | ||
1109 | if (BTF_INFO_KIND(def->info) != BTF_KIND_STRUCT) { | ||
1110 | pr_warning("map '%s': unexpected def kind %u.\n", | ||
1111 | map_name, BTF_INFO_KIND(var->info)); | ||
1112 | return -EINVAL; | ||
1113 | } | ||
1114 | if (def->size > vi->size) { | ||
1115 | pr_warning("map '%s': invalid def size.\n", map_name); | ||
1116 | return -EINVAL; | ||
1117 | } | ||
1118 | |||
1119 | map = bpf_object__add_map(obj); | ||
1120 | if (IS_ERR(map)) | ||
1121 | return PTR_ERR(map); | ||
1122 | map->name = strdup(map_name); | ||
1123 | if (!map->name) { | ||
1124 | pr_warning("map '%s': failed to alloc map name.\n", map_name); | ||
1125 | return -ENOMEM; | ||
1126 | } | ||
1127 | map->libbpf_type = LIBBPF_MAP_UNSPEC; | ||
1128 | map->def.type = BPF_MAP_TYPE_UNSPEC; | ||
1129 | map->sec_idx = sec_idx; | ||
1130 | map->sec_offset = vi->offset; | ||
1131 | pr_debug("map '%s': at sec_idx %d, offset %zu.\n", | ||
1132 | map_name, map->sec_idx, map->sec_offset); | ||
1133 | |||
1134 | def_data = data->d_buf + vi->offset; | ||
1135 | vlen = BTF_INFO_VLEN(def->info); | ||
1136 | m = (const void *)(def + 1); | ||
1137 | for (i = 0; i < vlen; i++, m++) { | ||
1138 | const char *name = btf__name_by_offset(obj->btf, m->name_off); | ||
1139 | |||
1140 | if (!name) { | ||
1141 | pr_warning("map '%s': invalid field #%d.\n", | ||
1142 | map_name, i); | ||
1143 | return -EINVAL; | ||
1144 | } | ||
1145 | if (strcmp(name, "type") == 0) { | ||
1146 | if (!get_map_field_int(map_name, obj->btf, def, m, | ||
1147 | def_data, &map->def.type)) | ||
1148 | return -EINVAL; | ||
1149 | pr_debug("map '%s': found type = %u.\n", | ||
1150 | map_name, map->def.type); | ||
1151 | } else if (strcmp(name, "max_entries") == 0) { | ||
1152 | if (!get_map_field_int(map_name, obj->btf, def, m, | ||
1153 | def_data, &map->def.max_entries)) | ||
1154 | return -EINVAL; | ||
1155 | pr_debug("map '%s': found max_entries = %u.\n", | ||
1156 | map_name, map->def.max_entries); | ||
1157 | } else if (strcmp(name, "map_flags") == 0) { | ||
1158 | if (!get_map_field_int(map_name, obj->btf, def, m, | ||
1159 | def_data, &map->def.map_flags)) | ||
1160 | return -EINVAL; | ||
1161 | pr_debug("map '%s': found map_flags = %u.\n", | ||
1162 | map_name, map->def.map_flags); | ||
1163 | } else if (strcmp(name, "key_size") == 0) { | ||
1164 | __u32 sz; | ||
1165 | |||
1166 | if (!get_map_field_int(map_name, obj->btf, def, m, | ||
1167 | def_data, &sz)) | ||
1168 | return -EINVAL; | ||
1169 | pr_debug("map '%s': found key_size = %u.\n", | ||
1170 | map_name, sz); | ||
1171 | if (map->def.key_size && map->def.key_size != sz) { | ||
1172 | pr_warning("map '%s': conflictling key size %u != %u.\n", | ||
1173 | map_name, map->def.key_size, sz); | ||
1174 | return -EINVAL; | ||
1175 | } | ||
1176 | map->def.key_size = sz; | ||
1177 | } else if (strcmp(name, "key") == 0) { | ||
1178 | __s64 sz; | ||
1179 | |||
1180 | t = btf__type_by_id(obj->btf, m->type); | ||
1181 | if (!t) { | ||
1182 | pr_warning("map '%s': key type [%d] not found.\n", | ||
1183 | map_name, m->type); | ||
1184 | return -EINVAL; | ||
1185 | } | ||
1186 | if (BTF_INFO_KIND(t->info) != BTF_KIND_PTR) { | ||
1187 | pr_warning("map '%s': key spec is not PTR: %u.\n", | ||
1188 | map_name, BTF_INFO_KIND(t->info)); | ||
1189 | return -EINVAL; | ||
1190 | } | ||
1191 | sz = btf__resolve_size(obj->btf, t->type); | ||
1192 | if (sz < 0) { | ||
1193 | pr_warning("map '%s': can't determine key size for type [%u]: %lld.\n", | ||
1194 | map_name, t->type, sz); | ||
1195 | return sz; | ||
1196 | } | ||
1197 | pr_debug("map '%s': found key [%u], sz = %lld.\n", | ||
1198 | map_name, t->type, sz); | ||
1199 | if (map->def.key_size && map->def.key_size != sz) { | ||
1200 | pr_warning("map '%s': conflictling key size %u != %lld.\n", | ||
1201 | map_name, map->def.key_size, sz); | ||
1202 | return -EINVAL; | ||
1203 | } | ||
1204 | map->def.key_size = sz; | ||
1205 | map->btf_key_type_id = t->type; | ||
1206 | } else if (strcmp(name, "value_size") == 0) { | ||
1207 | __u32 sz; | ||
1208 | |||
1209 | if (!get_map_field_int(map_name, obj->btf, def, m, | ||
1210 | def_data, &sz)) | ||
1211 | return -EINVAL; | ||
1212 | pr_debug("map '%s': found value_size = %u.\n", | ||
1213 | map_name, sz); | ||
1214 | if (map->def.value_size && map->def.value_size != sz) { | ||
1215 | pr_warning("map '%s': conflictling value size %u != %u.\n", | ||
1216 | map_name, map->def.value_size, sz); | ||
1217 | return -EINVAL; | ||
1218 | } | ||
1219 | map->def.value_size = sz; | ||
1220 | } else if (strcmp(name, "value") == 0) { | ||
1221 | __s64 sz; | ||
1222 | |||
1223 | t = btf__type_by_id(obj->btf, m->type); | ||
1224 | if (!t) { | ||
1225 | pr_warning("map '%s': value type [%d] not found.\n", | ||
1226 | map_name, m->type); | ||
1227 | return -EINVAL; | ||
1228 | } | ||
1229 | if (BTF_INFO_KIND(t->info) != BTF_KIND_PTR) { | ||
1230 | pr_warning("map '%s': value spec is not PTR: %u.\n", | ||
1231 | map_name, BTF_INFO_KIND(t->info)); | ||
1232 | return -EINVAL; | ||
1233 | } | ||
1234 | sz = btf__resolve_size(obj->btf, t->type); | ||
1235 | if (sz < 0) { | ||
1236 | pr_warning("map '%s': can't determine value size for type [%u]: %lld.\n", | ||
1237 | map_name, t->type, sz); | ||
1238 | return sz; | ||
1239 | } | ||
1240 | pr_debug("map '%s': found value [%u], sz = %lld.\n", | ||
1241 | map_name, t->type, sz); | ||
1242 | if (map->def.value_size && map->def.value_size != sz) { | ||
1243 | pr_warning("map '%s': conflictling value size %u != %lld.\n", | ||
1244 | map_name, map->def.value_size, sz); | ||
1245 | return -EINVAL; | ||
1246 | } | ||
1247 | map->def.value_size = sz; | ||
1248 | map->btf_value_type_id = t->type; | ||
1249 | } else { | ||
1250 | if (strict) { | ||
1251 | pr_warning("map '%s': unknown field '%s'.\n", | ||
1252 | map_name, name); | ||
1253 | return -ENOTSUP; | ||
1254 | } | ||
1255 | pr_debug("map '%s': ignoring unknown field '%s'.\n", | ||
1256 | map_name, name); | ||
1257 | } | ||
1258 | } | ||
1259 | |||
1260 | if (map->def.type == BPF_MAP_TYPE_UNSPEC) { | ||
1261 | pr_warning("map '%s': map type isn't specified.\n", map_name); | ||
1262 | return -EINVAL; | ||
1263 | } | ||
1264 | |||
1265 | return 0; | ||
1266 | } | ||
1267 | |||
1268 | static int bpf_object__init_user_btf_maps(struct bpf_object *obj, bool strict) | ||
1269 | { | ||
1270 | const struct btf_type *sec = NULL; | ||
1271 | int nr_types, i, vlen, err; | ||
1272 | const struct btf_type *t; | ||
1273 | const char *name; | ||
1274 | Elf_Data *data; | ||
1275 | Elf_Scn *scn; | ||
1276 | |||
1277 | if (obj->efile.btf_maps_shndx < 0) | ||
1278 | return 0; | ||
1279 | |||
1280 | scn = elf_getscn(obj->efile.elf, obj->efile.btf_maps_shndx); | ||
1281 | if (scn) | ||
1282 | data = elf_getdata(scn, NULL); | ||
1283 | if (!scn || !data) { | ||
1284 | pr_warning("failed to get Elf_Data from map section %d (%s)\n", | ||
1285 | obj->efile.maps_shndx, MAPS_ELF_SEC); | ||
1286 | return -EINVAL; | ||
1287 | } | ||
1288 | |||
1289 | nr_types = btf__get_nr_types(obj->btf); | ||
1290 | for (i = 1; i <= nr_types; i++) { | ||
1291 | t = btf__type_by_id(obj->btf, i); | ||
1292 | if (BTF_INFO_KIND(t->info) != BTF_KIND_DATASEC) | ||
1293 | continue; | ||
1294 | name = btf__name_by_offset(obj->btf, t->name_off); | ||
1295 | if (strcmp(name, MAPS_ELF_SEC) == 0) { | ||
1296 | sec = t; | ||
1297 | break; | ||
1298 | } | ||
1299 | } | ||
1300 | |||
1301 | if (!sec) { | ||
1302 | pr_warning("DATASEC '%s' not found.\n", MAPS_ELF_SEC); | ||
1303 | return -ENOENT; | ||
1304 | } | ||
1305 | |||
1306 | vlen = BTF_INFO_VLEN(sec->info); | ||
1307 | for (i = 0; i < vlen; i++) { | ||
1308 | err = bpf_object__init_user_btf_map(obj, sec, i, | ||
1309 | obj->efile.btf_maps_shndx, | ||
1310 | data, strict); | ||
1311 | if (err) | ||
1312 | return err; | ||
1313 | } | ||
1314 | |||
1315 | return 0; | ||
1316 | } | ||
1317 | |||
1010 | static int bpf_object__init_maps(struct bpf_object *obj, int flags) | 1318 | static int bpf_object__init_maps(struct bpf_object *obj, int flags) |
1011 | { | 1319 | { |
1012 | bool strict = !(flags & MAPS_RELAX_COMPAT); | 1320 | bool strict = !(flags & MAPS_RELAX_COMPAT); |
@@ -1016,6 +1324,10 @@ static int bpf_object__init_maps(struct bpf_object *obj, int flags) | |||
1016 | if (err) | 1324 | if (err) |
1017 | return err; | 1325 | return err; |
1018 | 1326 | ||
1327 | err = bpf_object__init_user_btf_maps(obj, strict); | ||
1328 | if (err) | ||
1329 | return err; | ||
1330 | |||
1019 | err = bpf_object__init_global_data_maps(obj); | 1331 | err = bpf_object__init_global_data_maps(obj); |
1020 | if (err) | 1332 | if (err) |
1021 | return err; | 1333 | return err; |
@@ -1113,10 +1425,16 @@ static void bpf_object__sanitize_btf_ext(struct bpf_object *obj) | |||
1113 | } | 1425 | } |
1114 | } | 1426 | } |
1115 | 1427 | ||
1428 | static bool bpf_object__is_btf_mandatory(const struct bpf_object *obj) | ||
1429 | { | ||
1430 | return obj->efile.btf_maps_shndx >= 0; | ||
1431 | } | ||
1432 | |||
1116 | static int bpf_object__init_btf(struct bpf_object *obj, | 1433 | static int bpf_object__init_btf(struct bpf_object *obj, |
1117 | Elf_Data *btf_data, | 1434 | Elf_Data *btf_data, |
1118 | Elf_Data *btf_ext_data) | 1435 | Elf_Data *btf_ext_data) |
1119 | { | 1436 | { |
1437 | bool btf_required = bpf_object__is_btf_mandatory(obj); | ||
1120 | int err = 0; | 1438 | int err = 0; |
1121 | 1439 | ||
1122 | if (btf_data) { | 1440 | if (btf_data) { |
@@ -1150,10 +1468,18 @@ static int bpf_object__init_btf(struct bpf_object *obj, | |||
1150 | } | 1468 | } |
1151 | out: | 1469 | out: |
1152 | if (err || IS_ERR(obj->btf)) { | 1470 | if (err || IS_ERR(obj->btf)) { |
1471 | if (btf_required) | ||
1472 | err = err ? : PTR_ERR(obj->btf); | ||
1473 | else | ||
1474 | err = 0; | ||
1153 | if (!IS_ERR_OR_NULL(obj->btf)) | 1475 | if (!IS_ERR_OR_NULL(obj->btf)) |
1154 | btf__free(obj->btf); | 1476 | btf__free(obj->btf); |
1155 | obj->btf = NULL; | 1477 | obj->btf = NULL; |
1156 | } | 1478 | } |
1479 | if (btf_required && !obj->btf) { | ||
1480 | pr_warning("BTF is required, but is missing or corrupted.\n"); | ||
1481 | return err == 0 ? -ENOENT : err; | ||
1482 | } | ||
1157 | return 0; | 1483 | return 0; |
1158 | } | 1484 | } |
1159 | 1485 | ||
@@ -1173,6 +1499,8 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj) | |||
1173 | BTF_ELF_SEC, err); | 1499 | BTF_ELF_SEC, err); |
1174 | btf__free(obj->btf); | 1500 | btf__free(obj->btf); |
1175 | obj->btf = NULL; | 1501 | obj->btf = NULL; |
1502 | if (bpf_object__is_btf_mandatory(obj)) | ||
1503 | return err; | ||
1176 | } | 1504 | } |
1177 | return 0; | 1505 | return 0; |
1178 | } | 1506 | } |
@@ -1236,6 +1564,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags) | |||
1236 | return err; | 1564 | return err; |
1237 | } else if (strcmp(name, "maps") == 0) { | 1565 | } else if (strcmp(name, "maps") == 0) { |
1238 | obj->efile.maps_shndx = idx; | 1566 | obj->efile.maps_shndx = idx; |
1567 | } else if (strcmp(name, MAPS_ELF_SEC) == 0) { | ||
1568 | obj->efile.btf_maps_shndx = idx; | ||
1239 | } else if (strcmp(name, BTF_ELF_SEC) == 0) { | 1569 | } else if (strcmp(name, BTF_ELF_SEC) == 0) { |
1240 | btf_data = data; | 1570 | btf_data = data; |
1241 | } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) { | 1571 | } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) { |
@@ -1355,7 +1685,8 @@ static bool bpf_object__shndx_is_data(const struct bpf_object *obj, | |||
1355 | static bool bpf_object__shndx_is_maps(const struct bpf_object *obj, | 1685 | static bool bpf_object__shndx_is_maps(const struct bpf_object *obj, |
1356 | int shndx) | 1686 | int shndx) |
1357 | { | 1687 | { |
1358 | return shndx == obj->efile.maps_shndx; | 1688 | return shndx == obj->efile.maps_shndx || |
1689 | shndx == obj->efile.btf_maps_shndx; | ||
1359 | } | 1690 | } |
1360 | 1691 | ||
1361 | static bool bpf_object__relo_in_known_section(const struct bpf_object *obj, | 1692 | static bool bpf_object__relo_in_known_section(const struct bpf_object *obj, |
@@ -1399,14 +1730,14 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr, | |||
1399 | prog->nr_reloc = nrels; | 1730 | prog->nr_reloc = nrels; |
1400 | 1731 | ||
1401 | for (i = 0; i < nrels; i++) { | 1732 | for (i = 0; i < nrels; i++) { |
1402 | GElf_Sym sym; | ||
1403 | GElf_Rel rel; | ||
1404 | unsigned int insn_idx; | ||
1405 | unsigned int shdr_idx; | ||
1406 | struct bpf_insn *insns = prog->insns; | 1733 | struct bpf_insn *insns = prog->insns; |
1407 | enum libbpf_map_type type; | 1734 | enum libbpf_map_type type; |
1735 | unsigned int insn_idx; | ||
1736 | unsigned int shdr_idx; | ||
1408 | const char *name; | 1737 | const char *name; |
1409 | size_t map_idx; | 1738 | size_t map_idx; |
1739 | GElf_Sym sym; | ||
1740 | GElf_Rel rel; | ||
1410 | 1741 | ||
1411 | if (!gelf_getrel(data, i, &rel)) { | 1742 | if (!gelf_getrel(data, i, &rel)) { |
1412 | pr_warning("relocation: failed to get %d reloc\n", i); | 1743 | pr_warning("relocation: failed to get %d reloc\n", i); |
@@ -1500,14 +1831,18 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr, | |||
1500 | return 0; | 1831 | return 0; |
1501 | } | 1832 | } |
1502 | 1833 | ||
1503 | static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) | 1834 | static int bpf_map_find_btf_info(struct bpf_object *obj, struct bpf_map *map) |
1504 | { | 1835 | { |
1505 | struct bpf_map_def *def = &map->def; | 1836 | struct bpf_map_def *def = &map->def; |
1506 | __u32 key_type_id = 0, value_type_id = 0; | 1837 | __u32 key_type_id = 0, value_type_id = 0; |
1507 | int ret; | 1838 | int ret; |
1508 | 1839 | ||
1840 | /* if it's BTF-defined map, we don't need to search for type IDs */ | ||
1841 | if (map->sec_idx == obj->efile.btf_maps_shndx) | ||
1842 | return 0; | ||
1843 | |||
1509 | if (!bpf_map__is_internal(map)) { | 1844 | if (!bpf_map__is_internal(map)) { |
1510 | ret = btf__get_map_kv_tids(btf, map->name, def->key_size, | 1845 | ret = btf__get_map_kv_tids(obj->btf, map->name, def->key_size, |
1511 | def->value_size, &key_type_id, | 1846 | def->value_size, &key_type_id, |
1512 | &value_type_id); | 1847 | &value_type_id); |
1513 | } else { | 1848 | } else { |
@@ -1515,7 +1850,7 @@ static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) | |||
1515 | * LLVM annotates global data differently in BTF, that is, | 1850 | * LLVM annotates global data differently in BTF, that is, |
1516 | * only as '.data', '.bss' or '.rodata'. | 1851 | * only as '.data', '.bss' or '.rodata'. |
1517 | */ | 1852 | */ |
1518 | ret = btf__find_by_name(btf, | 1853 | ret = btf__find_by_name(obj->btf, |
1519 | libbpf_type_to_btf_name[map->libbpf_type]); | 1854 | libbpf_type_to_btf_name[map->libbpf_type]); |
1520 | } | 1855 | } |
1521 | if (ret < 0) | 1856 | if (ret < 0) |
@@ -1805,7 +2140,7 @@ bpf_object__create_maps(struct bpf_object *obj) | |||
1805 | map->inner_map_fd >= 0) | 2140 | map->inner_map_fd >= 0) |
1806 | create_attr.inner_map_fd = map->inner_map_fd; | 2141 | create_attr.inner_map_fd = map->inner_map_fd; |
1807 | 2142 | ||
1808 | if (obj->btf && !bpf_map_find_btf_info(map, obj->btf)) { | 2143 | if (obj->btf && !bpf_map_find_btf_info(obj, map)) { |
1809 | create_attr.btf_fd = btf__fd(obj->btf); | 2144 | create_attr.btf_fd = btf__fd(obj->btf); |
1810 | create_attr.btf_key_type_id = map->btf_key_type_id; | 2145 | create_attr.btf_key_type_id = map->btf_key_type_id; |
1811 | create_attr.btf_value_type_id = map->btf_value_type_id; | 2146 | create_attr.btf_value_type_id = map->btf_value_type_id; |