aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/lib/bpf/btf.h1
-rw-r--r--tools/lib/bpf/libbpf.c353
2 files changed, 345 insertions, 9 deletions
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index ba4ffa831aa4..88a52ae56fc6 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -17,6 +17,7 @@ extern "C" {
17 17
18#define BTF_ELF_SEC ".BTF" 18#define BTF_ELF_SEC ".BTF"
19#define BTF_EXT_ELF_SEC ".BTF.ext" 19#define BTF_EXT_ELF_SEC ".BTF.ext"
20#define MAPS_ELF_SEC ".maps"
20 21
21struct btf; 22struct btf;
22struct btf_ext; 23struct btf_ext;
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
1012static 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
1031static 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
1068static 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
1268static 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
1010static int bpf_object__init_maps(struct bpf_object *obj, int flags) 1318static 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
1428static bool bpf_object__is_btf_mandatory(const struct bpf_object *obj)
1429{
1430 return obj->efile.btf_maps_shndx >= 0;
1431}
1432
1116static int bpf_object__init_btf(struct bpf_object *obj, 1433static 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 }
1151out: 1469out:
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,
1355static bool bpf_object__shndx_is_maps(const struct bpf_object *obj, 1685static 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
1361static bool bpf_object__relo_in_known_section(const struct bpf_object *obj, 1692static 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
1503static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) 1834static 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;