Lines Matching +full:ext +full:- +full:gen
1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
6 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
67 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
208 [BPF_PROG_TYPE_EXT] = "ext",
260 if (err != -EPERM || geteuid() != 0) in pr_perm_msg()
277 pr_warn("permission error while running as root; try raising 'ulimit -l'? current value: %s\n", in pr_perm_msg()
293 fd = -1; \
304 /* as of v1.0 libbpf_set_strict_mode() is a no-op */ in libbpf_set_strict_mode()
350 /* stored as sec_def->cookie for all libbpf-supported SEC()s */
369 /* BPF program support non-linear XDP buffer */
407 * program. For the entry-point (main) BPF program, this is always
408 * zero. For a sub-program, this gets reset before each of main BPF
410 * whether sub-program was already appended to the main program, and
422 * entry-point BPF programs this includes the size of main program
423 * itself plus all the used sub-programs, appended at the end
472 * kern_vdata-size == sizeof(struct bpf_struct_ops_tcp_congestion_ops)
578 /* BTF fd index to be patched in for insn->off, this is
579 * 0 for vmlinux BTF, index in obj->fd_array for module
664 /* Path to the custom BTF to be used for BPF CO-RE relocations as an
668 /* vmlinux BTF override for CO-RE relocations */
705 zclose(prog->fd); in bpf_program__unload()
707 zfree(&prog->func_info); in bpf_program__unload()
708 zfree(&prog->line_info); in bpf_program__unload()
717 zfree(&prog->name); in bpf_program__exit()
718 zfree(&prog->sec_name); in bpf_program__exit()
719 zfree(&prog->insns); in bpf_program__exit()
720 zfree(&prog->reloc_desc); in bpf_program__exit()
722 prog->nr_reloc = 0; in bpf_program__exit()
723 prog->insns_cnt = 0; in bpf_program__exit()
724 prog->sec_idx = -1; in bpf_program__exit()
729 return BPF_CLASS(insn->code) == BPF_JMP && in insn_is_subprog_call()
730 BPF_OP(insn->code) == BPF_CALL && in insn_is_subprog_call()
731 BPF_SRC(insn->code) == BPF_K && in insn_is_subprog_call()
732 insn->src_reg == BPF_PSEUDO_CALL && in insn_is_subprog_call()
733 insn->dst_reg == 0 && in insn_is_subprog_call()
734 insn->off == 0; in insn_is_subprog_call()
739 return insn->code == (BPF_JMP | BPF_CALL); in is_call_insn()
744 return is_ldimm64_insn(insn) && insn->src_reg == BPF_PSEUDO_FUNC; in insn_is_pseudo_func()
755 return -EINVAL; in bpf_object__init_prog()
759 prog->obj = obj; in bpf_object__init_prog()
761 prog->sec_idx = sec_idx; in bpf_object__init_prog()
762 prog->sec_insn_off = sec_off / BPF_INSN_SZ; in bpf_object__init_prog()
763 prog->sec_insn_cnt = insn_data_sz / BPF_INSN_SZ; in bpf_object__init_prog()
765 prog->insns_cnt = prog->sec_insn_cnt; in bpf_object__init_prog()
767 prog->type = BPF_PROG_TYPE_UNSPEC; in bpf_object__init_prog()
768 prog->fd = -1; in bpf_object__init_prog()
775 prog->autoload = false; in bpf_object__init_prog()
779 prog->autoload = true; in bpf_object__init_prog()
782 prog->autoattach = true; in bpf_object__init_prog()
785 prog->log_level = obj->log_level; in bpf_object__init_prog()
787 prog->sec_name = strdup(sec_name); in bpf_object__init_prog()
788 if (!prog->sec_name) in bpf_object__init_prog()
791 prog->name = strdup(name); in bpf_object__init_prog()
792 if (!prog->name) in bpf_object__init_prog()
795 prog->insns = malloc(insn_data_sz); in bpf_object__init_prog()
796 if (!prog->insns) in bpf_object__init_prog()
798 memcpy(prog->insns, insn_data, insn_data_sz); in bpf_object__init_prog()
804 return -ENOMEM; in bpf_object__init_prog()
811 Elf_Data *symbols = obj->efile.symbols; in bpf_object__add_programs()
813 void *data = sec_data->d_buf; in bpf_object__add_programs()
814 size_t sec_sz = sec_data->d_size, sec_off, prog_sz, nr_syms; in bpf_object__add_programs()
819 progs = obj->programs; in bpf_object__add_programs()
820 nr_progs = obj->nr_programs; in bpf_object__add_programs()
821 nr_syms = symbols->d_size / sizeof(Elf64_Sym); in bpf_object__add_programs()
826 if (sym->st_shndx != sec_idx) in bpf_object__add_programs()
828 if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) in bpf_object__add_programs()
831 prog_sz = sym->st_size; in bpf_object__add_programs()
832 sec_off = sym->st_value; in bpf_object__add_programs()
834 name = elf_sym_str(obj, sym->st_name); in bpf_object__add_programs()
838 return -LIBBPF_ERRNO__FORMAT; in bpf_object__add_programs()
844 return -LIBBPF_ERRNO__FORMAT; in bpf_object__add_programs()
847 if (sec_idx != obj->efile.text_shndx && ELF64_ST_BIND(sym->st_info) == STB_LOCAL) { in bpf_object__add_programs()
849 return -ENOTSUP; in bpf_object__add_programs()
858 * In this case the original obj->programs in bpf_object__add_programs()
864 return -ENOMEM; in bpf_object__add_programs()
866 obj->programs = progs; in bpf_object__add_programs()
880 if (ELF64_ST_BIND(sym->st_info) != STB_LOCAL in bpf_object__add_programs()
881 && (ELF64_ST_VISIBILITY(sym->st_other) == STV_HIDDEN in bpf_object__add_programs()
882 || ELF64_ST_VISIBILITY(sym->st_other) == STV_INTERNAL)) in bpf_object__add_programs()
883 prog->mark_btf_static = true; in bpf_object__add_programs()
886 obj->nr_programs = nr_progs; in bpf_object__add_programs()
914 if (!strcmp(btf__name_by_offset(btf, m->name_off), name)) in find_member_by_name()
966 if (kern_data_member->type == kern_type_id) in find_struct_ops_kern_types()
972 return -EINVAL; in find_struct_ops_kern_types()
986 return map->def.type == BPF_MAP_TYPE_STRUCT_OPS; in bpf_map__is_struct_ops()
1002 st_ops = map->st_ops; in bpf_map__init_kern_struct_ops()
1003 type = st_ops->type; in bpf_map__init_kern_struct_ops()
1004 tname = st_ops->tname; in bpf_map__init_kern_struct_ops()
1013 map->name, st_ops->type_id, kern_type_id, kern_vtype_id); in bpf_map__init_kern_struct_ops()
1015 map->def.value_size = kern_vtype->size; in bpf_map__init_kern_struct_ops()
1016 map->btf_vmlinux_value_type_id = kern_vtype_id; in bpf_map__init_kern_struct_ops()
1018 st_ops->kern_vdata = calloc(1, kern_vtype->size); in bpf_map__init_kern_struct_ops()
1019 if (!st_ops->kern_vdata) in bpf_map__init_kern_struct_ops()
1020 return -ENOMEM; in bpf_map__init_kern_struct_ops()
1022 data = st_ops->data; in bpf_map__init_kern_struct_ops()
1023 kern_data_off = kern_data_member->offset / 8; in bpf_map__init_kern_struct_ops()
1024 kern_data = st_ops->kern_vdata + kern_data_off; in bpf_map__init_kern_struct_ops()
1036 mname = btf__name_by_offset(btf, member->name_off); in bpf_map__init_kern_struct_ops()
1040 map->name, mname); in bpf_map__init_kern_struct_ops()
1041 return -ENOTSUP; in bpf_map__init_kern_struct_ops()
1044 kern_member_idx = kern_member - btf_members(kern_type); in bpf_map__init_kern_struct_ops()
1048 map->name, mname); in bpf_map__init_kern_struct_ops()
1049 return -ENOTSUP; in bpf_map__init_kern_struct_ops()
1052 moff = member->offset / 8; in bpf_map__init_kern_struct_ops()
1053 kern_moff = kern_member->offset / 8; in bpf_map__init_kern_struct_ops()
1058 mtype = skip_mods_and_typedefs(btf, member->type, &mtype_id); in bpf_map__init_kern_struct_ops()
1059 kern_mtype = skip_mods_and_typedefs(kern_btf, kern_member->type, in bpf_map__init_kern_struct_ops()
1061 if (BTF_INFO_KIND(mtype->info) != in bpf_map__init_kern_struct_ops()
1062 BTF_INFO_KIND(kern_mtype->info)) { in bpf_map__init_kern_struct_ops()
1064 map->name, mname, BTF_INFO_KIND(mtype->info), in bpf_map__init_kern_struct_ops()
1065 BTF_INFO_KIND(kern_mtype->info)); in bpf_map__init_kern_struct_ops()
1066 return -ENOTSUP; in bpf_map__init_kern_struct_ops()
1072 prog = st_ops->progs[i]; in bpf_map__init_kern_struct_ops()
1077 kern_mtype->type, in bpf_map__init_kern_struct_ops()
1080 /* mtype->type must be a func_proto which was in bpf_map__init_kern_struct_ops()
1086 map->name, mname); in bpf_map__init_kern_struct_ops()
1087 return -ENOTSUP; in bpf_map__init_kern_struct_ops()
1090 prog->attach_btf_id = kern_type_id; in bpf_map__init_kern_struct_ops()
1091 prog->expected_attach_type = kern_member_idx; in bpf_map__init_kern_struct_ops()
1093 st_ops->kern_func_off[i] = kern_data_off + kern_moff; in bpf_map__init_kern_struct_ops()
1096 map->name, mname, prog->name, moff, in bpf_map__init_kern_struct_ops()
1106 map->name, mname, (ssize_t)msize, in bpf_map__init_kern_struct_ops()
1108 return -ENOTSUP; in bpf_map__init_kern_struct_ops()
1112 map->name, mname, (unsigned int)msize, in bpf_map__init_kern_struct_ops()
1126 for (i = 0; i < obj->nr_maps; i++) { in bpf_object__init_kern_struct_ops_maps()
1127 map = &obj->maps[i]; in bpf_object__init_kern_struct_ops_maps()
1132 err = bpf_map__init_kern_struct_ops(map, obj->btf, in bpf_object__init_kern_struct_ops_maps()
1133 obj->btf_vmlinux); in bpf_object__init_kern_struct_ops_maps()
1153 if (shndx == -1) in init_struct_ops_maps()
1156 btf = obj->btf; in init_struct_ops_maps()
1162 return -EINVAL; in init_struct_ops_maps()
1168 type = btf__type_by_id(obj->btf, vsi->type); in init_struct_ops_maps()
1169 var_name = btf__name_by_offset(obj->btf, type->name_off); in init_struct_ops_maps()
1171 type_id = btf__resolve_type(obj->btf, vsi->type); in init_struct_ops_maps()
1174 vsi->type, sec_name); in init_struct_ops_maps()
1175 return -EINVAL; in init_struct_ops_maps()
1178 type = btf__type_by_id(obj->btf, type_id); in init_struct_ops_maps()
1179 tname = btf__name_by_offset(obj->btf, type->name_off); in init_struct_ops_maps()
1182 return -ENOTSUP; in init_struct_ops_maps()
1186 return -EINVAL; in init_struct_ops_maps()
1193 map->sec_idx = shndx; in init_struct_ops_maps()
1194 map->sec_offset = vsi->offset; in init_struct_ops_maps()
1195 map->name = strdup(var_name); in init_struct_ops_maps()
1196 if (!map->name) in init_struct_ops_maps()
1197 return -ENOMEM; in init_struct_ops_maps()
1199 map->def.type = BPF_MAP_TYPE_STRUCT_OPS; in init_struct_ops_maps()
1200 map->def.key_size = sizeof(int); in init_struct_ops_maps()
1201 map->def.value_size = type->size; in init_struct_ops_maps()
1202 map->def.max_entries = 1; in init_struct_ops_maps()
1203 map->def.map_flags = map_flags; in init_struct_ops_maps()
1205 map->st_ops = calloc(1, sizeof(*map->st_ops)); in init_struct_ops_maps()
1206 if (!map->st_ops) in init_struct_ops_maps()
1207 return -ENOMEM; in init_struct_ops_maps()
1208 st_ops = map->st_ops; in init_struct_ops_maps()
1209 st_ops->data = malloc(type->size); in init_struct_ops_maps()
1210 st_ops->progs = calloc(btf_vlen(type), sizeof(*st_ops->progs)); in init_struct_ops_maps()
1211 st_ops->kern_func_off = malloc(btf_vlen(type) * in init_struct_ops_maps()
1212 sizeof(*st_ops->kern_func_off)); in init_struct_ops_maps()
1213 if (!st_ops->data || !st_ops->progs || !st_ops->kern_func_off) in init_struct_ops_maps()
1214 return -ENOMEM; in init_struct_ops_maps()
1216 if (vsi->offset + type->size > data->d_size) { in init_struct_ops_maps()
1219 return -EINVAL; in init_struct_ops_maps()
1222 memcpy(st_ops->data, in init_struct_ops_maps()
1223 data->d_buf + vsi->offset, in init_struct_ops_maps()
1224 type->size); in init_struct_ops_maps()
1225 st_ops->tname = tname; in init_struct_ops_maps()
1226 st_ops->type = type; in init_struct_ops_maps()
1227 st_ops->type_id = type_id; in init_struct_ops_maps()
1230 tname, type_id, var_name, vsi->offset); in init_struct_ops_maps()
1240 err = init_struct_ops_maps(obj, STRUCT_OPS_SEC, obj->efile.st_ops_shndx, in bpf_object_init_struct_ops()
1241 obj->efile.st_ops_data, 0); in bpf_object_init_struct_ops()
1243 obj->efile.st_ops_link_shndx, in bpf_object_init_struct_ops()
1244 obj->efile.st_ops_link_data, in bpf_object_init_struct_ops()
1260 return ERR_PTR(-ENOMEM); in bpf_object__new()
1263 strcpy(obj->path, path); in bpf_object__new()
1265 libbpf_strlcpy(obj->name, obj_name, sizeof(obj->name)); in bpf_object__new()
1268 libbpf_strlcpy(obj->name, basename((void *)path), sizeof(obj->name)); in bpf_object__new()
1269 end = strchr(obj->name, '.'); in bpf_object__new()
1274 obj->efile.fd = -1; in bpf_object__new()
1281 obj->efile.obj_buf = obj_buf; in bpf_object__new()
1282 obj->efile.obj_buf_sz = obj_buf_sz; in bpf_object__new()
1283 obj->efile.btf_maps_shndx = -1; in bpf_object__new()
1284 obj->efile.st_ops_shndx = -1; in bpf_object__new()
1285 obj->efile.st_ops_link_shndx = -1; in bpf_object__new()
1286 obj->kconfig_map_idx = -1; in bpf_object__new()
1288 obj->kern_version = get_kernel_version(); in bpf_object__new()
1289 obj->loaded = false; in bpf_object__new()
1296 if (!obj->efile.elf) in bpf_object__elf_finish()
1299 elf_end(obj->efile.elf); in bpf_object__elf_finish()
1300 obj->efile.elf = NULL; in bpf_object__elf_finish()
1301 obj->efile.symbols = NULL; in bpf_object__elf_finish()
1302 obj->efile.st_ops_data = NULL; in bpf_object__elf_finish()
1303 obj->efile.st_ops_link_data = NULL; in bpf_object__elf_finish()
1305 zfree(&obj->efile.secs); in bpf_object__elf_finish()
1306 obj->efile.sec_cnt = 0; in bpf_object__elf_finish()
1307 zclose(obj->efile.fd); in bpf_object__elf_finish()
1308 obj->efile.obj_buf = NULL; in bpf_object__elf_finish()
1309 obj->efile.obj_buf_sz = 0; in bpf_object__elf_finish()
1318 if (obj->efile.elf) { in bpf_object__elf_init()
1320 return -LIBBPF_ERRNO__LIBELF; in bpf_object__elf_init()
1323 if (obj->efile.obj_buf_sz > 0) { in bpf_object__elf_init()
1325 elf = elf_memory((char *)obj->efile.obj_buf, obj->efile.obj_buf_sz); in bpf_object__elf_init()
1327 obj->efile.fd = open(obj->path, O_RDONLY | O_CLOEXEC); in bpf_object__elf_init()
1328 if (obj->efile.fd < 0) { in bpf_object__elf_init()
1331 err = -errno; in bpf_object__elf_init()
1333 pr_warn("elf: failed to open %s: %s\n", obj->path, cp); in bpf_object__elf_init()
1337 elf = elf_begin(obj->efile.fd, ELF_C_READ_MMAP, NULL); in bpf_object__elf_init()
1341 pr_warn("elf: failed to open %s as ELF file: %s\n", obj->path, elf_errmsg(-1)); in bpf_object__elf_init()
1342 err = -LIBBPF_ERRNO__LIBELF; in bpf_object__elf_init()
1346 obj->efile.elf = elf; in bpf_object__elf_init()
1349 err = -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_init()
1350 pr_warn("elf: '%s' is not a proper ELF object\n", obj->path); in bpf_object__elf_init()
1355 err = -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_init()
1356 pr_warn("elf: '%s' is not a 64-bit ELF object\n", obj->path); in bpf_object__elf_init()
1360 obj->efile.ehdr = ehdr = elf64_getehdr(elf); in bpf_object__elf_init()
1361 if (!obj->efile.ehdr) { in bpf_object__elf_init()
1362 pr_warn("elf: failed to get ELF header from %s: %s\n", obj->path, elf_errmsg(-1)); in bpf_object__elf_init()
1363 err = -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_init()
1367 if (elf_getshdrstrndx(elf, &obj->efile.shstrndx)) { in bpf_object__elf_init()
1369 obj->path, elf_errmsg(-1)); in bpf_object__elf_init()
1370 err = -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_init()
1375 if (!elf_rawdata(elf_getscn(elf, obj->efile.shstrndx), NULL)) { in bpf_object__elf_init()
1377 obj->path, elf_errmsg(-1)); in bpf_object__elf_init()
1378 err = -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_init()
1383 if (ehdr->e_type != ET_REL || (ehdr->e_machine && ehdr->e_machine != EM_BPF)) { in bpf_object__elf_init()
1384 pr_warn("elf: %s is not a valid eBPF object file\n", obj->path); in bpf_object__elf_init()
1385 err = -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_init()
1398 if (obj->efile.ehdr->e_ident[EI_DATA] == ELFDATA2LSB) in bpf_object__check_endianness()
1401 if (obj->efile.ehdr->e_ident[EI_DATA] == ELFDATA2MSB) in bpf_object__check_endianness()
1406 pr_warn("elf: endianness mismatch in %s.\n", obj->path); in bpf_object__check_endianness()
1407 return -LIBBPF_ERRNO__ENDIAN; in bpf_object__check_endianness()
1414 pr_warn("invalid license section in %s\n", obj->path); in bpf_object__init_license()
1415 return -LIBBPF_ERRNO__FORMAT; in bpf_object__init_license()
1417 /* libbpf_strlcpy() only copies first N - 1 bytes, so size + 1 won't in bpf_object__init_license()
1420 libbpf_strlcpy(obj->license, data, min(size + 1, sizeof(obj->license))); in bpf_object__init_license()
1421 pr_debug("license of %s is %s\n", obj->path, obj->license); in bpf_object__init_license()
1431 pr_warn("invalid kver section in %s\n", obj->path); in bpf_object__init_kversion()
1432 return -LIBBPF_ERRNO__FORMAT; in bpf_object__init_kversion()
1435 obj->kern_version = kver; in bpf_object__init_kversion()
1436 pr_debug("kernel version of %s is %x\n", obj->path, obj->kern_version); in bpf_object__init_kversion()
1454 return -EINVAL; in find_elf_sec_sz()
1459 *size = data->d_size; in find_elf_sec_sz()
1463 return -ENOENT; in find_elf_sec_sz()
1468 Elf_Data *symbols = obj->efile.symbols; in find_elf_var_sym()
1472 for (si = 0; si < symbols->d_size / sizeof(Elf64_Sym); si++) { in find_elf_var_sym()
1475 if (ELF64_ST_TYPE(sym->st_info) != STT_OBJECT) in find_elf_var_sym()
1478 if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL && in find_elf_var_sym()
1479 ELF64_ST_BIND(sym->st_info) != STB_WEAK) in find_elf_var_sym()
1482 sname = elf_sym_str(obj, sym->st_name); in find_elf_var_sym()
1485 return ERR_PTR(-EIO); in find_elf_var_sym()
1491 return ERR_PTR(-ENOENT); in find_elf_var_sym()
1499 err = libbpf_ensure_mem((void **)&obj->maps, &obj->maps_cap, in bpf_object__add_map()
1500 sizeof(*obj->maps), obj->nr_maps + 1); in bpf_object__add_map()
1504 map = &obj->maps[obj->nr_maps++]; in bpf_object__add_map()
1505 map->obj = obj; in bpf_object__add_map()
1506 map->fd = -1; in bpf_object__add_map()
1507 map->inner_map_fd = -1; in bpf_object__add_map()
1508 map->autocreate = true; in bpf_object__add_map()
1527 if (!map->mmaped) in bpf_map_mmap_resize()
1528 return -EINVAL; in bpf_map_mmap_resize()
1533 mmaped = mmap(NULL, new_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); in bpf_map_mmap_resize()
1535 return -errno; in bpf_map_mmap_resize()
1537 memcpy(mmaped, map->mmaped, min(old_sz, new_sz)); in bpf_map_mmap_resize()
1538 munmap(map->mmaped, old_sz); in bpf_map_mmap_resize()
1539 map->mmaped = mmaped; in bpf_map_mmap_resize()
1573 * '.rodata.abracad' kernel and user-visible name. in internal_map_name()
1582 sfx_len = BPF_OBJ_NAME_LEN - 1; in internal_map_name()
1588 pfx_len = min((size_t)BPF_OBJ_NAME_LEN - sfx_len - 1, strlen(obj->name)); in internal_map_name()
1590 snprintf(map_name, sizeof(map_name), "%.*s%.*s", pfx_len, obj->name, in internal_map_name()
1615 if (!map->btf_value_type_id) in map_is_mmapable()
1618 t = btf__type_by_id(obj->btf, map->btf_value_type_id); in map_is_mmapable()
1624 vt = btf__type_by_id(obj->btf, vsi->type); in map_is_mmapable()
1628 if (btf_var(vt)->linkage != BTF_VAR_STATIC) in map_is_mmapable()
1648 map->libbpf_type = type; in bpf_object__init_internal_map()
1649 map->sec_idx = sec_idx; in bpf_object__init_internal_map()
1650 map->sec_offset = 0; in bpf_object__init_internal_map()
1651 map->real_name = strdup(real_name); in bpf_object__init_internal_map()
1652 map->name = internal_map_name(obj, real_name); in bpf_object__init_internal_map()
1653 if (!map->real_name || !map->name) { in bpf_object__init_internal_map()
1654 zfree(&map->real_name); in bpf_object__init_internal_map()
1655 zfree(&map->name); in bpf_object__init_internal_map()
1656 return -ENOMEM; in bpf_object__init_internal_map()
1659 def = &map->def; in bpf_object__init_internal_map()
1660 def->type = BPF_MAP_TYPE_ARRAY; in bpf_object__init_internal_map()
1661 def->key_size = sizeof(int); in bpf_object__init_internal_map()
1662 def->value_size = data_sz; in bpf_object__init_internal_map()
1663 def->max_entries = 1; in bpf_object__init_internal_map()
1664 def->map_flags = type == LIBBPF_MAP_RODATA || type == LIBBPF_MAP_KCONFIG in bpf_object__init_internal_map()
1671 def->map_flags |= BPF_F_MMAPABLE; in bpf_object__init_internal_map()
1674 map->name, map->sec_idx, map->sec_offset, def->map_flags); in bpf_object__init_internal_map()
1676 mmap_sz = bpf_map_mmap_sz(map->def.value_size, map->def.max_entries); in bpf_object__init_internal_map()
1677 map->mmaped = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE, in bpf_object__init_internal_map()
1678 MAP_SHARED | MAP_ANONYMOUS, -1, 0); in bpf_object__init_internal_map()
1679 if (map->mmaped == MAP_FAILED) { in bpf_object__init_internal_map()
1680 err = -errno; in bpf_object__init_internal_map()
1681 map->mmaped = NULL; in bpf_object__init_internal_map()
1683 map->name, err); in bpf_object__init_internal_map()
1684 zfree(&map->real_name); in bpf_object__init_internal_map()
1685 zfree(&map->name); in bpf_object__init_internal_map()
1690 memcpy(map->mmaped, data, data_sz); in bpf_object__init_internal_map()
1692 pr_debug("map %td is \"%s\"\n", map - obj->maps, map->name); in bpf_object__init_internal_map()
1703 * Populate obj->maps with libbpf internal maps. in bpf_object__init_global_data_maps()
1705 for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) { in bpf_object__init_global_data_maps()
1706 sec_desc = &obj->efile.secs[sec_idx]; in bpf_object__init_global_data_maps()
1709 if (!sec_desc->data || sec_desc->data->d_size == 0) in bpf_object__init_global_data_maps()
1712 switch (sec_desc->sec_type) { in bpf_object__init_global_data_maps()
1717 sec_desc->data->d_buf, in bpf_object__init_global_data_maps()
1718 sec_desc->data->d_size); in bpf_object__init_global_data_maps()
1721 obj->has_rodata = true; in bpf_object__init_global_data_maps()
1725 sec_desc->data->d_buf, in bpf_object__init_global_data_maps()
1726 sec_desc->data->d_size); in bpf_object__init_global_data_maps()
1733 sec_desc->data->d_size); in bpf_object__init_global_data_maps()
1751 for (i = 0; i < obj->nr_extern; i++) { in find_extern_by_name()
1752 if (strcmp(obj->externs[i].name, name) == 0) in find_extern_by_name()
1753 return &obj->externs[i]; in find_extern_by_name()
1758 static int set_kcfg_value_tri(struct extern_desc *ext, void *ext_val, in set_kcfg_value_tri() argument
1761 switch (ext->kcfg.type) { in set_kcfg_value_tri()
1765 ext->name, value); in set_kcfg_value_tri()
1766 return -EINVAL; in set_kcfg_value_tri()
1786 ext->name, value); in set_kcfg_value_tri()
1787 return -EINVAL; in set_kcfg_value_tri()
1789 ext->is_set = true; in set_kcfg_value_tri()
1793 static int set_kcfg_value_str(struct extern_desc *ext, char *ext_val, in set_kcfg_value_str() argument
1798 if (ext->kcfg.type != KCFG_CHAR_ARR) { in set_kcfg_value_str()
1800 ext->name, value); in set_kcfg_value_str()
1801 return -EINVAL; in set_kcfg_value_str()
1805 if (value[len - 1] != '"') { in set_kcfg_value_str()
1807 ext->name, value); in set_kcfg_value_str()
1808 return -EINVAL; in set_kcfg_value_str()
1812 len -= 2; in set_kcfg_value_str()
1813 if (len >= ext->kcfg.sz) { in set_kcfg_value_str()
1815 ext->name, value, len, ext->kcfg.sz - 1); in set_kcfg_value_str()
1816 len = ext->kcfg.sz - 1; in set_kcfg_value_str()
1820 ext->is_set = true; in set_kcfg_value_str()
1832 err = -errno; in parse_u64()
1838 return -EINVAL; in parse_u64()
1843 static bool is_kcfg_value_in_range(const struct extern_desc *ext, __u64 v) in is_kcfg_value_in_range() argument
1845 int bit_sz = ext->kcfg.sz * 8; in is_kcfg_value_in_range()
1847 if (ext->kcfg.sz == 8) in is_kcfg_value_in_range()
1850 /* Validate that value stored in u64 fits in integer of `ext->sz` in is_kcfg_value_in_range()
1855 * -2^(Y-1) <= X <= 2^(Y-1) - 1 in is_kcfg_value_in_range()
1856 * 0 <= X + 2^(Y-1) <= 2^Y - 1 in is_kcfg_value_in_range()
1857 * 0 <= X + 2^(Y-1) < 2^Y in is_kcfg_value_in_range()
1859 * For unsigned target integer, check that all the (64 - Y) bits are in is_kcfg_value_in_range()
1862 if (ext->kcfg.is_signed) in is_kcfg_value_in_range()
1863 return v + (1ULL << (bit_sz - 1)) < (1ULL << bit_sz); in is_kcfg_value_in_range()
1868 static int set_kcfg_value_num(struct extern_desc *ext, void *ext_val, in set_kcfg_value_num() argument
1871 if (ext->kcfg.type != KCFG_INT && ext->kcfg.type != KCFG_CHAR && in set_kcfg_value_num()
1872 ext->kcfg.type != KCFG_BOOL) { in set_kcfg_value_num()
1874 ext->name, (unsigned long long)value); in set_kcfg_value_num()
1875 return -EINVAL; in set_kcfg_value_num()
1877 if (ext->kcfg.type == KCFG_BOOL && value > 1) { in set_kcfg_value_num()
1879 ext->name, (unsigned long long)value); in set_kcfg_value_num()
1880 return -EINVAL; in set_kcfg_value_num()
1883 if (!is_kcfg_value_in_range(ext, value)) { in set_kcfg_value_num()
1885 ext->name, (unsigned long long)value, ext->kcfg.sz); in set_kcfg_value_num()
1886 return -ERANGE; in set_kcfg_value_num()
1888 switch (ext->kcfg.sz) { in set_kcfg_value_num()
1902 return -EINVAL; in set_kcfg_value_num()
1904 ext->is_set = true; in set_kcfg_value_num()
1911 struct extern_desc *ext; in bpf_object__process_kconfig_line() local
1923 return -EINVAL; in bpf_object__process_kconfig_line()
1928 if (buf[len - 1] == '\n') in bpf_object__process_kconfig_line()
1929 buf[len - 1] = '\0'; in bpf_object__process_kconfig_line()
1935 return -EINVAL; in bpf_object__process_kconfig_line()
1938 ext = find_extern_by_name(obj, buf); in bpf_object__process_kconfig_line()
1939 if (!ext || ext->is_set) in bpf_object__process_kconfig_line()
1942 ext_val = data + ext->kcfg.data_off; in bpf_object__process_kconfig_line()
1947 err = set_kcfg_value_tri(ext, ext_val, *value); in bpf_object__process_kconfig_line()
1950 err = set_kcfg_value_str(ext, ext_val, value); in bpf_object__process_kconfig_line()
1956 pr_warn("extern (kcfg) '%s': value '%s' isn't a valid integer\n", ext->name, value); in bpf_object__process_kconfig_line()
1959 if (ext->kcfg.type != KCFG_INT && ext->kcfg.type != KCFG_CHAR) { in bpf_object__process_kconfig_line()
1960 pr_warn("extern (kcfg) '%s': value '%s' implies integer type\n", ext->name, value); in bpf_object__process_kconfig_line()
1961 return -EINVAL; in bpf_object__process_kconfig_line()
1963 err = set_kcfg_value_num(ext, ext_val, num); in bpf_object__process_kconfig_line()
1968 pr_debug("extern (kcfg) '%s': set to %s\n", ext->name, value); in bpf_object__process_kconfig_line()
1980 len = snprintf(buf, PATH_MAX, "/boot/config-%s", uts.release); in bpf_object__read_kconfig_file()
1982 return -EINVAL; in bpf_object__read_kconfig_file()
1984 return -ENAMETOOLONG; in bpf_object__read_kconfig_file()
1993 return -ENOENT; in bpf_object__read_kconfig_file()
2019 err = -errno; in bpf_object__read_kconfig_mem()
2020 pr_warn("failed to open in-memory Kconfig: %d\n", err); in bpf_object__read_kconfig_mem()
2027 pr_warn("error parsing in-memory Kconfig line '%s': %d\n", in bpf_object__read_kconfig_mem()
2039 struct extern_desc *last_ext = NULL, *ext; in bpf_object__init_kconfig_map() local
2043 for (i = 0; i < obj->nr_extern; i++) { in bpf_object__init_kconfig_map()
2044 ext = &obj->externs[i]; in bpf_object__init_kconfig_map()
2045 if (ext->type == EXT_KCFG) in bpf_object__init_kconfig_map()
2046 last_ext = ext; in bpf_object__init_kconfig_map()
2052 map_sz = last_ext->kcfg.data_off + last_ext->kcfg.sz; in bpf_object__init_kconfig_map()
2054 ".kconfig", obj->efile.symbols_shndx, in bpf_object__init_kconfig_map()
2059 obj->kconfig_map_idx = obj->nr_maps - 1; in bpf_object__init_kconfig_map()
2074 *res_id = t->type; in skip_mods_and_typedefs()
2075 t = btf__type_by_id(btf, t->type); in skip_mods_and_typedefs()
2090 t = skip_mods_and_typedefs(btf, t->type, res_id); in resolve_func_ptr()
2137 const struct btf_type *t = skip_mods_and_typedefs(btf, m->type, NULL); in get_map_field_int()
2138 const char *name = btf__name_by_offset(btf, m->name_off); in get_map_field_int()
2148 arr_t = btf__type_by_id(btf, t->type); in get_map_field_int()
2151 map_name, name, t->type); in get_map_field_int()
2160 *res = arr_info->nelems; in get_map_field_int()
2170 return -EINVAL; in pathname_concat()
2172 return -ENAMETOOLONG; in pathname_concat()
2211 const char *name = btf__name_by_offset(btf, m->name_off); in parse_btf_map_def()
2215 return -EINVAL; in parse_btf_map_def()
2218 if (!get_map_field_int(map_name, btf, m, &map_def->map_type)) in parse_btf_map_def()
2219 return -EINVAL; in parse_btf_map_def()
2220 map_def->parts |= MAP_DEF_MAP_TYPE; in parse_btf_map_def()
2222 if (!get_map_field_int(map_name, btf, m, &map_def->max_entries)) in parse_btf_map_def()
2223 return -EINVAL; in parse_btf_map_def()
2224 map_def->parts |= MAP_DEF_MAX_ENTRIES; in parse_btf_map_def()
2226 if (!get_map_field_int(map_name, btf, m, &map_def->map_flags)) in parse_btf_map_def()
2227 return -EINVAL; in parse_btf_map_def()
2228 map_def->parts |= MAP_DEF_MAP_FLAGS; in parse_btf_map_def()
2230 if (!get_map_field_int(map_name, btf, m, &map_def->numa_node)) in parse_btf_map_def()
2231 return -EINVAL; in parse_btf_map_def()
2232 map_def->parts |= MAP_DEF_NUMA_NODE; in parse_btf_map_def()
2237 return -EINVAL; in parse_btf_map_def()
2238 if (map_def->key_size && map_def->key_size != sz) { in parse_btf_map_def()
2240 map_name, map_def->key_size, sz); in parse_btf_map_def()
2241 return -EINVAL; in parse_btf_map_def()
2243 map_def->key_size = sz; in parse_btf_map_def()
2244 map_def->parts |= MAP_DEF_KEY_SIZE; in parse_btf_map_def()
2248 t = btf__type_by_id(btf, m->type); in parse_btf_map_def()
2251 map_name, m->type); in parse_btf_map_def()
2252 return -EINVAL; in parse_btf_map_def()
2257 return -EINVAL; in parse_btf_map_def()
2259 sz = btf__resolve_size(btf, t->type); in parse_btf_map_def()
2262 map_name, t->type, (ssize_t)sz); in parse_btf_map_def()
2265 if (map_def->key_size && map_def->key_size != sz) { in parse_btf_map_def()
2267 map_name, map_def->key_size, (ssize_t)sz); in parse_btf_map_def()
2268 return -EINVAL; in parse_btf_map_def()
2270 map_def->key_size = sz; in parse_btf_map_def()
2271 map_def->key_type_id = t->type; in parse_btf_map_def()
2272 map_def->parts |= MAP_DEF_KEY_SIZE | MAP_DEF_KEY_TYPE; in parse_btf_map_def()
2277 return -EINVAL; in parse_btf_map_def()
2278 if (map_def->value_size && map_def->value_size != sz) { in parse_btf_map_def()
2280 map_name, map_def->value_size, sz); in parse_btf_map_def()
2281 return -EINVAL; in parse_btf_map_def()
2283 map_def->value_size = sz; in parse_btf_map_def()
2284 map_def->parts |= MAP_DEF_VALUE_SIZE; in parse_btf_map_def()
2288 t = btf__type_by_id(btf, m->type); in parse_btf_map_def()
2291 map_name, m->type); in parse_btf_map_def()
2292 return -EINVAL; in parse_btf_map_def()
2297 return -EINVAL; in parse_btf_map_def()
2299 sz = btf__resolve_size(btf, t->type); in parse_btf_map_def()
2302 map_name, t->type, (ssize_t)sz); in parse_btf_map_def()
2305 if (map_def->value_size && map_def->value_size != sz) { in parse_btf_map_def()
2307 map_name, map_def->value_size, (ssize_t)sz); in parse_btf_map_def()
2308 return -EINVAL; in parse_btf_map_def()
2310 map_def->value_size = sz; in parse_btf_map_def()
2311 map_def->value_type_id = t->type; in parse_btf_map_def()
2312 map_def->parts |= MAP_DEF_VALUE_SIZE | MAP_DEF_VALUE_TYPE; in parse_btf_map_def()
2315 bool is_map_in_map = bpf_map_type__is_map_in_map(map_def->map_type); in parse_btf_map_def()
2316 bool is_prog_array = map_def->map_type == BPF_MAP_TYPE_PROG_ARRAY; in parse_btf_map_def()
2317 const char *desc = is_map_in_map ? "map-in-map inner" : "prog-array value"; in parse_btf_map_def()
2322 pr_warn("map '%s': multi-level inner maps not supported.\n", in parse_btf_map_def()
2324 return -ENOTSUP; in parse_btf_map_def()
2326 if (i != vlen - 1) { in parse_btf_map_def()
2329 return -EINVAL; in parse_btf_map_def()
2332 pr_warn("map '%s': should be map-in-map or prog-array.\n", in parse_btf_map_def()
2334 return -ENOTSUP; in parse_btf_map_def()
2336 if (map_def->value_size && map_def->value_size != 4) { in parse_btf_map_def()
2338 map_name, map_def->value_size); in parse_btf_map_def()
2339 return -EINVAL; in parse_btf_map_def()
2341 map_def->value_size = 4; in parse_btf_map_def()
2342 t = btf__type_by_id(btf, m->type); in parse_btf_map_def()
2345 map_name, desc, m->type); in parse_btf_map_def()
2346 return -EINVAL; in parse_btf_map_def()
2348 if (!btf_is_array(t) || btf_array(t)->nelems) { in parse_btf_map_def()
2349 pr_warn("map '%s': %s spec is not a zero-sized array.\n", in parse_btf_map_def()
2351 return -EINVAL; in parse_btf_map_def()
2353 t = skip_mods_and_typedefs(btf, btf_array(t)->type, NULL); in parse_btf_map_def()
2357 return -EINVAL; in parse_btf_map_def()
2359 t = skip_mods_and_typedefs(btf, t->type, NULL); in parse_btf_map_def()
2362 pr_warn("map '%s': prog-array value def is of unexpected kind %s.\n", in parse_btf_map_def()
2364 return -EINVAL; in parse_btf_map_def()
2369 pr_warn("map '%s': map-in-map inner def is of unexpected kind %s.\n", in parse_btf_map_def()
2371 return -EINVAL; in parse_btf_map_def()
2379 map_def->parts |= MAP_DEF_INNER_MAP; in parse_btf_map_def()
2385 return -EINVAL; in parse_btf_map_def()
2388 return -EINVAL; in parse_btf_map_def()
2392 return -EINVAL; in parse_btf_map_def()
2394 map_def->pinning = val; in parse_btf_map_def()
2395 map_def->parts |= MAP_DEF_PINNING; in parse_btf_map_def()
2400 return -EINVAL; in parse_btf_map_def()
2401 map_def->map_extra = map_extra; in parse_btf_map_def()
2402 map_def->parts |= MAP_DEF_MAP_EXTRA; in parse_btf_map_def()
2406 return -ENOTSUP; in parse_btf_map_def()
2412 if (map_def->map_type == BPF_MAP_TYPE_UNSPEC) { in parse_btf_map_def()
2414 return -EINVAL; in parse_btf_map_def()
2429 * a power-of-2 multiple of kernel's page size. If user diligently in adjust_ringbuf_sz()
2436 * user-set size to satisfy both user size request and kernel in adjust_ringbuf_sz()
2445 * very close to UINT_MAX but is not a power-of-2 multiple of in adjust_ringbuf_sz()
2453 return map->def.type == BPF_MAP_TYPE_RINGBUF || in map_is_ringbuf()
2454 map->def.type == BPF_MAP_TYPE_USER_RINGBUF; in map_is_ringbuf()
2459 map->def.type = def->map_type; in fill_map_from_def()
2460 map->def.key_size = def->key_size; in fill_map_from_def()
2461 map->def.value_size = def->value_size; in fill_map_from_def()
2462 map->def.max_entries = def->max_entries; in fill_map_from_def()
2463 map->def.map_flags = def->map_flags; in fill_map_from_def()
2464 map->map_extra = def->map_extra; in fill_map_from_def()
2466 map->numa_node = def->numa_node; in fill_map_from_def()
2467 map->btf_key_type_id = def->key_type_id; in fill_map_from_def()
2468 map->btf_value_type_id = def->value_type_id; in fill_map_from_def()
2470 /* auto-adjust BPF ringbuf map max_entries to be a multiple of page size */ in fill_map_from_def()
2472 map->def.max_entries = adjust_ringbuf_sz(map->def.max_entries); in fill_map_from_def()
2474 if (def->parts & MAP_DEF_MAP_TYPE) in fill_map_from_def()
2475 pr_debug("map '%s': found type = %u.\n", map->name, def->map_type); in fill_map_from_def()
2477 if (def->parts & MAP_DEF_KEY_TYPE) in fill_map_from_def()
2479 map->name, def->key_type_id, def->key_size); in fill_map_from_def()
2480 else if (def->parts & MAP_DEF_KEY_SIZE) in fill_map_from_def()
2481 pr_debug("map '%s': found key_size = %u.\n", map->name, def->key_size); in fill_map_from_def()
2483 if (def->parts & MAP_DEF_VALUE_TYPE) in fill_map_from_def()
2485 map->name, def->value_type_id, def->value_size); in fill_map_from_def()
2486 else if (def->parts & MAP_DEF_VALUE_SIZE) in fill_map_from_def()
2487 pr_debug("map '%s': found value_size = %u.\n", map->name, def->value_size); in fill_map_from_def()
2489 if (def->parts & MAP_DEF_MAX_ENTRIES) in fill_map_from_def()
2490 pr_debug("map '%s': found max_entries = %u.\n", map->name, def->max_entries); in fill_map_from_def()
2491 if (def->parts & MAP_DEF_MAP_FLAGS) in fill_map_from_def()
2492 pr_debug("map '%s': found map_flags = 0x%x.\n", map->name, def->map_flags); in fill_map_from_def()
2493 if (def->parts & MAP_DEF_MAP_EXTRA) in fill_map_from_def()
2494 pr_debug("map '%s': found map_extra = 0x%llx.\n", map->name, in fill_map_from_def()
2495 (unsigned long long)def->map_extra); in fill_map_from_def()
2496 if (def->parts & MAP_DEF_PINNING) in fill_map_from_def()
2497 pr_debug("map '%s': found pinning = %u.\n", map->name, def->pinning); in fill_map_from_def()
2498 if (def->parts & MAP_DEF_NUMA_NODE) in fill_map_from_def()
2499 pr_debug("map '%s': found numa_node = %u.\n", map->name, def->numa_node); in fill_map_from_def()
2501 if (def->parts & MAP_DEF_INNER_MAP) in fill_map_from_def()
2502 pr_debug("map '%s': found inner map definition.\n", map->name); in fill_map_from_def()
2530 var = btf__type_by_id(obj->btf, vi->type); in bpf_object__init_user_btf_map()
2532 map_name = btf__name_by_offset(obj->btf, var->name_off); in bpf_object__init_user_btf_map()
2536 return -EINVAL; in bpf_object__init_user_btf_map()
2538 if ((__u64)vi->offset + vi->size > data->d_size) { in bpf_object__init_user_btf_map()
2540 return -EINVAL; in bpf_object__init_user_btf_map()
2545 return -EINVAL; in bpf_object__init_user_btf_map()
2547 if (var_extra->linkage != BTF_VAR_GLOBAL_ALLOCATED) { in bpf_object__init_user_btf_map()
2549 map_name, btf_var_linkage_str(var_extra->linkage)); in bpf_object__init_user_btf_map()
2550 return -EOPNOTSUPP; in bpf_object__init_user_btf_map()
2553 def = skip_mods_and_typedefs(obj->btf, var->type, NULL); in bpf_object__init_user_btf_map()
2557 return -EINVAL; in bpf_object__init_user_btf_map()
2559 if (def->size > vi->size) { in bpf_object__init_user_btf_map()
2561 return -EINVAL; in bpf_object__init_user_btf_map()
2567 map->name = strdup(map_name); in bpf_object__init_user_btf_map()
2568 if (!map->name) { in bpf_object__init_user_btf_map()
2570 return -ENOMEM; in bpf_object__init_user_btf_map()
2572 map->libbpf_type = LIBBPF_MAP_UNSPEC; in bpf_object__init_user_btf_map()
2573 map->def.type = BPF_MAP_TYPE_UNSPEC; in bpf_object__init_user_btf_map()
2574 map->sec_idx = sec_idx; in bpf_object__init_user_btf_map()
2575 map->sec_offset = vi->offset; in bpf_object__init_user_btf_map()
2576 map->btf_var_idx = var_idx; in bpf_object__init_user_btf_map()
2578 map_name, map->sec_idx, map->sec_offset); in bpf_object__init_user_btf_map()
2580 err = parse_btf_map_def(map->name, obj->btf, def, strict, &map_def, &inner_def); in bpf_object__init_user_btf_map()
2589 pr_warn("map '%s': couldn't build pin path.\n", map->name); in bpf_object__init_user_btf_map()
2595 map->inner_map = calloc(1, sizeof(*map->inner_map)); in bpf_object__init_user_btf_map()
2596 if (!map->inner_map) in bpf_object__init_user_btf_map()
2597 return -ENOMEM; in bpf_object__init_user_btf_map()
2598 map->inner_map->fd = -1; in bpf_object__init_user_btf_map()
2599 map->inner_map->sec_idx = sec_idx; in bpf_object__init_user_btf_map()
2600 map->inner_map->name = malloc(strlen(map_name) + sizeof(".inner") + 1); in bpf_object__init_user_btf_map()
2601 if (!map->inner_map->name) in bpf_object__init_user_btf_map()
2602 return -ENOMEM; in bpf_object__init_user_btf_map()
2603 sprintf(map->inner_map->name, "%s.inner", map_name); in bpf_object__init_user_btf_map()
2605 fill_map_from_def(map->inner_map, &inner_def); in bpf_object__init_user_btf_map()
2625 if (obj->efile.btf_maps_shndx < 0) in bpf_object__init_user_btf_maps()
2628 scn = elf_sec_by_idx(obj, obj->efile.btf_maps_shndx); in bpf_object__init_user_btf_maps()
2632 MAPS_ELF_SEC, obj->path); in bpf_object__init_user_btf_maps()
2633 return -EINVAL; in bpf_object__init_user_btf_maps()
2636 nr_types = btf__type_cnt(obj->btf); in bpf_object__init_user_btf_maps()
2638 t = btf__type_by_id(obj->btf, i); in bpf_object__init_user_btf_maps()
2641 name = btf__name_by_offset(obj->btf, t->name_off); in bpf_object__init_user_btf_maps()
2644 obj->efile.btf_maps_sec_btf_id = i; in bpf_object__init_user_btf_maps()
2651 return -ENOENT; in bpf_object__init_user_btf_maps()
2657 obj->efile.btf_maps_shndx, in bpf_object__init_user_btf_maps()
2693 return sh->sh_flags & SHF_EXECINSTR; in section_have_execinstr()
2728 t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0); in bpf_object__sanitize_btf()
2734 t->size = 1; in bpf_object__sanitize_btf()
2743 name = (char *)btf__name_by_offset(btf, t->name_off); in bpf_object__sanitize_btf()
2751 t->info = BTF_INFO_ENC(BTF_KIND_STRUCT, 0, vlen); in bpf_object__sanitize_btf()
2754 m->offset = v->offset * 8; in bpf_object__sanitize_btf()
2755 m->type = v->type; in bpf_object__sanitize_btf()
2757 vt = (void *)btf__type_by_id(btf, v->type); in bpf_object__sanitize_btf()
2758 m->name_off = vt->name_off; in bpf_object__sanitize_btf()
2763 t->info = BTF_INFO_ENC(BTF_KIND_ENUM, 0, vlen); in bpf_object__sanitize_btf()
2764 t->size = sizeof(__u32); /* kernel enforced */ in bpf_object__sanitize_btf()
2767 t->info = BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0); in bpf_object__sanitize_btf()
2770 t->info = BTF_INFO_ENC(BTF_KIND_FUNC, 0, 0); in bpf_object__sanitize_btf()
2772 /* replace FLOAT with an equally-sized empty STRUCT; in bpf_object__sanitize_btf()
2776 t->name_off = 0; in bpf_object__sanitize_btf()
2777 t->info = BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 0); in bpf_object__sanitize_btf()
2780 t->name_off = 0; in bpf_object__sanitize_btf()
2781 t->info = BTF_INFO_ENC(BTF_KIND_CONST, 0, 0); in bpf_object__sanitize_btf()
2784 t->info = btf_type_info(btf_kind(t), btf_vlen(t), false); in bpf_object__sanitize_btf()
2799 t->info = BTF_INFO_ENC(BTF_KIND_UNION, 0, vlen); in bpf_object__sanitize_btf()
2801 m->type = enum64_placeholder_id; in bpf_object__sanitize_btf()
2802 m->offset = 0; in bpf_object__sanitize_btf()
2812 return obj->efile.btf_maps_shndx >= 0 || in libbpf_needs_btf()
2813 obj->efile.st_ops_shndx >= 0 || in libbpf_needs_btf()
2814 obj->efile.st_ops_link_shndx >= 0 || in libbpf_needs_btf()
2815 obj->nr_extern > 0; in libbpf_needs_btf()
2820 return obj->efile.st_ops_shndx >= 0 || obj->efile.st_ops_link_shndx >= 0; in kernel_needs_btf()
2827 int err = -ENOENT; in bpf_object__init_btf()
2830 obj->btf = btf__new(btf_data->d_buf, btf_data->d_size); in bpf_object__init_btf()
2831 err = libbpf_get_error(obj->btf); in bpf_object__init_btf()
2833 obj->btf = NULL; in bpf_object__init_btf()
2837 /* enforce 8-byte pointers for BPF-targeted BTFs */ in bpf_object__init_btf()
2838 btf__set_pointer_size(obj->btf, 8); in bpf_object__init_btf()
2844 if (!obj->btf) { in bpf_object__init_btf()
2849 obj->btf_ext = btf_ext__new(btf_ext_data->d_buf, btf_ext_data->d_size); in bpf_object__init_btf()
2850 err = libbpf_get_error(obj->btf_ext); in bpf_object__init_btf()
2854 obj->btf_ext = NULL; in bpf_object__init_btf()
2858 /* setup .BTF.ext to ELF section mapping */ in bpf_object__init_btf()
2859 ext_segs[0] = &obj->btf_ext->func_info; in bpf_object__init_btf()
2860 ext_segs[1] = &obj->btf_ext->line_info; in bpf_object__init_btf()
2861 ext_segs[2] = &obj->btf_ext->core_relo_info; in bpf_object__init_btf()
2868 if (seg->sec_cnt == 0) in bpf_object__init_btf()
2871 seg->sec_idxs = calloc(seg->sec_cnt, sizeof(*seg->sec_idxs)); in bpf_object__init_btf()
2872 if (!seg->sec_idxs) { in bpf_object__init_btf()
2873 err = -ENOMEM; in bpf_object__init_btf()
2884 sec_name = btf__name_by_offset(obj->btf, sec->sec_name_off); in bpf_object__init_btf()
2891 seg->sec_idxs[sec_num - 1] = elf_ndxscn(scn); in bpf_object__init_btf()
2908 return a->offset - b->offset; in compare_vsi_off()
2915 const char *sec_name = btf__name_by_offset(btf, t->name_off); in btf_fixup_datasec()
2922 return -ENOENT; in btf_fixup_datasec()
2925 /* Extern-backing datasecs (.ksyms, .kconfig) have their size and in btf_fixup_datasec()
2937 * to be optional. But the STV_HIDDEN handling is non-optional for any in btf_fixup_datasec()
2938 * non-extern DATASEC, so the variable fixup loop below handles both in btf_fixup_datasec()
2939 * functions at the same time, paying the cost of BTF VAR <-> ELF in btf_fixup_datasec()
2942 if (t->size == 0) { in btf_fixup_datasec()
2947 return -ENOENT; in btf_fixup_datasec()
2950 t->size = size; in btf_fixup_datasec()
2960 t_var = btf__type_by_id(btf, vsi->type); in btf_fixup_datasec()
2962 pr_debug("sec '%s': unexpected non-VAR type found\n", sec_name); in btf_fixup_datasec()
2963 return -EINVAL; in btf_fixup_datasec()
2967 if (var->linkage == BTF_VAR_STATIC || var->linkage == BTF_VAR_GLOBAL_EXTERN) in btf_fixup_datasec()
2970 var_name = btf__name_by_offset(btf, t_var->name_off); in btf_fixup_datasec()
2974 return -ENOENT; in btf_fixup_datasec()
2981 return -ENOENT; in btf_fixup_datasec()
2985 vsi->offset = sym->st_value; in btf_fixup_datasec()
2994 if (ELF64_ST_VISIBILITY(sym->st_other) == STV_HIDDEN in btf_fixup_datasec()
2995 || ELF64_ST_VISIBILITY(sym->st_other) == STV_INTERNAL) in btf_fixup_datasec()
2996 var->linkage = BTF_VAR_STATIC; in btf_fixup_datasec()
3008 if (!obj->btf) in bpf_object_fixup_btf()
3011 n = btf__type_cnt(obj->btf); in bpf_object_fixup_btf()
3013 struct btf_type *t = btf_type_by_id(obj->btf, i); in bpf_object_fixup_btf()
3021 err = btf_fixup_datasec(obj, obj->btf, t); in bpf_object_fixup_btf()
3032 if (prog->type == BPF_PROG_TYPE_STRUCT_OPS || in prog_needs_vmlinux_btf()
3033 prog->type == BPF_PROG_TYPE_LSM) in prog_needs_vmlinux_btf()
3039 if (prog->type == BPF_PROG_TYPE_TRACING && !prog->attach_prog_fd) in prog_needs_vmlinux_btf()
3050 /* CO-RE relocations need kernel BTF, only when btf_custom_path in obj_needs_vmlinux_btf()
3053 if (obj->btf_ext && obj->btf_ext->core_relo_info.len && !obj->btf_custom_path) in obj_needs_vmlinux_btf()
3057 for (i = 0; i < obj->nr_extern; i++) { in obj_needs_vmlinux_btf()
3058 const struct extern_desc *ext; in obj_needs_vmlinux_btf() local
3060 ext = &obj->externs[i]; in obj_needs_vmlinux_btf()
3061 if (ext->type == EXT_KSYM && ext->ksym.type_id) in obj_needs_vmlinux_btf()
3066 if (!prog->autoload) in obj_needs_vmlinux_btf()
3080 if (obj->btf_vmlinux || obj->gen_loader) in bpf_object__load_vmlinux_btf()
3086 obj->btf_vmlinux = btf__load_vmlinux_btf(); in bpf_object__load_vmlinux_btf()
3087 err = libbpf_get_error(obj->btf_vmlinux); in bpf_object__load_vmlinux_btf()
3090 obj->btf_vmlinux = NULL; in bpf_object__load_vmlinux_btf()
3098 struct btf *kern_btf = obj->btf; in bpf_object__sanitize_and_load_btf()
3102 if (!obj->btf) in bpf_object__sanitize_and_load_btf()
3107 err = -EOPNOTSUPP; in bpf_object__sanitize_and_load_btf()
3122 for (i = 0; i < obj->nr_programs; i++) { in bpf_object__sanitize_and_load_btf()
3123 struct bpf_program *prog = &obj->programs[i]; in bpf_object__sanitize_and_load_btf()
3128 if (!prog->mark_btf_static || !prog_is_subprog(obj, prog)) in bpf_object__sanitize_and_load_btf()
3131 n = btf__type_cnt(obj->btf); in bpf_object__sanitize_and_load_btf()
3133 t = btf_type_by_id(obj->btf, j); in bpf_object__sanitize_and_load_btf()
3137 name = btf__str_by_offset(obj->btf, t->name_off); in bpf_object__sanitize_and_load_btf()
3138 if (strcmp(name, prog->name) != 0) in bpf_object__sanitize_and_load_btf()
3141 t->info = btf_type_info(BTF_KIND_FUNC, BTF_FUNC_STATIC, 0); in bpf_object__sanitize_and_load_btf()
3152 raw_data = btf__raw_data(obj->btf, &sz); in bpf_object__sanitize_and_load_btf()
3158 /* enforce 8-byte pointers for BPF-targeted BTFs */ in bpf_object__sanitize_and_load_btf()
3159 btf__set_pointer_size(obj->btf, 8); in bpf_object__sanitize_and_load_btf()
3165 if (obj->gen_loader) { in bpf_object__sanitize_and_load_btf()
3170 return -ENOMEM; in bpf_object__sanitize_and_load_btf()
3171 bpf_gen__load_btf(obj->gen_loader, raw_data, raw_size); in bpf_object__sanitize_and_load_btf()
3173 * This fd == 0 will not be used with any syscall and will be reset to -1 eventually. in bpf_object__sanitize_and_load_btf()
3178 err = btf_load_into_kernel(kern_btf, obj->log_buf, obj->log_size, in bpf_object__sanitize_and_load_btf()
3179 obj->log_level ? 1 : 0); in bpf_object__sanitize_and_load_btf()
3184 btf__set_fd(obj->btf, btf__fd(kern_btf)); in bpf_object__sanitize_and_load_btf()
3185 btf__set_fd(kern_btf, -1); in bpf_object__sanitize_and_load_btf()
3205 name = elf_strptr(obj->efile.elf, obj->efile.strtabidx, off); in elf_sym_str()
3208 off, obj->path, elf_errmsg(-1)); in elf_sym_str()
3219 name = elf_strptr(obj->efile.elf, obj->efile.shstrndx, off); in elf_sec_str()
3222 off, obj->path, elf_errmsg(-1)); in elf_sec_str()
3233 scn = elf_getscn(obj->efile.elf, idx); in elf_sec_by_idx()
3236 idx, obj->path, elf_errmsg(-1)); in elf_sec_by_idx()
3245 Elf *elf = obj->efile.elf; in elf_sec_by_name()
3271 elf_ndxscn(scn), obj->path, elf_errmsg(-1)); in elf_sec_hdr()
3290 name = elf_sec_str(obj, sh->sh_name); in elf_sec_name()
3293 elf_ndxscn(scn), obj->path, elf_errmsg(-1)); in elf_sec_name()
3311 obj->path, elf_errmsg(-1)); in elf_sec_data()
3320 if (idx >= obj->efile.symbols->d_size / sizeof(Elf64_Sym)) in elf_sym_by_idx()
3323 return (Elf64_Sym *)obj->efile.symbols->d_buf + idx; in elf_sym_by_idx()
3328 if (idx >= data->d_size / sizeof(Elf64_Rel)) in elf_rel_by_idx()
3331 return (Elf64_Rel *)data->d_buf + idx; in elf_rel_by_idx()
3343 if (hdr->sh_type == SHT_STRTAB) in ignore_elf_section()
3347 if (hdr->sh_type == SHT_LLVM_ADDRSIG) in ignore_elf_section()
3351 if (hdr->sh_type == SHT_PROGBITS && hdr->sh_size == 0 && in ignore_elf_section()
3360 name += sizeof(".rel") - 1; in ignore_elf_section()
3365 /* .BTF and .BTF.ext don't need relocations */ in ignore_elf_section()
3379 if (a->sec_idx != b->sec_idx) in cmp_progs()
3380 return a->sec_idx < b->sec_idx ? -1 : 1; in cmp_progs()
3383 return a->sec_insn_off < b->sec_insn_off ? -1 : 1; in cmp_progs()
3389 Elf *elf = obj->efile.elf; in bpf_object__elf_collect()
3398 /* ELF section indices are 0-based, but sec #0 is special "invalid" in bpf_object__elf_collect()
3403 if (elf_getshdrnum(obj->efile.elf, &obj->efile.sec_cnt)) { in bpf_object__elf_collect()
3405 obj->path, elf_errmsg(-1)); in bpf_object__elf_collect()
3406 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3408 obj->efile.secs = calloc(obj->efile.sec_cnt, sizeof(*obj->efile.secs)); in bpf_object__elf_collect()
3409 if (!obj->efile.secs) in bpf_object__elf_collect()
3410 return -ENOMEM; in bpf_object__elf_collect()
3419 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3421 if (sh->sh_type == SHT_SYMTAB) { in bpf_object__elf_collect()
3422 if (obj->efile.symbols) { in bpf_object__elf_collect()
3423 pr_warn("elf: multiple symbol tables in %s\n", obj->path); in bpf_object__elf_collect()
3424 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3429 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3433 obj->efile.symbols = data; in bpf_object__elf_collect()
3434 obj->efile.symbols_shndx = idx; in bpf_object__elf_collect()
3435 obj->efile.strtabidx = sh->sh_link; in bpf_object__elf_collect()
3439 if (!obj->efile.symbols) { in bpf_object__elf_collect()
3441 obj->path); in bpf_object__elf_collect()
3442 return -ENOENT; in bpf_object__elf_collect()
3448 sec_desc = &obj->efile.secs[idx]; in bpf_object__elf_collect()
3452 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3454 name = elf_sec_str(obj, sh->sh_name); in bpf_object__elf_collect()
3456 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3463 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3466 idx, name, (unsigned long)data->d_size, in bpf_object__elf_collect()
3467 (int)sh->sh_link, (unsigned long)sh->sh_flags, in bpf_object__elf_collect()
3468 (int)sh->sh_type); in bpf_object__elf_collect()
3471 err = bpf_object__init_license(obj, data->d_buf, data->d_size); in bpf_object__elf_collect()
3475 err = bpf_object__init_kversion(obj, data->d_buf, data->d_size); in bpf_object__elf_collect()
3480 return -ENOTSUP; in bpf_object__elf_collect()
3482 obj->efile.btf_maps_shndx = idx; in bpf_object__elf_collect()
3484 if (sh->sh_type != SHT_PROGBITS) in bpf_object__elf_collect()
3485 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3488 if (sh->sh_type != SHT_PROGBITS) in bpf_object__elf_collect()
3489 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3491 } else if (sh->sh_type == SHT_SYMTAB) { in bpf_object__elf_collect()
3493 } else if (sh->sh_type == SHT_PROGBITS && data->d_size > 0) { in bpf_object__elf_collect()
3494 if (sh->sh_flags & SHF_EXECINSTR) { in bpf_object__elf_collect()
3496 obj->efile.text_shndx = idx; in bpf_object__elf_collect()
3502 sec_desc->sec_type = SEC_DATA; in bpf_object__elf_collect()
3503 sec_desc->shdr = sh; in bpf_object__elf_collect()
3504 sec_desc->data = data; in bpf_object__elf_collect()
3507 sec_desc->sec_type = SEC_RODATA; in bpf_object__elf_collect()
3508 sec_desc->shdr = sh; in bpf_object__elf_collect()
3509 sec_desc->data = data; in bpf_object__elf_collect()
3511 obj->efile.st_ops_data = data; in bpf_object__elf_collect()
3512 obj->efile.st_ops_shndx = idx; in bpf_object__elf_collect()
3514 obj->efile.st_ops_link_data = data; in bpf_object__elf_collect()
3515 obj->efile.st_ops_link_shndx = idx; in bpf_object__elf_collect()
3520 } else if (sh->sh_type == SHT_REL) { in bpf_object__elf_collect()
3521 int targ_sec_idx = sh->sh_info; /* points to other section */ in bpf_object__elf_collect()
3523 if (sh->sh_entsize != sizeof(Elf64_Rel) || in bpf_object__elf_collect()
3524 targ_sec_idx >= obj->efile.sec_cnt) in bpf_object__elf_collect()
3525 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3538 sec_desc->sec_type = SEC_RELO; in bpf_object__elf_collect()
3539 sec_desc->shdr = sh; in bpf_object__elf_collect()
3540 sec_desc->data = data; in bpf_object__elf_collect()
3541 } else if (sh->sh_type == SHT_NOBITS && (strcmp(name, BSS_SEC) == 0 || in bpf_object__elf_collect()
3543 sec_desc->sec_type = SEC_BSS; in bpf_object__elf_collect()
3544 sec_desc->shdr = sh; in bpf_object__elf_collect()
3545 sec_desc->data = data; in bpf_object__elf_collect()
3548 (size_t)sh->sh_size); in bpf_object__elf_collect()
3552 if (!obj->efile.strtabidx || obj->efile.strtabidx > idx) { in bpf_object__elf_collect()
3553 pr_warn("elf: symbol strings section missing or invalid in %s\n", obj->path); in bpf_object__elf_collect()
3554 return -LIBBPF_ERRNO__FORMAT; in bpf_object__elf_collect()
3557 /* sort BPF programs by section name and in-section instruction offset in bpf_object__elf_collect()
3560 if (obj->nr_programs) in bpf_object__elf_collect()
3561 qsort(obj->programs, obj->nr_programs, sizeof(*obj->programs), cmp_progs); in bpf_object__elf_collect()
3568 int bind = ELF64_ST_BIND(sym->st_info); in sym_is_extern()
3570 return sym->st_shndx == SHN_UNDEF && in sym_is_extern()
3572 ELF64_ST_TYPE(sym->st_info) == STT_NOTYPE; in sym_is_extern()
3577 int bind = ELF64_ST_BIND(sym->st_info); in sym_is_subprog()
3578 int type = ELF64_ST_TYPE(sym->st_info); in sym_is_subprog()
3581 if (sym->st_shndx != text_shndx) in sym_is_subprog()
3599 return -ESRCH; in find_extern_btf_id()
3608 tname = btf__name_by_offset(btf, t->name_off); in find_extern_btf_id()
3613 btf_var(t)->linkage != BTF_VAR_GLOBAL_EXTERN) in find_extern_btf_id()
3614 return -EINVAL; in find_extern_btf_id()
3617 return -EINVAL; in find_extern_btf_id()
3622 return -ENOENT; in find_extern_btf_id()
3631 return -ESRCH; in find_extern_sec_btf_id()
3642 if (vs->type == ext_btf_id) in find_extern_sec_btf_id()
3647 return -ENOENT; in find_extern_sec_btf_id()
3657 name = btf__name_by_offset(btf, t->name_off); in find_kcfg_type()
3666 return t->size == 1 ? KCFG_BOOL : KCFG_UNKNOWN; in find_kcfg_type()
3669 if (t->size == 1) in find_kcfg_type()
3671 if (t->size < 1 || t->size > 8 || (t->size & (t->size - 1))) in find_kcfg_type()
3676 if (t->size != 4) in find_kcfg_type()
3686 if (btf_array(t)->nelems == 0) in find_kcfg_type()
3688 if (find_kcfg_type(btf, btf_array(t)->type, NULL) != KCFG_CHAR) in find_kcfg_type()
3701 if (a->type != b->type) in cmp_externs()
3702 return a->type < b->type ? -1 : 1; in cmp_externs()
3704 if (a->type == EXT_KCFG) { in cmp_externs()
3706 if (a->kcfg.align != b->kcfg.align) in cmp_externs()
3707 return a->kcfg.align > b->kcfg.align ? -1 : 1; in cmp_externs()
3709 if (a->kcfg.sz != b->kcfg.sz) in cmp_externs()
3710 return a->kcfg.sz < b->kcfg.sz ? -1 : 1; in cmp_externs()
3714 return strcmp(a->name, b->name); in cmp_externs()
3752 vt = btf__type_by_id(btf, vs->type); in add_dummy_ksym_var()
3776 struct extern_desc *ext; in bpf_object__collect_externs() local
3783 if (!obj->efile.symbols) in bpf_object__collect_externs()
3786 scn = elf_sec_by_idx(obj, obj->efile.symbols_shndx); in bpf_object__collect_externs()
3788 if (!sh || sh->sh_entsize != sizeof(Elf64_Sym)) in bpf_object__collect_externs()
3789 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_externs()
3791 dummy_var_btf_id = add_dummy_ksym_var(obj->btf); in bpf_object__collect_externs()
3795 n = sh->sh_size / sh->sh_entsize; in bpf_object__collect_externs()
3802 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_externs()
3805 ext_name = elf_sym_str(obj, sym->st_name); in bpf_object__collect_externs()
3809 ext = obj->externs; in bpf_object__collect_externs()
3810 ext = libbpf_reallocarray(ext, obj->nr_extern + 1, sizeof(*ext)); in bpf_object__collect_externs()
3811 if (!ext) in bpf_object__collect_externs()
3812 return -ENOMEM; in bpf_object__collect_externs()
3813 obj->externs = ext; in bpf_object__collect_externs()
3814 ext = &ext[obj->nr_extern]; in bpf_object__collect_externs()
3815 memset(ext, 0, sizeof(*ext)); in bpf_object__collect_externs()
3816 obj->nr_extern++; in bpf_object__collect_externs()
3818 ext->btf_id = find_extern_btf_id(obj->btf, ext_name); in bpf_object__collect_externs()
3819 if (ext->btf_id <= 0) { in bpf_object__collect_externs()
3821 ext_name, ext->btf_id); in bpf_object__collect_externs()
3822 return ext->btf_id; in bpf_object__collect_externs()
3824 t = btf__type_by_id(obj->btf, ext->btf_id); in bpf_object__collect_externs()
3825 ext->name = btf__name_by_offset(obj->btf, t->name_off); in bpf_object__collect_externs()
3826 ext->sym_idx = i; in bpf_object__collect_externs()
3827 ext->is_weak = ELF64_ST_BIND(sym->st_info) == STB_WEAK; in bpf_object__collect_externs()
3829 ext_essent_len = bpf_core_essential_name_len(ext->name); in bpf_object__collect_externs()
3830 ext->essent_name = NULL; in bpf_object__collect_externs()
3831 if (ext_essent_len != strlen(ext->name)) { in bpf_object__collect_externs()
3832 ext->essent_name = strndup(ext->name, ext_essent_len); in bpf_object__collect_externs()
3833 if (!ext->essent_name) in bpf_object__collect_externs()
3834 return -ENOMEM; in bpf_object__collect_externs()
3837 ext->sec_btf_id = find_extern_sec_btf_id(obj->btf, ext->btf_id); in bpf_object__collect_externs()
3838 if (ext->sec_btf_id <= 0) { in bpf_object__collect_externs()
3840 ext_name, ext->btf_id, ext->sec_btf_id); in bpf_object__collect_externs()
3841 return ext->sec_btf_id; in bpf_object__collect_externs()
3843 sec = (void *)btf__type_by_id(obj->btf, ext->sec_btf_id); in bpf_object__collect_externs()
3844 sec_name = btf__name_by_offset(obj->btf, sec->name_off); in bpf_object__collect_externs()
3849 ext->name, KCONFIG_SEC); in bpf_object__collect_externs()
3850 return -ENOTSUP; in bpf_object__collect_externs()
3853 ext->type = EXT_KCFG; in bpf_object__collect_externs()
3854 ext->kcfg.sz = btf__resolve_size(obj->btf, t->type); in bpf_object__collect_externs()
3855 if (ext->kcfg.sz <= 0) { in bpf_object__collect_externs()
3857 ext_name, ext->kcfg.sz); in bpf_object__collect_externs()
3858 return ext->kcfg.sz; in bpf_object__collect_externs()
3860 ext->kcfg.align = btf__align_of(obj->btf, t->type); in bpf_object__collect_externs()
3861 if (ext->kcfg.align <= 0) { in bpf_object__collect_externs()
3863 ext_name, ext->kcfg.align); in bpf_object__collect_externs()
3864 return -EINVAL; in bpf_object__collect_externs()
3866 ext->kcfg.type = find_kcfg_type(obj->btf, t->type, in bpf_object__collect_externs()
3867 &ext->kcfg.is_signed); in bpf_object__collect_externs()
3868 if (ext->kcfg.type == KCFG_UNKNOWN) { in bpf_object__collect_externs()
3870 return -ENOTSUP; in bpf_object__collect_externs()
3874 ext->type = EXT_KSYM; in bpf_object__collect_externs()
3875 skip_mods_and_typedefs(obj->btf, t->type, in bpf_object__collect_externs()
3876 &ext->ksym.type_id); in bpf_object__collect_externs()
3879 return -ENOTSUP; in bpf_object__collect_externs()
3882 pr_debug("collected %d externs total\n", obj->nr_extern); in bpf_object__collect_externs()
3884 if (!obj->nr_extern) in bpf_object__collect_externs()
3888 qsort(obj->externs, obj->nr_extern, sizeof(*ext), cmp_externs); in bpf_object__collect_externs()
3892 * pretending that each extern is a 8-byte variable in bpf_object__collect_externs()
3895 /* find existing 4-byte integer type in BTF to use for fake in bpf_object__collect_externs()
3898 int int_btf_id = find_int_btf_id(obj->btf); in bpf_object__collect_externs()
3900 * will be used to replace the vs->type and in bpf_object__collect_externs()
3906 dummy_var = btf__type_by_id(obj->btf, dummy_var_btf_id); in bpf_object__collect_externs()
3907 for (i = 0; i < obj->nr_extern; i++) { in bpf_object__collect_externs()
3908 ext = &obj->externs[i]; in bpf_object__collect_externs()
3909 if (ext->type != EXT_KSYM) in bpf_object__collect_externs()
3912 i, ext->sym_idx, ext->name); in bpf_object__collect_externs()
3921 vt = (void *)btf__type_by_id(obj->btf, vs->type); in bpf_object__collect_externs()
3922 ext_name = btf__name_by_offset(obj->btf, vt->name_off); in bpf_object__collect_externs()
3923 ext = find_extern_by_name(obj, ext_name); in bpf_object__collect_externs()
3924 if (!ext) { in bpf_object__collect_externs()
3927 return -ESRCH; in bpf_object__collect_externs()
3934 func_proto = btf__type_by_id(obj->btf, in bpf_object__collect_externs()
3935 vt->type); in bpf_object__collect_externs()
3943 dummy_var->name_off; in bpf_object__collect_externs()
3944 vs->type = dummy_var_btf_id; in bpf_object__collect_externs()
3945 vt->info &= ~0xffff; in bpf_object__collect_externs()
3946 vt->info |= BTF_FUNC_GLOBAL; in bpf_object__collect_externs()
3948 btf_var(vt)->linkage = BTF_VAR_GLOBAL_ALLOCATED; in bpf_object__collect_externs()
3949 vt->type = int_btf_id; in bpf_object__collect_externs()
3951 vs->offset = off; in bpf_object__collect_externs()
3952 vs->size = sizeof(int); in bpf_object__collect_externs()
3954 sec->size = off; in bpf_object__collect_externs()
3961 for (i = 0; i < obj->nr_extern; i++) { in bpf_object__collect_externs()
3962 ext = &obj->externs[i]; in bpf_object__collect_externs()
3963 if (ext->type != EXT_KCFG) in bpf_object__collect_externs()
3966 ext->kcfg.data_off = roundup(off, ext->kcfg.align); in bpf_object__collect_externs()
3967 off = ext->kcfg.data_off + ext->kcfg.sz; in bpf_object__collect_externs()
3969 i, ext->sym_idx, ext->kcfg.data_off, ext->name); in bpf_object__collect_externs()
3971 sec->size = off; in bpf_object__collect_externs()
3976 t = btf__type_by_id(obj->btf, vs->type); in bpf_object__collect_externs()
3977 ext_name = btf__name_by_offset(obj->btf, t->name_off); in bpf_object__collect_externs()
3978 ext = find_extern_by_name(obj, ext_name); in bpf_object__collect_externs()
3979 if (!ext) { in bpf_object__collect_externs()
3982 return -ESRCH; in bpf_object__collect_externs()
3984 btf_var(t)->linkage = BTF_VAR_GLOBAL_ALLOCATED; in bpf_object__collect_externs()
3985 vs->offset = ext->kcfg.data_off; in bpf_object__collect_externs()
3993 return prog->sec_idx == obj->efile.text_shndx; in prog_is_subprog()
4005 if (!strcmp(prog->name, name)) in bpf_object__find_program_by_name()
4014 switch (obj->efile.secs[shndx].sec_type) { in bpf_object__shndx_is_data()
4027 return shndx == obj->efile.btf_maps_shndx; in bpf_object__shndx_is_maps()
4033 if (shndx == obj->efile.symbols_shndx) in bpf_object__section_to_libbpf_map_type()
4036 switch (obj->efile.secs[shndx].sec_type) { in bpf_object__section_to_libbpf_map_type()
4053 struct bpf_insn *insn = &prog->insns[insn_idx]; in bpf_program__record_reloc()
4054 size_t map_idx, nr_maps = prog->obj->nr_maps; in bpf_program__record_reloc()
4055 struct bpf_object *obj = prog->obj; in bpf_program__record_reloc()
4056 __u32 shdr_idx = sym->st_shndx; in bpf_program__record_reloc()
4063 prog->name, sym_name, insn_idx, insn->code); in bpf_program__record_reloc()
4064 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4068 int sym_idx = ELF64_R_SYM(rel->r_info); in bpf_program__record_reloc()
4069 int i, n = obj->nr_extern; in bpf_program__record_reloc()
4070 struct extern_desc *ext; in bpf_program__record_reloc() local
4073 ext = &obj->externs[i]; in bpf_program__record_reloc()
4074 if (ext->sym_idx == sym_idx) in bpf_program__record_reloc()
4079 prog->name, sym_name, sym_idx); in bpf_program__record_reloc()
4080 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4083 prog->name, i, ext->name, ext->sym_idx, insn_idx); in bpf_program__record_reloc()
4084 if (insn->code == (BPF_JMP | BPF_CALL)) in bpf_program__record_reloc()
4085 reloc_desc->type = RELO_EXTERN_CALL; in bpf_program__record_reloc()
4087 reloc_desc->type = RELO_EXTERN_LD64; in bpf_program__record_reloc()
4088 reloc_desc->insn_idx = insn_idx; in bpf_program__record_reloc()
4089 reloc_desc->ext_idx = i; in bpf_program__record_reloc()
4093 /* sub-program call relocation */ in bpf_program__record_reloc()
4095 if (insn->src_reg != BPF_PSEUDO_CALL) { in bpf_program__record_reloc()
4096 pr_warn("prog '%s': incorrect bpf_call opcode\n", prog->name); in bpf_program__record_reloc()
4097 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4100 if (!shdr_idx || shdr_idx != obj->efile.text_shndx) { in bpf_program__record_reloc()
4103 prog->name, sym_name, sym_sec_name); in bpf_program__record_reloc()
4104 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4106 if (sym->st_value % BPF_INSN_SZ) { in bpf_program__record_reloc()
4108 prog->name, sym_name, (size_t)sym->st_value); in bpf_program__record_reloc()
4109 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4111 reloc_desc->type = RELO_CALL; in bpf_program__record_reloc()
4112 reloc_desc->insn_idx = insn_idx; in bpf_program__record_reloc()
4113 reloc_desc->sym_off = sym->st_value; in bpf_program__record_reloc()
4119 prog->name, sym_name, shdr_idx); in bpf_program__record_reloc()
4120 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4124 if (sym_is_subprog(sym, obj->efile.text_shndx)) { in bpf_program__record_reloc()
4125 /* global_func: sym->st_value = offset in the section, insn->imm = 0. in bpf_program__record_reloc()
4126 * local_func: sym->st_value = 0, insn->imm = offset in the section. in bpf_program__record_reloc()
4128 if ((sym->st_value % BPF_INSN_SZ) || (insn->imm % BPF_INSN_SZ)) { in bpf_program__record_reloc()
4130 prog->name, sym_name, (size_t)sym->st_value, insn->imm); in bpf_program__record_reloc()
4131 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4134 reloc_desc->type = RELO_SUBPROG_ADDR; in bpf_program__record_reloc()
4135 reloc_desc->insn_idx = insn_idx; in bpf_program__record_reloc()
4136 reloc_desc->sym_off = sym->st_value; in bpf_program__record_reloc()
4147 prog->name, sym_name, sym_sec_name); in bpf_program__record_reloc()
4148 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4151 map = &obj->maps[map_idx]; in bpf_program__record_reloc()
4152 if (map->libbpf_type != type || in bpf_program__record_reloc()
4153 map->sec_idx != sym->st_shndx || in bpf_program__record_reloc()
4154 map->sec_offset != sym->st_value) in bpf_program__record_reloc()
4157 prog->name, map_idx, map->name, map->sec_idx, in bpf_program__record_reloc()
4158 map->sec_offset, insn_idx); in bpf_program__record_reloc()
4163 prog->name, sym_sec_name, (size_t)sym->st_value); in bpf_program__record_reloc()
4164 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4166 reloc_desc->type = RELO_LD64; in bpf_program__record_reloc()
4167 reloc_desc->insn_idx = insn_idx; in bpf_program__record_reloc()
4168 reloc_desc->map_idx = map_idx; in bpf_program__record_reloc()
4169 reloc_desc->sym_off = 0; /* sym->st_value determines map_idx */ in bpf_program__record_reloc()
4176 prog->name, sym_sec_name); in bpf_program__record_reloc()
4177 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4180 map = &obj->maps[map_idx]; in bpf_program__record_reloc()
4181 if (map->libbpf_type != type || map->sec_idx != sym->st_shndx) in bpf_program__record_reloc()
4184 prog->name, map_idx, map->name, map->sec_idx, in bpf_program__record_reloc()
4185 map->sec_offset, insn_idx); in bpf_program__record_reloc()
4190 prog->name, sym_sec_name); in bpf_program__record_reloc()
4191 return -LIBBPF_ERRNO__RELOC; in bpf_program__record_reloc()
4194 reloc_desc->type = RELO_DATA; in bpf_program__record_reloc()
4195 reloc_desc->insn_idx = insn_idx; in bpf_program__record_reloc()
4196 reloc_desc->map_idx = map_idx; in bpf_program__record_reloc()
4197 reloc_desc->sym_off = sym->st_value; in bpf_program__record_reloc()
4203 return insn_idx >= prog->sec_insn_off && in prog_contains_insn()
4204 insn_idx < prog->sec_insn_off + prog->sec_insn_cnt; in prog_contains_insn()
4210 int l = 0, r = obj->nr_programs - 1, m; in find_prog_by_sec_insn()
4213 if (!obj->nr_programs) in find_prog_by_sec_insn()
4217 m = l + (r - l + 1) / 2; in find_prog_by_sec_insn()
4218 prog = &obj->programs[m]; in find_prog_by_sec_insn()
4220 if (prog->sec_idx < sec_idx || in find_prog_by_sec_insn()
4221 (prog->sec_idx == sec_idx && prog->sec_insn_off <= insn_idx)) in find_prog_by_sec_insn()
4224 r = m - 1; in find_prog_by_sec_insn()
4229 prog = &obj->programs[l]; in find_prog_by_sec_insn()
4230 if (prog->sec_idx == sec_idx && prog_contains_insn(prog, insn_idx)) in find_prog_by_sec_insn()
4239 size_t sec_idx = shdr->sh_info, sym_idx; in bpf_object__collect_prog_relos()
4250 if (sec_idx >= obj->efile.sec_cnt) in bpf_object__collect_prog_relos()
4251 return -EINVAL; in bpf_object__collect_prog_relos()
4256 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_prog_relos()
4258 relo_sec_name = elf_sec_str(obj, shdr->sh_name); in bpf_object__collect_prog_relos()
4261 return -EINVAL; in bpf_object__collect_prog_relos()
4265 nrels = shdr->sh_size / shdr->sh_entsize; in bpf_object__collect_prog_relos()
4271 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_prog_relos()
4274 sym_idx = ELF64_R_SYM(rel->r_info); in bpf_object__collect_prog_relos()
4279 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_prog_relos()
4282 if (sym->st_shndx >= obj->efile.sec_cnt) { in bpf_object__collect_prog_relos()
4284 relo_sec_name, sym_idx, (size_t)sym->st_shndx, i); in bpf_object__collect_prog_relos()
4285 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_prog_relos()
4288 if (rel->r_offset % BPF_INSN_SZ || rel->r_offset >= scn_data->d_size) { in bpf_object__collect_prog_relos()
4290 relo_sec_name, (size_t)rel->r_offset, i); in bpf_object__collect_prog_relos()
4291 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_prog_relos()
4294 insn_idx = rel->r_offset / BPF_INSN_SZ; in bpf_object__collect_prog_relos()
4301 if (ELF64_ST_TYPE(sym->st_info) == STT_SECTION && sym->st_name == 0) in bpf_object__collect_prog_relos()
4302 sym_name = elf_sec_name(obj, elf_sec_by_idx(obj, sym->st_shndx)); in bpf_object__collect_prog_relos()
4304 sym_name = elf_sym_str(obj, sym->st_name); in bpf_object__collect_prog_relos()
4317 relos = libbpf_reallocarray(prog->reloc_desc, in bpf_object__collect_prog_relos()
4318 prog->nr_reloc + 1, sizeof(*relos)); in bpf_object__collect_prog_relos()
4320 return -ENOMEM; in bpf_object__collect_prog_relos()
4321 prog->reloc_desc = relos; in bpf_object__collect_prog_relos()
4324 insn_idx -= prog->sec_insn_off; in bpf_object__collect_prog_relos()
4325 err = bpf_program__record_reloc(prog, &relos[prog->nr_reloc], in bpf_object__collect_prog_relos()
4330 prog->nr_reloc++; in bpf_object__collect_prog_relos()
4339 if (!obj->btf) in map_fill_btf_type_info()
4340 return -ENOENT; in map_fill_btf_type_info()
4342 /* if it's BTF-defined map, we don't need to search for type IDs. in map_fill_btf_type_info()
4346 if (map->sec_idx == obj->efile.btf_maps_shndx || bpf_map__is_struct_ops(map)) in map_fill_btf_type_info()
4354 return -ENOENT; in map_fill_btf_type_info()
4356 id = btf__find_by_name(obj->btf, map->real_name); in map_fill_btf_type_info()
4360 map->btf_key_type_id = 0; in map_fill_btf_type_info()
4361 map->btf_value_type_id = id; in map_fill_btf_type_info()
4377 err = -errno; in bpf_get_map_info_from_fdinfo()
4385 info->type = val; in bpf_get_map_info_from_fdinfo()
4387 info->key_size = val; in bpf_get_map_info_from_fdinfo()
4389 info->value_size = val; in bpf_get_map_info_from_fdinfo()
4391 info->max_entries = val; in bpf_get_map_info_from_fdinfo()
4393 info->map_flags = val; in bpf_get_map_info_from_fdinfo()
4403 return map->autocreate; in bpf_map__autocreate()
4408 if (map->obj->loaded) in bpf_map__set_autocreate()
4409 return libbpf_err(-EBUSY); in bpf_map__set_autocreate()
4411 map->autocreate = autocreate; in bpf_map__set_autocreate()
4430 if (name_len == BPF_OBJ_NAME_LEN - 1 && strncmp(map->name, info.name, name_len) == 0) in bpf_map__reuse_fd()
4431 new_name = strdup(map->name); in bpf_map__reuse_fd()
4436 return libbpf_err(-errno); in bpf_map__reuse_fd()
4445 err = -errno; in bpf_map__reuse_fd()
4449 err = zclose(map->fd); in bpf_map__reuse_fd()
4451 err = -errno; in bpf_map__reuse_fd()
4454 free(map->name); in bpf_map__reuse_fd()
4456 map->fd = new_fd; in bpf_map__reuse_fd()
4457 map->name = new_name; in bpf_map__reuse_fd()
4458 map->def.type = info.type; in bpf_map__reuse_fd()
4459 map->def.key_size = info.key_size; in bpf_map__reuse_fd()
4460 map->def.value_size = info.value_size; in bpf_map__reuse_fd()
4461 map->def.max_entries = info.max_entries; in bpf_map__reuse_fd()
4462 map->def.map_flags = info.map_flags; in bpf_map__reuse_fd()
4463 map->btf_key_type_id = info.btf_key_type_id; in bpf_map__reuse_fd()
4464 map->btf_value_type_id = info.btf_value_type_id; in bpf_map__reuse_fd()
4465 map->reused = true; in bpf_map__reuse_fd()
4466 map->map_extra = info.map_extra; in bpf_map__reuse_fd()
4479 return map->def.max_entries; in bpf_map__max_entries()
4484 if (!bpf_map_type__is_map_in_map(map->def.type)) in bpf_map__inner_map()
4487 return map->inner_map; in bpf_map__inner_map()
4492 if (map->obj->loaded) in bpf_map__set_max_entries()
4493 return libbpf_err(-EBUSY); in bpf_map__set_max_entries()
4495 map->def.max_entries = max_entries; in bpf_map__set_max_entries()
4497 /* auto-adjust BPF ringbuf map max_entries to be a multiple of page size */ in bpf_map__set_max_entries()
4499 map->def.max_entries = adjust_ringbuf_sz(map->def.max_entries); in bpf_map__set_max_entries()
4514 if (obj->gen_loader) in bpf_object__probe_loading()
4532 return -ret; in bpf_object__probe_loading()
4581 ret = -errno; in probe_kern_global_data()
4584 __func__, cp, -ret); in probe_kern_global_data()
4684 BTF_TYPE_DECL_TAG_ENC(1, 2, -1), in probe_kern_btf_decl_tag()
4726 * non-zero expected attach type (i.e., not a BPF_CGROUP_INET_INGRESS) in probe_kern_exp_attach_type()
4738 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -8), /* r1 += -8 */ in probe_kern_probe_read_kernel()
4761 ret = -errno; in probe_prog_bind_map()
4764 __func__, cp, -ret); in probe_prog_bind_map()
4822 return -errno; in probe_perf_link()
4827 link_fd = bpf_link_create(prog_fd, -1, BPF_PERF_EVENT, NULL); in probe_perf_link()
4828 err = -errno; /* close() can clobber errno */ in probe_perf_link()
4834 return link_fd < 0 && err == -EBADF; in probe_perf_link()
4853 return -errno; in probe_uprobe_multi_link()
4855 /* Creating uprobe in '/' binary should fail with -EBADF. */ in probe_uprobe_multi_link()
4860 link_fd = bpf_link_create(prog_fd, -1, BPF_TRACE_UPROBE_MULTI, &link_opts); in probe_uprobe_multi_link()
4861 err = -errno; /* close() can clobber errno */ in probe_uprobe_multi_link()
4867 return link_fd < 0 && err == -EBADF; in probe_uprobe_multi_link()
4955 "memcg-based memory accounting", probe_memcg_account,
4967 "BPF multi-uprobe link support", probe_uprobe_multi_link,
4976 if (obj && obj->gen_loader) in kernel_supports()
4982 if (READ_ONCE(feat->res) == FEAT_UNKNOWN) { in kernel_supports()
4983 ret = feat->probe(); in kernel_supports()
4985 WRITE_ONCE(feat->res, FEAT_SUPPORTED); in kernel_supports()
4987 WRITE_ONCE(feat->res, FEAT_MISSING); in kernel_supports()
4989 pr_warn("Detection of kernel %s support failed: %d\n", feat->desc, ret); in kernel_supports()
4990 WRITE_ONCE(feat->res, FEAT_MISSING); in kernel_supports()
4994 return READ_ONCE(feat->res) == FEAT_SUPPORTED; in kernel_supports()
5014 return (map_info.type == map->def.type && in map_is_reuse_compat()
5015 map_info.key_size == map->def.key_size && in map_is_reuse_compat()
5016 map_info.value_size == map->def.value_size && in map_is_reuse_compat()
5017 map_info.max_entries == map->def.max_entries && in map_is_reuse_compat()
5018 map_info.map_flags == map->def.map_flags && in map_is_reuse_compat()
5019 map_info.map_extra == map->map_extra); in map_is_reuse_compat()
5028 pin_fd = bpf_obj_get(map->pin_path); in bpf_object__reuse_map()
5030 err = -errno; in bpf_object__reuse_map()
5031 if (err == -ENOENT) { in bpf_object__reuse_map()
5033 map->pin_path); in bpf_object__reuse_map()
5037 cp = libbpf_strerror_r(-err, errmsg, sizeof(errmsg)); in bpf_object__reuse_map()
5039 map->pin_path, cp); in bpf_object__reuse_map()
5045 map->pin_path); in bpf_object__reuse_map()
5047 return -EINVAL; in bpf_object__reuse_map()
5055 map->pinned = true; in bpf_object__reuse_map()
5056 pr_debug("reused pinned map at '%s'\n", map->pin_path); in bpf_object__reuse_map()
5064 enum libbpf_map_type map_type = map->libbpf_type; in bpf_object__populate_internal_map()
5068 if (obj->gen_loader) { in bpf_object__populate_internal_map()
5069 bpf_gen__map_update_elem(obj->gen_loader, map - obj->maps, in bpf_object__populate_internal_map()
5070 map->mmaped, map->def.value_size); in bpf_object__populate_internal_map()
5072 bpf_gen__map_freeze(obj->gen_loader, map - obj->maps); in bpf_object__populate_internal_map()
5075 err = bpf_map_update_elem(map->fd, &zero, map->mmaped, 0); in bpf_object__populate_internal_map()
5077 err = -errno; in bpf_object__populate_internal_map()
5080 map->name, cp); in bpf_object__populate_internal_map()
5084 /* Freeze .rodata and .kconfig map as read-only from syscall side. */ in bpf_object__populate_internal_map()
5086 err = bpf_map_freeze(map->fd); in bpf_object__populate_internal_map()
5088 err = -errno; in bpf_object__populate_internal_map()
5090 pr_warn("Error freezing map(%s) as read-only: %s\n", in bpf_object__populate_internal_map()
5091 map->name, cp); in bpf_object__populate_internal_map()
5103 struct bpf_map_def *def = &map->def; in bpf_object__create_map()
5108 map_name = map->name; in bpf_object__create_map()
5109 create_attr.map_ifindex = map->map_ifindex; in bpf_object__create_map()
5110 create_attr.map_flags = def->map_flags; in bpf_object__create_map()
5111 create_attr.numa_node = map->numa_node; in bpf_object__create_map()
5112 create_attr.map_extra = map->map_extra; in bpf_object__create_map()
5115 create_attr.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id; in bpf_object__create_map()
5117 if (obj->btf && btf__fd(obj->btf) >= 0) { in bpf_object__create_map()
5118 create_attr.btf_fd = btf__fd(obj->btf); in bpf_object__create_map()
5119 create_attr.btf_key_type_id = map->btf_key_type_id; in bpf_object__create_map()
5120 create_attr.btf_value_type_id = map->btf_value_type_id; in bpf_object__create_map()
5123 if (bpf_map_type__is_map_in_map(def->type)) { in bpf_object__create_map()
5124 if (map->inner_map) { in bpf_object__create_map()
5125 err = map_set_def_max_entries(map->inner_map); in bpf_object__create_map()
5128 err = bpf_object__create_map(obj, map->inner_map, true); in bpf_object__create_map()
5131 map->name, err); in bpf_object__create_map()
5134 map->inner_map_fd = bpf_map__fd(map->inner_map); in bpf_object__create_map()
5136 if (map->inner_map_fd >= 0) in bpf_object__create_map()
5137 create_attr.inner_map_fd = map->inner_map_fd; in bpf_object__create_map()
5140 switch (def->type) { in bpf_object__create_map()
5157 map->btf_key_type_id = 0; in bpf_object__create_map()
5158 map->btf_value_type_id = 0; in bpf_object__create_map()
5163 if (obj->gen_loader) { in bpf_object__create_map()
5164 bpf_gen__map_create(obj->gen_loader, def->type, map_name, in bpf_object__create_map()
5165 def->key_size, def->value_size, def->max_entries, in bpf_object__create_map()
5166 &create_attr, is_inner ? -1 : map - obj->maps); in bpf_object__create_map()
5168 * This fd == 0 will not be used with any syscall and will be reset to -1 eventually. in bpf_object__create_map()
5170 map->fd = 0; in bpf_object__create_map()
5172 map->fd = bpf_map_create(def->type, map_name, in bpf_object__create_map()
5173 def->key_size, def->value_size, in bpf_object__create_map()
5174 def->max_entries, &create_attr); in bpf_object__create_map()
5176 if (map->fd < 0 && (create_attr.btf_key_type_id || in bpf_object__create_map()
5180 err = -errno; in bpf_object__create_map()
5183 map->name, cp, err); in bpf_object__create_map()
5187 map->btf_key_type_id = 0; in bpf_object__create_map()
5188 map->btf_value_type_id = 0; in bpf_object__create_map()
5189 map->fd = bpf_map_create(def->type, map_name, in bpf_object__create_map()
5190 def->key_size, def->value_size, in bpf_object__create_map()
5191 def->max_entries, &create_attr); in bpf_object__create_map()
5194 err = map->fd < 0 ? -errno : 0; in bpf_object__create_map()
5196 if (bpf_map_type__is_map_in_map(def->type) && map->inner_map) { in bpf_object__create_map()
5197 if (obj->gen_loader) in bpf_object__create_map()
5198 map->inner_map->fd = -1; in bpf_object__create_map()
5199 bpf_map__destroy(map->inner_map); in bpf_object__create_map()
5200 zfree(&map->inner_map); in bpf_object__create_map()
5212 for (i = 0; i < map->init_slots_sz; i++) { in init_map_in_map_slots()
5213 if (!map->init_slots[i]) in init_map_in_map_slots()
5216 targ_map = map->init_slots[i]; in init_map_in_map_slots()
5219 if (obj->gen_loader) { in init_map_in_map_slots()
5220 bpf_gen__populate_outer_map(obj->gen_loader, in init_map_in_map_slots()
5221 map - obj->maps, i, in init_map_in_map_slots()
5222 targ_map - obj->maps); in init_map_in_map_slots()
5224 err = bpf_map_update_elem(map->fd, &i, &fd, 0); in init_map_in_map_slots()
5227 err = -errno; in init_map_in_map_slots()
5229 map->name, i, targ_map->name, fd, err); in init_map_in_map_slots()
5233 map->name, i, targ_map->name, fd); in init_map_in_map_slots()
5236 zfree(&map->init_slots); in init_map_in_map_slots()
5237 map->init_slots_sz = 0; in init_map_in_map_slots()
5248 if (obj->gen_loader) in init_prog_array_slots()
5249 return -ENOTSUP; in init_prog_array_slots()
5251 for (i = 0; i < map->init_slots_sz; i++) { in init_prog_array_slots()
5252 if (!map->init_slots[i]) in init_prog_array_slots()
5255 targ_prog = map->init_slots[i]; in init_prog_array_slots()
5258 err = bpf_map_update_elem(map->fd, &i, &fd, 0); in init_prog_array_slots()
5260 err = -errno; in init_prog_array_slots()
5262 map->name, i, targ_prog->name, fd, err); in init_prog_array_slots()
5266 map->name, i, targ_prog->name, fd); in init_prog_array_slots()
5269 zfree(&map->init_slots); in init_prog_array_slots()
5270 map->init_slots_sz = 0; in init_prog_array_slots()
5280 for (i = 0; i < obj->nr_maps; i++) { in bpf_object_init_prog_arrays()
5281 map = &obj->maps[i]; in bpf_object_init_prog_arrays()
5283 if (!map->init_slots_sz || map->def.type != BPF_MAP_TYPE_PROG_ARRAY) in bpf_object_init_prog_arrays()
5288 zclose(map->fd); in bpf_object_init_prog_arrays()
5297 if (map->def.type == BPF_MAP_TYPE_PERF_EVENT_ARRAY && !map->def.max_entries) { in map_set_def_max_entries()
5303 map->name, nr_cpus); in map_set_def_max_entries()
5306 pr_debug("map '%s': setting size to %d\n", map->name, nr_cpus); in map_set_def_max_entries()
5307 map->def.max_entries = nr_cpus; in map_set_def_max_entries()
5322 for (i = 0; i < obj->nr_maps; i++) { in bpf_object__create_maps()
5323 map = &obj->maps[i]; in bpf_object__create_maps()
5327 * loading, if we detect that at least one of the to-be-loaded in bpf_object__create_maps()
5332 * but also it allows to have CO-RE applications that use in bpf_object__create_maps()
5334 * If those global variable-using programs are not loaded at in bpf_object__create_maps()
5340 map->autocreate = false; in bpf_object__create_maps()
5342 if (!map->autocreate) { in bpf_object__create_maps()
5343 pr_debug("map '%s': skipped auto-creating...\n", map->name); in bpf_object__create_maps()
5353 if (map->pin_path) { in bpf_object__create_maps()
5357 map->name); in bpf_object__create_maps()
5360 if (retried && map->fd < 0) { in bpf_object__create_maps()
5362 map->name); in bpf_object__create_maps()
5363 err = -ENOENT; in bpf_object__create_maps()
5368 if (map->fd >= 0) { in bpf_object__create_maps()
5370 map->name, map->fd); in bpf_object__create_maps()
5377 map->name, map->fd); in bpf_object__create_maps()
5382 zclose(map->fd); in bpf_object__create_maps()
5387 if (map->init_slots_sz && map->def.type != BPF_MAP_TYPE_PROG_ARRAY) { in bpf_object__create_maps()
5390 zclose(map->fd); in bpf_object__create_maps()
5396 if (map->pin_path && !map->pinned) { in bpf_object__create_maps()
5399 zclose(map->fd); in bpf_object__create_maps()
5400 if (!retried && err == -EEXIST) { in bpf_object__create_maps()
5404 pr_warn("map '%s': failed to auto-pin at '%s': %d\n", in bpf_object__create_maps()
5405 map->name, map->pin_path, err); in bpf_object__create_maps()
5415 pr_warn("map '%s': failed to create: %s(%d)\n", map->name, cp, err); in bpf_object__create_maps()
5418 zclose(obj->maps[j].fd); in bpf_object__create_maps()
5432 * underscore is ignored by BPF CO-RE relocation during relocation matching.
5439 for (i = n - 5; i >= 0; i--) { in bpf_core_essential_name_len()
5451 free(cands->cands); in bpf_core_free_cands()
5468 local_t = btf__type_by_id(local_cand->btf, local_cand->id); in bpf_core_add_cands()
5469 local_name = btf__str_by_offset(local_cand->btf, local_t->name_off); in bpf_core_add_cands()
5477 targ_name = btf__name_by_offset(targ_btf, t->name_off); in bpf_core_add_cands()
5488 pr_debug("CO-RE relocating [%d] %s %s: found target candidate [%d] %s %s in [%s]\n", in bpf_core_add_cands()
5489 local_cand->id, btf_kind_str(local_t), in bpf_core_add_cands()
5492 new_cands = libbpf_reallocarray(cands->cands, cands->len + 1, in bpf_core_add_cands()
5493 sizeof(*cands->cands)); in bpf_core_add_cands()
5495 return -ENOMEM; in bpf_core_add_cands()
5497 cand = &new_cands[cands->len]; in bpf_core_add_cands()
5498 cand->btf = targ_btf; in bpf_core_add_cands()
5499 cand->id = i; in bpf_core_add_cands()
5501 cands->cands = new_cands; in bpf_core_add_cands()
5502 cands->len++; in bpf_core_add_cands()
5516 if (obj->btf_modules_loaded) in load_module_btfs()
5519 if (obj->gen_loader) in load_module_btfs()
5523 obj->btf_modules_loaded = true; in load_module_btfs()
5538 err = -errno; in load_module_btfs()
5547 err = -errno; in load_module_btfs()
5559 err = -errno; in load_module_btfs()
5564 /* ignore non-module BTFs */ in load_module_btfs()
5570 btf = btf_get_from_fd(fd, obj->btf_vmlinux); in load_module_btfs()
5578 err = libbpf_ensure_mem((void **)&obj->btf_modules, &obj->btf_module_cap, in load_module_btfs()
5579 sizeof(*obj->btf_modules), obj->btf_module_cnt + 1); in load_module_btfs()
5583 mod_btf = &obj->btf_modules[obj->btf_module_cnt++]; in load_module_btfs()
5585 mod_btf->btf = btf; in load_module_btfs()
5586 mod_btf->id = id; in load_module_btfs()
5587 mod_btf->fd = fd; in load_module_btfs()
5588 mod_btf->name = strdup(name); in load_module_btfs()
5589 if (!mod_btf->name) { in load_module_btfs()
5590 err = -ENOMEM; in load_module_btfs()
5618 return ERR_PTR(-EINVAL); in bpf_core_find_cands()
5620 local_name = btf__name_by_offset(local_btf, local_t->name_off); in bpf_core_find_cands()
5622 return ERR_PTR(-EINVAL); in bpf_core_find_cands()
5627 return ERR_PTR(-ENOMEM); in bpf_core_find_cands()
5630 main_btf = obj->btf_vmlinux_override ?: obj->btf_vmlinux; in bpf_core_find_cands()
5636 if (cands->len) in bpf_core_find_cands()
5640 if (obj->btf_vmlinux_override) in bpf_core_find_cands()
5648 for (i = 0; i < obj->btf_module_cnt; i++) { in bpf_core_find_cands()
5650 obj->btf_modules[i].btf, in bpf_core_find_cands()
5651 obj->btf_modules[i].name, in bpf_core_find_cands()
5652 btf__type_cnt(obj->btf_vmlinux), in bpf_core_find_cands()
5665 * type-based CO-RE relocations and follow slightly different rules than
5666 * field-based relocations. This function assumes that root types were already
5667 * checked for name match. Beyond that initial root-level name check, names
5669 * - any two STRUCTs/UNIONs/FWDs/ENUMs/INTs are considered compatible, but
5672 * - for ENUMs, the size is ignored;
5673 * - for INT, size and signedness are ignored;
5674 * - for ARRAY, dimensionality is ignored, element types are checked for
5676 * - CONST/VOLATILE/RESTRICT modifiers are ignored;
5677 * - TYPEDEFs/PTRs are compatible if types they pointing to are compatible;
5678 * - FUNC_PROTOs are compatible if they have compatible signature: same
5681 * more experience with using BPF CO-RE relocations.
5710 relos = libbpf_reallocarray(prog->reloc_desc, in record_relo_core()
5711 prog->nr_reloc + 1, sizeof(*relos)); in record_relo_core()
5713 return -ENOMEM; in record_relo_core()
5714 relo = &relos[prog->nr_reloc]; in record_relo_core()
5715 relo->type = RELO_CORE; in record_relo_core()
5716 relo->insn_idx = insn_idx; in record_relo_core()
5717 relo->core_relo = core_relo; in record_relo_core()
5718 prog->reloc_desc = relos; in record_relo_core()
5719 prog->nr_reloc++; in record_relo_core()
5728 for (i = 0; i < prog->nr_reloc; i++) { in find_relo_core()
5729 relo = &prog->reloc_desc[i]; in find_relo_core()
5730 if (relo->type != RELO_CORE || relo->insn_idx != insn_idx) in find_relo_core()
5733 return relo->core_relo; in find_relo_core()
5748 const char *prog_name = prog->name; in bpf_core_resolve_relo()
5751 __u32 local_id = relo->type_id; in bpf_core_resolve_relo()
5756 return -EINVAL; in bpf_core_resolve_relo()
5758 local_name = btf__name_by_offset(local_btf, local_type->name_off); in bpf_core_resolve_relo()
5760 return -EINVAL; in bpf_core_resolve_relo()
5762 if (relo->kind != BPF_CORE_TYPE_ID_LOCAL && in bpf_core_resolve_relo()
5764 cands = bpf_core_find_cands(prog->obj, local_btf, local_id); in bpf_core_resolve_relo()
5796 if (obj->btf_ext->core_relo_info.len == 0) in bpf_object__relocate_core()
5800 obj->btf_vmlinux_override = btf__parse(targ_btf_path, NULL); in bpf_object__relocate_core()
5801 err = libbpf_get_error(obj->btf_vmlinux_override); in bpf_object__relocate_core()
5814 seg = &obj->btf_ext->core_relo_info; in bpf_object__relocate_core()
5817 sec_idx = seg->sec_idxs[sec_num]; in bpf_object__relocate_core()
5820 sec_name = btf__name_by_offset(obj->btf, sec->sec_name_off); in bpf_object__relocate_core()
5822 err = -EINVAL; in bpf_object__relocate_core()
5826 pr_debug("sec '%s': found %d CO-RE relocations\n", sec_name, sec->num_info); in bpf_object__relocate_core()
5829 if (rec->insn_off % BPF_INSN_SZ) in bpf_object__relocate_core()
5830 return -EINVAL; in bpf_object__relocate_core()
5831 insn_idx = rec->insn_off / BPF_INSN_SZ; in bpf_object__relocate_core()
5836 * appends all the .BTF.ext info that used to belong to that in bpf_object__relocate_core()
5838 * This is similar to what x86-64 linker does for relocations. in bpf_object__relocate_core()
5842 …pr_debug("sec '%s': skipping CO-RE relocation #%d for insn #%d belonging to eliminated weak subpro… in bpf_object__relocate_core()
5846 /* no need to apply CO-RE relocation if the program is in bpf_object__relocate_core()
5849 if (!prog->autoload) in bpf_object__relocate_core()
5853 * program's frame of reference; (sub-)program code is not yet in bpf_object__relocate_core()
5854 * relocated, so it's enough to just subtract in-section offset in bpf_object__relocate_core()
5856 insn_idx = insn_idx - prog->sec_insn_off; in bpf_object__relocate_core()
5857 if (insn_idx >= prog->insns_cnt) in bpf_object__relocate_core()
5858 return -EINVAL; in bpf_object__relocate_core()
5859 insn = &prog->insns[insn_idx]; in bpf_object__relocate_core()
5864 prog->name, i, err); in bpf_object__relocate_core()
5868 if (prog->obj->gen_loader) in bpf_object__relocate_core()
5871 err = bpf_core_resolve_relo(prog, rec, i, obj->btf, cand_cache, &targ_res); in bpf_object__relocate_core()
5874 prog->name, i, err); in bpf_object__relocate_core()
5878 err = bpf_core_patch_insn(prog->name, insn, insn_idx, rec, i, &targ_res); in bpf_object__relocate_core()
5881 prog->name, i, insn_idx, err); in bpf_object__relocate_core()
5888 /* obj->btf_vmlinux and module BTFs are freed after object load */ in bpf_object__relocate_core()
5889 btf__free(obj->btf_vmlinux_override); in bpf_object__relocate_core()
5890 obj->btf_vmlinux_override = NULL; in bpf_object__relocate_core()
5894 bpf_core_free_cands(entry->pvalue); in bpf_object__relocate_core()
5912 prog->name, relo_idx, insn_idx, map_idx, map->name); in poison_map_ldimm64()
5916 insn->code = BPF_JMP | BPF_CALL; in poison_map_ldimm64()
5917 insn->dst_reg = 0; in poison_map_ldimm64()
5918 insn->src_reg = 0; in poison_map_ldimm64()
5919 insn->off = 0; in poison_map_ldimm64()
5923 * where lower 123 is map index into obj->maps[] array in poison_map_ldimm64()
5925 insn->imm = POISON_LDIMM64_MAP_BASE + map_idx; in poison_map_ldimm64()
5937 int ext_idx, const struct extern_desc *ext) in poison_kfunc_call() argument
5940 prog->name, relo_idx, insn_idx, ext->name); in poison_kfunc_call()
5943 insn->code = BPF_JMP | BPF_CALL; in poison_kfunc_call()
5944 insn->dst_reg = 0; in poison_kfunc_call()
5945 insn->src_reg = 0; in poison_kfunc_call()
5946 insn->off = 0; in poison_kfunc_call()
5950 * where lower 123 is extern index into obj->externs[] array in poison_kfunc_call()
5952 insn->imm = POISON_CALL_KFUNC_BASE + ext_idx; in poison_kfunc_call()
5956 * - map references;
5957 * - global variable references;
5958 * - extern references.
5965 for (i = 0; i < prog->nr_reloc; i++) { in bpf_object__relocate_data()
5966 struct reloc_desc *relo = &prog->reloc_desc[i]; in bpf_object__relocate_data()
5967 struct bpf_insn *insn = &prog->insns[relo->insn_idx]; in bpf_object__relocate_data()
5969 struct extern_desc *ext; in bpf_object__relocate_data() local
5971 switch (relo->type) { in bpf_object__relocate_data()
5973 map = &obj->maps[relo->map_idx]; in bpf_object__relocate_data()
5974 if (obj->gen_loader) { in bpf_object__relocate_data()
5976 insn[0].imm = relo->map_idx; in bpf_object__relocate_data()
5977 } else if (map->autocreate) { in bpf_object__relocate_data()
5979 insn[0].imm = map->fd; in bpf_object__relocate_data()
5981 poison_map_ldimm64(prog, i, relo->insn_idx, insn, in bpf_object__relocate_data()
5982 relo->map_idx, map); in bpf_object__relocate_data()
5986 map = &obj->maps[relo->map_idx]; in bpf_object__relocate_data()
5987 insn[1].imm = insn[0].imm + relo->sym_off; in bpf_object__relocate_data()
5988 if (obj->gen_loader) { in bpf_object__relocate_data()
5990 insn[0].imm = relo->map_idx; in bpf_object__relocate_data()
5991 } else if (map->autocreate) { in bpf_object__relocate_data()
5993 insn[0].imm = map->fd; in bpf_object__relocate_data()
5995 poison_map_ldimm64(prog, i, relo->insn_idx, insn, in bpf_object__relocate_data()
5996 relo->map_idx, map); in bpf_object__relocate_data()
6000 ext = &obj->externs[relo->ext_idx]; in bpf_object__relocate_data()
6001 if (ext->type == EXT_KCFG) { in bpf_object__relocate_data()
6002 if (obj->gen_loader) { in bpf_object__relocate_data()
6004 insn[0].imm = obj->kconfig_map_idx; in bpf_object__relocate_data()
6007 insn[0].imm = obj->maps[obj->kconfig_map_idx].fd; in bpf_object__relocate_data()
6009 insn[1].imm = ext->kcfg.data_off; in bpf_object__relocate_data()
6011 if (ext->ksym.type_id && ext->is_set) { /* typed ksyms */ in bpf_object__relocate_data()
6013 insn[0].imm = ext->ksym.kernel_btf_id; in bpf_object__relocate_data()
6014 insn[1].imm = ext->ksym.kernel_btf_obj_fd; in bpf_object__relocate_data()
6016 insn[0].imm = (__u32)ext->ksym.addr; in bpf_object__relocate_data()
6017 insn[1].imm = ext->ksym.addr >> 32; in bpf_object__relocate_data()
6022 ext = &obj->externs[relo->ext_idx]; in bpf_object__relocate_data()
6024 if (ext->is_set) { in bpf_object__relocate_data()
6025 insn[0].imm = ext->ksym.kernel_btf_id; in bpf_object__relocate_data()
6026 insn[0].off = ext->ksym.btf_fd_idx; in bpf_object__relocate_data()
6028 poison_kfunc_call(prog, i, relo->insn_idx, insn, in bpf_object__relocate_data()
6029 relo->ext_idx, ext); in bpf_object__relocate_data()
6035 prog->name, i); in bpf_object__relocate_data()
6036 return -EINVAL; in bpf_object__relocate_data()
6048 prog->name, i, relo->type); in bpf_object__relocate_data()
6049 return -EINVAL; in bpf_object__relocate_data()
6070 sec_idx = ext_info->sec_idxs[sec_num]; in adjust_prog_btf_ext_info()
6072 if (prog->sec_idx != sec_idx) in adjust_prog_btf_ext_info()
6078 if (insn_off < prog->sec_insn_off) in adjust_prog_btf_ext_info()
6080 if (insn_off >= prog->sec_insn_off + prog->sec_insn_cnt) in adjust_prog_btf_ext_info()
6085 copy_end = rec + ext_info->rec_size; in adjust_prog_btf_ext_info()
6089 return -ENOENT; in adjust_prog_btf_ext_info()
6091 /* append func/line info of a given (sub-)program to the main in adjust_prog_btf_ext_info()
6094 old_sz = (size_t)(*prog_rec_cnt) * ext_info->rec_size; in adjust_prog_btf_ext_info()
6095 new_sz = old_sz + (copy_end - copy_start); in adjust_prog_btf_ext_info()
6098 return -ENOMEM; in adjust_prog_btf_ext_info()
6100 *prog_rec_cnt = new_sz / ext_info->rec_size; in adjust_prog_btf_ext_info()
6101 memcpy(new_prog_info + old_sz, copy_start, copy_end - copy_start); in adjust_prog_btf_ext_info()
6103 /* Kernel instruction offsets are in units of 8-byte in adjust_prog_btf_ext_info()
6104 * instructions, while .BTF.ext instruction offsets generated in adjust_prog_btf_ext_info()
6109 off_adj = prog->sub_insn_off - prog->sec_insn_off; in adjust_prog_btf_ext_info()
6112 for (; rec < rec_end; rec += ext_info->rec_size) { in adjust_prog_btf_ext_info()
6117 *prog_rec_sz = ext_info->rec_size; in adjust_prog_btf_ext_info()
6121 return -ENOENT; in adjust_prog_btf_ext_info()
6131 /* no .BTF.ext relocation if .BTF.ext is missing or kernel doesn't in reloc_prog_func_and_line_info()
6134 if (!obj->btf_ext || !kernel_supports(obj, FEAT_BTF_FUNC)) in reloc_prog_func_and_line_info()
6140 if (main_prog != prog && !main_prog->func_info) in reloc_prog_func_and_line_info()
6143 err = adjust_prog_btf_ext_info(obj, prog, &obj->btf_ext->func_info, in reloc_prog_func_and_line_info()
6144 &main_prog->func_info, in reloc_prog_func_and_line_info()
6145 &main_prog->func_info_cnt, in reloc_prog_func_and_line_info()
6146 &main_prog->func_info_rec_size); in reloc_prog_func_and_line_info()
6148 if (err != -ENOENT) { in reloc_prog_func_and_line_info()
6149 pr_warn("prog '%s': error relocating .BTF.ext function info: %d\n", in reloc_prog_func_and_line_info()
6150 prog->name, err); in reloc_prog_func_and_line_info()
6153 if (main_prog->func_info) { in reloc_prog_func_and_line_info()
6158 pr_warn("prog '%s': missing .BTF.ext function info.\n", prog->name); in reloc_prog_func_and_line_info()
6162 …pr_warn("prog '%s': missing .BTF.ext function info for the main program, skipping all of .BTF.ext … in reloc_prog_func_and_line_info()
6163 prog->name); in reloc_prog_func_and_line_info()
6168 if (main_prog != prog && !main_prog->line_info) in reloc_prog_func_and_line_info()
6171 err = adjust_prog_btf_ext_info(obj, prog, &obj->btf_ext->line_info, in reloc_prog_func_and_line_info()
6172 &main_prog->line_info, in reloc_prog_func_and_line_info()
6173 &main_prog->line_info_cnt, in reloc_prog_func_and_line_info()
6174 &main_prog->line_info_rec_size); in reloc_prog_func_and_line_info()
6176 if (err != -ENOENT) { in reloc_prog_func_and_line_info()
6177 pr_warn("prog '%s': error relocating .BTF.ext line info: %d\n", in reloc_prog_func_and_line_info()
6178 prog->name, err); in reloc_prog_func_and_line_info()
6181 if (main_prog->line_info) { in reloc_prog_func_and_line_info()
6186 pr_warn("prog '%s': missing .BTF.ext line info.\n", prog->name); in reloc_prog_func_and_line_info()
6190 …pr_warn("prog '%s': missing .BTF.ext line info for the main program, skipping all of .BTF.ext line… in reloc_prog_func_and_line_info()
6191 prog->name); in reloc_prog_func_and_line_info()
6201 if (insn_idx == relo->insn_idx) in cmp_relo_by_insn_idx()
6203 return insn_idx < relo->insn_idx ? -1 : 1; in cmp_relo_by_insn_idx()
6208 if (!prog->nr_reloc) in find_prog_insn_relo()
6210 return bsearch(&insn_idx, prog->reloc_desc, prog->nr_reloc, in find_prog_insn_relo()
6211 sizeof(*prog->reloc_desc), cmp_relo_by_insn_idx); in find_prog_insn_relo()
6216 int new_cnt = main_prog->nr_reloc + subprog->nr_reloc; in append_subprog_relos()
6222 relos = libbpf_reallocarray(main_prog->reloc_desc, new_cnt, sizeof(*relos)); in append_subprog_relos()
6228 return -ENOMEM; in append_subprog_relos()
6229 if (subprog->nr_reloc) in append_subprog_relos()
6230 memcpy(relos + main_prog->nr_reloc, subprog->reloc_desc, in append_subprog_relos()
6231 sizeof(*relos) * subprog->nr_reloc); in append_subprog_relos()
6233 for (i = main_prog->nr_reloc; i < new_cnt; i++) in append_subprog_relos()
6234 relos[i].insn_idx += subprog->sub_insn_off; in append_subprog_relos()
6238 main_prog->reloc_desc = relos; in append_subprog_relos()
6239 main_prog->nr_reloc = new_cnt; in append_subprog_relos()
6257 for (insn_idx = 0; insn_idx < prog->sec_insn_cnt; insn_idx++) { in bpf_object__reloc_code()
6258 insn = &main_prog->insns[prog->sub_insn_off + insn_idx]; in bpf_object__reloc_code()
6263 if (relo && relo->type == RELO_EXTERN_CALL) in bpf_object__reloc_code()
6268 if (relo && relo->type != RELO_CALL && relo->type != RELO_SUBPROG_ADDR) { in bpf_object__reloc_code()
6270 prog->name, insn_idx, relo->type); in bpf_object__reloc_code()
6271 return -LIBBPF_ERRNO__RELOC; in bpf_object__reloc_code()
6274 /* sub-program instruction index is a combination of in bpf_object__reloc_code()
6277 * call always has imm = -1, but for static functions in bpf_object__reloc_code()
6278 * relocation is against STT_SECTION and insn->imm in bpf_object__reloc_code()
6281 * for subprog addr relocation, the relo->sym_off + insn->imm is in bpf_object__reloc_code()
6284 if (relo->type == RELO_CALL) in bpf_object__reloc_code()
6285 sub_insn_idx = relo->sym_off / BPF_INSN_SZ + insn->imm + 1; in bpf_object__reloc_code()
6287 sub_insn_idx = (relo->sym_off + insn->imm) / BPF_INSN_SZ; in bpf_object__reloc_code()
6294 prog->name, insn_idx); in bpf_object__reloc_code()
6295 return -LIBBPF_ERRNO__RELOC; in bpf_object__reloc_code()
6300 * offset necessary, insns->imm is relative to in bpf_object__reloc_code()
6303 sub_insn_idx = prog->sec_insn_off + insn_idx + insn->imm + 1; in bpf_object__reloc_code()
6306 /* we enforce that sub-programs should be in .text section */ in bpf_object__reloc_code()
6307 subprog = find_prog_by_sec_insn(obj, obj->efile.text_shndx, sub_insn_idx); in bpf_object__reloc_code()
6309 pr_warn("prog '%s': no .text section found yet sub-program call exists\n", in bpf_object__reloc_code()
6310 prog->name); in bpf_object__reloc_code()
6311 return -LIBBPF_ERRNO__RELOC; in bpf_object__reloc_code()
6317 * - append it at the end of main program's instructions blog; in bpf_object__reloc_code()
6318 * - process is recursively, while current program is put on hold; in bpf_object__reloc_code()
6319 * - if that subprogram calls some other not yet processes in bpf_object__reloc_code()
6324 if (subprog->sub_insn_off == 0) { in bpf_object__reloc_code()
6325 subprog->sub_insn_off = main_prog->insns_cnt; in bpf_object__reloc_code()
6327 new_cnt = main_prog->insns_cnt + subprog->insns_cnt; in bpf_object__reloc_code()
6328 insns = libbpf_reallocarray(main_prog->insns, new_cnt, sizeof(*insns)); in bpf_object__reloc_code()
6330 pr_warn("prog '%s': failed to realloc prog code\n", main_prog->name); in bpf_object__reloc_code()
6331 return -ENOMEM; in bpf_object__reloc_code()
6333 main_prog->insns = insns; in bpf_object__reloc_code()
6334 main_prog->insns_cnt = new_cnt; in bpf_object__reloc_code()
6336 memcpy(main_prog->insns + subprog->sub_insn_off, subprog->insns, in bpf_object__reloc_code()
6337 subprog->insns_cnt * sizeof(*insns)); in bpf_object__reloc_code()
6339 pr_debug("prog '%s': added %zu insns from sub-prog '%s'\n", in bpf_object__reloc_code()
6340 main_prog->name, subprog->insns_cnt, subprog->name); in bpf_object__reloc_code()
6351 /* main_prog->insns memory could have been re-allocated, so in bpf_object__reloc_code()
6354 insn = &main_prog->insns[prog->sub_insn_off + insn_idx]; in bpf_object__reloc_code()
6361 insn->imm = subprog->sub_insn_off - (prog->sub_insn_off + insn_idx) - 1; in bpf_object__reloc_code()
6364 prog->name, insn_idx, insn->imm, subprog->name, subprog->sub_insn_off); in bpf_object__reloc_code()
6371 * Relocate sub-program calls.
6373 * Algorithm operates as follows. Each entry-point BPF program (referred to as
6374 * main prog) is processed separately. For each subprog (non-entry functions,
6383 * is into a subprog that hasn't been processed (i.e., subprog->sub_insn_off
6399 * subprog->sub_insn_off as zero at all times and won't be appended to current
6408 * +--------+ +-------+
6410 * +--+---+ +--+-+-+ +---+--+
6412 * +--+---+ +------+ +---+--+
6415 * +---+-------+ +------+----+
6417 * +-----------+ +-----------+
6422 * +-----------+------+
6424 * +-----------+------+
6429 * +-----------+------+------+
6431 * +-----------+------+------+
6440 * +-----------+------+
6442 * +-----------+------+
6445 * +-----------+------+------+
6447 * +-----------+------+------+
6460 for (i = 0; i < obj->nr_programs; i++) { in bpf_object__relocate_calls()
6461 subprog = &obj->programs[i]; in bpf_object__relocate_calls()
6465 subprog->sub_insn_off = 0; in bpf_object__relocate_calls()
6482 for (i = 0; i < obj->nr_programs; i++) { in bpf_object__free_relocs()
6483 prog = &obj->programs[i]; in bpf_object__free_relocs()
6484 zfree(&prog->reloc_desc); in bpf_object__free_relocs()
6485 prog->nr_reloc = 0; in bpf_object__free_relocs()
6494 if (a->insn_idx != b->insn_idx) in cmp_relocs()
6495 return a->insn_idx < b->insn_idx ? -1 : 1; in cmp_relocs()
6498 if (a->type != b->type) in cmp_relocs()
6499 return a->type < b->type ? -1 : 1; in cmp_relocs()
6508 for (i = 0; i < obj->nr_programs; i++) { in bpf_object__sort_relos()
6509 struct bpf_program *p = &obj->programs[i]; in bpf_object__sort_relos()
6511 if (!p->nr_reloc) in bpf_object__sort_relos()
6514 qsort(p->reloc_desc, p->nr_reloc, sizeof(*p->reloc_desc), cmp_relocs); in bpf_object__sort_relos()
6525 if (obj->btf_ext) { in bpf_object__relocate()
6528 pr_warn("failed to perform CO-RE relocations: %d\n", in bpf_object__relocate()
6535 /* Before relocating calls pre-process relocations and mark in bpf_object__relocate()
6542 for (i = 0; i < obj->nr_programs; i++) { in bpf_object__relocate()
6543 prog = &obj->programs[i]; in bpf_object__relocate()
6544 for (j = 0; j < prog->nr_reloc; j++) { in bpf_object__relocate()
6545 struct reloc_desc *relo = &prog->reloc_desc[j]; in bpf_object__relocate()
6546 struct bpf_insn *insn = &prog->insns[relo->insn_idx]; in bpf_object__relocate()
6549 if (relo->type == RELO_SUBPROG_ADDR) in bpf_object__relocate()
6561 for (i = 0; i < obj->nr_programs; i++) { in bpf_object__relocate()
6562 prog = &obj->programs[i]; in bpf_object__relocate()
6563 /* sub-program's sub-calls are relocated within the context of in bpf_object__relocate()
6568 if (!prog->autoload) in bpf_object__relocate()
6574 prog->name, err); in bpf_object__relocate()
6579 for (i = 0; i < obj->nr_programs; i++) { in bpf_object__relocate()
6580 prog = &obj->programs[i]; in bpf_object__relocate()
6583 if (!prog->autoload) in bpf_object__relocate()
6588 prog->name, err); in bpf_object__relocate()
6616 if (!obj->efile.btf_maps_sec_btf_id || !obj->btf) in bpf_object__collect_map_relos()
6617 return -EINVAL; in bpf_object__collect_map_relos()
6618 sec = btf__type_by_id(obj->btf, obj->efile.btf_maps_sec_btf_id); in bpf_object__collect_map_relos()
6620 return -EINVAL; in bpf_object__collect_map_relos()
6622 nrels = shdr->sh_size / shdr->sh_entsize; in bpf_object__collect_map_relos()
6627 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_map_relos()
6630 sym = elf_sym_by_idx(obj, ELF64_R_SYM(rel->r_info)); in bpf_object__collect_map_relos()
6633 i, (size_t)ELF64_R_SYM(rel->r_info)); in bpf_object__collect_map_relos()
6634 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_map_relos()
6636 name = elf_sym_str(obj, sym->st_name) ?: "<?>"; in bpf_object__collect_map_relos()
6638 pr_debug(".maps relo #%d: for %zd value %zd rel->r_offset %zu name %d ('%s')\n", in bpf_object__collect_map_relos()
6639 i, (ssize_t)(rel->r_info >> 32), (size_t)sym->st_value, in bpf_object__collect_map_relos()
6640 (size_t)rel->r_offset, sym->st_name, name); in bpf_object__collect_map_relos()
6642 for (j = 0; j < obj->nr_maps; j++) { in bpf_object__collect_map_relos()
6643 map = &obj->maps[j]; in bpf_object__collect_map_relos()
6644 if (map->sec_idx != obj->efile.btf_maps_shndx) in bpf_object__collect_map_relos()
6647 vi = btf_var_secinfos(sec) + map->btf_var_idx; in bpf_object__collect_map_relos()
6648 if (vi->offset <= rel->r_offset && in bpf_object__collect_map_relos()
6649 rel->r_offset + bpf_ptr_sz <= vi->offset + vi->size) in bpf_object__collect_map_relos()
6652 if (j == obj->nr_maps) { in bpf_object__collect_map_relos()
6653 pr_warn(".maps relo #%d: cannot find map '%s' at rel->r_offset %zu\n", in bpf_object__collect_map_relos()
6654 i, name, (size_t)rel->r_offset); in bpf_object__collect_map_relos()
6655 return -EINVAL; in bpf_object__collect_map_relos()
6658 is_map_in_map = bpf_map_type__is_map_in_map(map->def.type); in bpf_object__collect_map_relos()
6659 is_prog_array = map->def.type == BPF_MAP_TYPE_PROG_ARRAY; in bpf_object__collect_map_relos()
6662 if (sym->st_shndx != obj->efile.btf_maps_shndx) { in bpf_object__collect_map_relos()
6663 pr_warn(".maps relo #%d: '%s' isn't a BTF-defined map\n", in bpf_object__collect_map_relos()
6665 return -LIBBPF_ERRNO__RELOC; in bpf_object__collect_map_relos()
6667 if (map->def.type == BPF_MAP_TYPE_HASH_OF_MAPS && in bpf_object__collect_map_relos()
6668 map->def.key_size != sizeof(int)) { in bpf_object__collect_map_relos()
6669 pr_warn(".maps relo #%d: hash-of-maps '%s' should have key size %zu.\n", in bpf_object__collect_map_relos()
6670 i, map->name, sizeof(int)); in bpf_object__collect_map_relos()
6671 return -EINVAL; in bpf_object__collect_map_relos()
6677 return -ESRCH; in bpf_object__collect_map_relos()
6684 return -ESRCH; in bpf_object__collect_map_relos()
6686 if (targ_prog->sec_idx != sym->st_shndx || in bpf_object__collect_map_relos()
6687 targ_prog->sec_insn_off * 8 != sym->st_value || in bpf_object__collect_map_relos()
6689 pr_warn(".maps relo #%d: '%s' isn't an entry-point program\n", in bpf_object__collect_map_relos()
6691 return -LIBBPF_ERRNO__RELOC; in bpf_object__collect_map_relos()
6694 return -EINVAL; in bpf_object__collect_map_relos()
6697 var = btf__type_by_id(obj->btf, vi->type); in bpf_object__collect_map_relos()
6698 def = skip_mods_and_typedefs(obj->btf, var->type, NULL); in bpf_object__collect_map_relos()
6700 return -EINVAL; in bpf_object__collect_map_relos()
6701 member = btf_members(def) + btf_vlen(def) - 1; in bpf_object__collect_map_relos()
6702 mname = btf__name_by_offset(obj->btf, member->name_off); in bpf_object__collect_map_relos()
6704 return -EINVAL; in bpf_object__collect_map_relos()
6706 moff = btf_member_bit_offset(def, btf_vlen(def) - 1) / 8; in bpf_object__collect_map_relos()
6707 if (rel->r_offset - vi->offset < moff) in bpf_object__collect_map_relos()
6708 return -EINVAL; in bpf_object__collect_map_relos()
6710 moff = rel->r_offset - vi->offset - moff; in bpf_object__collect_map_relos()
6715 return -EINVAL; in bpf_object__collect_map_relos()
6717 if (moff >= map->init_slots_sz) { in bpf_object__collect_map_relos()
6719 tmp = libbpf_reallocarray(map->init_slots, new_sz, host_ptr_sz); in bpf_object__collect_map_relos()
6721 return -ENOMEM; in bpf_object__collect_map_relos()
6722 map->init_slots = tmp; in bpf_object__collect_map_relos()
6723 memset(map->init_slots + map->init_slots_sz, 0, in bpf_object__collect_map_relos()
6724 (new_sz - map->init_slots_sz) * host_ptr_sz); in bpf_object__collect_map_relos()
6725 map->init_slots_sz = new_sz; in bpf_object__collect_map_relos()
6727 map->init_slots[moff] = is_map_in_map ? (void *)targ_map : (void *)targ_prog; in bpf_object__collect_map_relos()
6730 i, map->name, moff, type, name); in bpf_object__collect_map_relos()
6740 for (i = 0; i < obj->efile.sec_cnt; i++) { in bpf_object__collect_relos()
6741 struct elf_sec_desc *sec_desc = &obj->efile.secs[i]; in bpf_object__collect_relos()
6746 if (sec_desc->sec_type != SEC_RELO) in bpf_object__collect_relos()
6749 shdr = sec_desc->shdr; in bpf_object__collect_relos()
6750 data = sec_desc->data; in bpf_object__collect_relos()
6751 idx = shdr->sh_info; in bpf_object__collect_relos()
6753 if (shdr->sh_type != SHT_REL) { in bpf_object__collect_relos()
6755 return -LIBBPF_ERRNO__INTERNAL; in bpf_object__collect_relos()
6758 if (idx == obj->efile.st_ops_shndx || idx == obj->efile.st_ops_link_shndx) in bpf_object__collect_relos()
6760 else if (idx == obj->efile.btf_maps_shndx) in bpf_object__collect_relos()
6774 if (BPF_CLASS(insn->code) == BPF_JMP && in insn_is_helper_call()
6775 BPF_OP(insn->code) == BPF_CALL && in insn_is_helper_call()
6776 BPF_SRC(insn->code) == BPF_K && in insn_is_helper_call()
6777 insn->src_reg == 0 && in insn_is_helper_call()
6778 insn->dst_reg == 0) { in insn_is_helper_call()
6779 *func_id = insn->imm; in insn_is_helper_call()
6787 struct bpf_insn *insn = prog->insns; in bpf_object__sanitize_prog()
6791 if (obj->gen_loader) in bpf_object__sanitize_prog()
6794 for (i = 0; i < prog->insns_cnt; i++, insn++) { in bpf_object__sanitize_prog()
6806 insn->imm = BPF_FUNC_probe_read; in bpf_object__sanitize_prog()
6811 insn->imm = BPF_FUNC_probe_read_str; in bpf_object__sanitize_prog()
6823 /* this is called as prog->sec_def->prog_prepare_load_fn for libbpf-supported sec_defs */
6830 if ((def & SEC_EXP_ATTACH_OPT) && !kernel_supports(prog->obj, FEAT_EXP_ATTACH_TYPE)) in libbpf_prepare_prog_load()
6831 opts->expected_attach_type = 0; in libbpf_prepare_prog_load()
6834 opts->prog_flags |= BPF_F_SLEEPABLE; in libbpf_prepare_prog_load()
6836 if (prog->type == BPF_PROG_TYPE_XDP && (def & SEC_XDP_FRAGS)) in libbpf_prepare_prog_load()
6837 opts->prog_flags |= BPF_F_XDP_HAS_FRAGS; in libbpf_prepare_prog_load()
6840 if ((def & SEC_USDT) && kernel_supports(prog->obj, FEAT_UPROBE_MULTI_LINK)) { in libbpf_prepare_prog_load()
6845 prog->expected_attach_type = BPF_TRACE_UPROBE_MULTI; in libbpf_prepare_prog_load()
6846 opts->expected_attach_type = BPF_TRACE_UPROBE_MULTI; in libbpf_prepare_prog_load()
6849 if ((def & SEC_ATTACH_BTF) && !prog->attach_btf_id) { in libbpf_prepare_prog_load()
6853 attach_name = strchr(prog->sec_name, '/'); in libbpf_prepare_prog_load()
6864 …pr_warn("prog '%s': no BTF-based attach target is specified, use bpf_program__set_attach_target()\… in libbpf_prepare_prog_load()
6865 prog->name); in libbpf_prepare_prog_load()
6866 return -EINVAL; in libbpf_prepare_prog_load()
6875 prog->attach_btf_obj_fd = btf_obj_fd; in libbpf_prepare_prog_load()
6876 prog->attach_btf_id = btf_type_id; in libbpf_prepare_prog_load()
6879 * prog->atach_btf_obj_fd/prog->attach_btf_id anymore because in libbpf_prepare_prog_load()
6883 opts->attach_btf_obj_fd = btf_obj_fd; in libbpf_prepare_prog_load()
6884 opts->attach_btf_id = btf_type_id; in libbpf_prepare_prog_load()
6902 __u32 log_level = prog->log_level; in bpf_object_load_prog()
6904 if (prog->type == BPF_PROG_TYPE_UNSPEC) { in bpf_object_load_prog()
6910 prog->name, prog->sec_name); in bpf_object_load_prog()
6911 return -EINVAL; in bpf_object_load_prog()
6915 return -EINVAL; in bpf_object_load_prog()
6918 prog_name = prog->name; in bpf_object_load_prog()
6919 load_attr.attach_prog_fd = prog->attach_prog_fd; in bpf_object_load_prog()
6920 load_attr.attach_btf_obj_fd = prog->attach_btf_obj_fd; in bpf_object_load_prog()
6921 load_attr.attach_btf_id = prog->attach_btf_id; in bpf_object_load_prog()
6923 load_attr.prog_ifindex = prog->prog_ifindex; in bpf_object_load_prog()
6924 load_attr.expected_attach_type = prog->expected_attach_type; in bpf_object_load_prog()
6930 load_attr.func_info = prog->func_info; in bpf_object_load_prog()
6931 load_attr.func_info_rec_size = prog->func_info_rec_size; in bpf_object_load_prog()
6932 load_attr.func_info_cnt = prog->func_info_cnt; in bpf_object_load_prog()
6933 load_attr.line_info = prog->line_info; in bpf_object_load_prog()
6934 load_attr.line_info_rec_size = prog->line_info_rec_size; in bpf_object_load_prog()
6935 load_attr.line_info_cnt = prog->line_info_cnt; in bpf_object_load_prog()
6938 load_attr.prog_flags = prog->prog_flags; in bpf_object_load_prog()
6939 load_attr.fd_array = obj->fd_array; in bpf_object_load_prog()
6942 if (prog->sec_def && prog->sec_def->prog_prepare_load_fn) { in bpf_object_load_prog()
6943 err = prog->sec_def->prog_prepare_load_fn(prog, &load_attr, prog->sec_def->cookie); in bpf_object_load_prog()
6946 prog->name, err); in bpf_object_load_prog()
6949 insns = prog->insns; in bpf_object_load_prog()
6950 insns_cnt = prog->insns_cnt; in bpf_object_load_prog()
6953 if (obj->gen_loader) { in bpf_object_load_prog()
6954 bpf_gen__prog_load(obj->gen_loader, prog->type, prog->name, in bpf_object_load_prog()
6956 prog - obj->programs); in bpf_object_load_prog()
6957 *prog_fd = -1; in bpf_object_load_prog()
6968 if (prog->log_buf) { in bpf_object_load_prog()
6969 log_buf = prog->log_buf; in bpf_object_load_prog()
6970 log_buf_size = prog->log_size; in bpf_object_load_prog()
6972 } else if (obj->log_buf) { in bpf_object_load_prog()
6973 log_buf = obj->log_buf; in bpf_object_load_prog()
6974 log_buf_size = obj->log_size; in bpf_object_load_prog()
6980 ret = -ENOMEM; in bpf_object_load_prog()
6993 ret = bpf_prog_load(prog->type, prog_name, license, insns, insns_cnt, &load_attr); in bpf_object_load_prog()
6996 pr_debug("prog '%s': -- BEGIN PROG LOAD LOG --\n%s-- END PROG LOAD LOG --\n", in bpf_object_load_prog()
6997 prog->name, log_buf); in bpf_object_load_prog()
7000 if (obj->has_rodata && kernel_supports(obj, FEAT_PROG_BIND_MAP)) { in bpf_object_load_prog()
7004 for (i = 0; i < obj->nr_maps; i++) { in bpf_object_load_prog()
7005 map = &prog->obj->maps[i]; in bpf_object_load_prog()
7006 if (map->libbpf_type != LIBBPF_MAP_RODATA) in bpf_object_load_prog()
7012 prog->name, map->real_name, cp); in bpf_object_load_prog()
7032 * Currently, we'll get -EINVAL when we reach (UINT_MAX >> 2). in bpf_object_load_prog()
7037 ret = -errno; in bpf_object_load_prog()
7039 /* post-process verifier log to improve error descriptions */ in bpf_object_load_prog()
7043 pr_warn("prog '%s': BPF program load failed: %s\n", prog->name, cp); in bpf_object_load_prog()
7047 pr_warn("prog '%s': -- BEGIN PROG LOAD LOG --\n%s-- END PROG LOAD LOG --\n", in bpf_object_load_prog()
7048 prog->name, log_buf); in bpf_object_load_prog()
7064 p = cur - 1; in find_prev_line()
7065 while (p - 1 >= buf && *(p - 1) != '\n') in find_prev_line()
7066 p--; in find_prev_line()
7074 /* size of the remaining log content to the right from the to-be-replaced part */ in patch_log()
7075 size_t rem_sz = (buf + log_sz) - (orig + orig_sz); in patch_log()
7080 * shift log contents by (patch_sz - orig_sz) bytes to the right in patch_log()
7081 * starting from after to-be-replaced part of the log. in patch_log()
7084 * shift log contents by (orig_sz - patch_sz) bytes to the left in patch_log()
7085 * starting from after to-be-replaced part of the log in patch_log()
7094 patch_sz -= (orig + patch_sz) - (buf + buf_sz) + 1; in patch_log()
7096 } else if (patch_sz - orig_sz > buf_sz - log_sz) { in patch_log()
7098 rem_sz -= (patch_sz - orig_sz) - (buf_sz - log_sz); in patch_log()
7112 /* Expected log for failed and not properly guarded CO-RE relocation: in fixup_log_failed_core_relo()
7113 * line1 -> 123: (85) call unknown#195896080 in fixup_log_failed_core_relo()
7114 * line2 -> invalid func unknown#195896080 in fixup_log_failed_core_relo()
7115 * line3 -> <anything else or end of buffer> in fixup_log_failed_core_relo()
7118 * instruction index to find corresponding CO-RE relocation and in fixup_log_failed_core_relo()
7120 * failed CO-RE relocation. in fixup_log_failed_core_relo()
7134 err = bpf_core_parse_spec(prog->name, prog->obj->btf, relo, &spec); in fixup_log_failed_core_relo()
7140 "%d: <invalid CO-RE relocation>\n" in fixup_log_failed_core_relo()
7141 "failed to resolve CO-RE relocation %s%s\n", in fixup_log_failed_core_relo()
7144 patch_log(buf, buf_sz, log_sz, line1, line3 - line1, patch); in fixup_log_failed_core_relo()
7152 * line1 -> 123: (85) call unknown#2001000345 in fixup_log_missing_map_load()
7153 * line2 -> invalid func unknown#2001000345 in fixup_log_missing_map_load()
7154 * line3 -> <anything else or end of buffer> in fixup_log_missing_map_load()
7157 * "345" in "2001000345" is a map index in obj->maps to fetch map name. in fixup_log_missing_map_load()
7159 struct bpf_object *obj = prog->obj; in fixup_log_missing_map_load()
7167 map_idx -= POISON_LDIMM64_MAP_BASE; in fixup_log_missing_map_load()
7168 if (map_idx < 0 || map_idx >= obj->nr_maps) in fixup_log_missing_map_load()
7170 map = &obj->maps[map_idx]; in fixup_log_missing_map_load()
7175 insn_idx, map->name); in fixup_log_missing_map_load()
7177 patch_log(buf, buf_sz, log_sz, line1, line3 - line1, patch); in fixup_log_missing_map_load()
7185 * line1 -> 123: (85) call unknown#2002000345 in fixup_log_missing_kfunc_call()
7186 * line2 -> invalid func unknown#2002000345 in fixup_log_missing_kfunc_call()
7187 * line3 -> <anything else or end of buffer> in fixup_log_missing_kfunc_call()
7190 * "345" in "2002000345" is an extern index in obj->externs to fetch kfunc name. in fixup_log_missing_kfunc_call()
7192 struct bpf_object *obj = prog->obj; in fixup_log_missing_kfunc_call()
7193 const struct extern_desc *ext; in fixup_log_missing_kfunc_call() local
7200 ext_idx -= POISON_CALL_KFUNC_BASE; in fixup_log_missing_kfunc_call()
7201 if (ext_idx < 0 || ext_idx >= obj->nr_extern) in fixup_log_missing_kfunc_call()
7203 ext = &obj->externs[ext_idx]; in fixup_log_missing_kfunc_call()
7208 insn_idx, ext->name); in fixup_log_missing_kfunc_call()
7210 patch_log(buf, buf_sz, log_sz, line1, line3 - line1, patch); in fixup_log_missing_kfunc_call()
7225 next_line = buf + log_sz - 1; in fixup_verifier_log()
7237 /* failed CO-RE relocation case */ in fixup_verifier_log()
7265 struct bpf_object *obj = prog->obj; in bpf_program_record_relos()
7268 for (i = 0; i < prog->nr_reloc; i++) { in bpf_program_record_relos()
7269 struct reloc_desc *relo = &prog->reloc_desc[i]; in bpf_program_record_relos()
7270 struct extern_desc *ext = &obj->externs[relo->ext_idx]; in bpf_program_record_relos() local
7273 switch (relo->type) { in bpf_program_record_relos()
7275 if (ext->type != EXT_KSYM) in bpf_program_record_relos()
7277 kind = btf_is_var(btf__type_by_id(obj->btf, ext->btf_id)) ? in bpf_program_record_relos()
7279 bpf_gen__record_extern(obj->gen_loader, ext->name, in bpf_program_record_relos()
7280 ext->is_weak, !ext->ksym.type_id, in bpf_program_record_relos()
7281 true, kind, relo->insn_idx); in bpf_program_record_relos()
7284 bpf_gen__record_extern(obj->gen_loader, ext->name, in bpf_program_record_relos()
7285 ext->is_weak, false, false, BTF_KIND_FUNC, in bpf_program_record_relos()
7286 relo->insn_idx); in bpf_program_record_relos()
7290 .insn_off = relo->insn_idx * 8, in bpf_program_record_relos()
7291 .type_id = relo->core_relo->type_id, in bpf_program_record_relos()
7292 .access_str_off = relo->core_relo->access_str_off, in bpf_program_record_relos()
7293 .kind = relo->core_relo->kind, in bpf_program_record_relos()
7296 bpf_gen__record_relo_core(obj->gen_loader, &cr); in bpf_program_record_relos()
7313 for (i = 0; i < obj->nr_programs; i++) { in bpf_object__load_progs()
7314 prog = &obj->programs[i]; in bpf_object__load_progs()
7320 for (i = 0; i < obj->nr_programs; i++) { in bpf_object__load_progs()
7321 prog = &obj->programs[i]; in bpf_object__load_progs()
7324 if (!prog->autoload) { in bpf_object__load_progs()
7325 pr_debug("prog '%s': skipped loading\n", prog->name); in bpf_object__load_progs()
7328 prog->log_level |= log_level; in bpf_object__load_progs()
7330 if (obj->gen_loader) in bpf_object__load_progs()
7333 err = bpf_object_load_prog(obj, prog, prog->insns, prog->insns_cnt, in bpf_object__load_progs()
7334 obj->license, obj->kern_version, &prog->fd); in bpf_object__load_progs()
7336 pr_warn("prog '%s': failed to load: %d\n", prog->name, err); in bpf_object__load_progs()
7353 prog->sec_def = find_sec_def(prog->sec_name); in bpf_object_init_progs()
7354 if (!prog->sec_def) { in bpf_object_init_progs()
7357 prog->name, prog->sec_name); in bpf_object_init_progs()
7361 prog->type = prog->sec_def->prog_type; in bpf_object_init_progs()
7362 prog->expected_attach_type = prog->sec_def->expected_attach_type; in bpf_object_init_progs()
7367 if (prog->sec_def->prog_setup_fn) { in bpf_object_init_progs()
7368 err = prog->sec_def->prog_setup_fn(prog, prog->sec_def->cookie); in bpf_object_init_progs()
7371 prog->name, err); in bpf_object_init_progs()
7394 return ERR_PTR(-LIBBPF_ERRNO__LIBELF); in bpf_object_open()
7398 return ERR_PTR(-EINVAL); in bpf_object_open()
7403 snprintf(tmp_name, sizeof(tmp_name), "%lx-%lx", in bpf_object_open()
7416 return ERR_PTR(-EINVAL); in bpf_object_open()
7418 return ERR_PTR(-EINVAL); in bpf_object_open()
7424 obj->log_buf = log_buf; in bpf_object_open()
7425 obj->log_size = log_size; in bpf_object_open()
7426 obj->log_level = log_level; in bpf_object_open()
7431 err = -ENAMETOOLONG; in bpf_object_open()
7434 obj->btf_custom_path = strdup(btf_tmp_path); in bpf_object_open()
7435 if (!obj->btf_custom_path) { in bpf_object_open()
7436 err = -ENOMEM; in bpf_object_open()
7443 obj->kconfig = strdup(kconfig); in bpf_object_open()
7444 if (!obj->kconfig) { in bpf_object_open()
7445 err = -ENOMEM; in bpf_object_open()
7473 return libbpf_err_ptr(-EINVAL); in bpf_object__open_file()
7490 return libbpf_err_ptr(-EINVAL); in bpf_object__open_mem()
7500 return libbpf_err(-EINVAL); in bpf_object_unload()
7502 for (i = 0; i < obj->nr_maps; i++) { in bpf_object_unload()
7503 zclose(obj->maps[i].fd); in bpf_object_unload()
7504 if (obj->maps[i].st_ops) in bpf_object_unload()
7505 zfree(&obj->maps[i].st_ops->kern_vdata); in bpf_object_unload()
7508 for (i = 0; i < obj->nr_programs; i++) in bpf_object_unload()
7509 bpf_program__unload(&obj->programs[i]); in bpf_object_unload()
7522 m->def.map_flags &= ~BPF_F_MMAPABLE; in bpf_object__sanitize_maps()
7537 err = -errno; in libbpf_kallsyms_parse()
7549 err = -EINVAL; in libbpf_kallsyms_parse()
7567 struct extern_desc *ext; in kallsyms_cb() local
7569 ext = find_extern_by_name(obj, sym_name); in kallsyms_cb()
7570 if (!ext || ext->type != EXT_KSYM) in kallsyms_cb()
7573 t = btf__type_by_id(obj->btf, ext->btf_id); in kallsyms_cb()
7577 if (ext->is_set && ext->ksym.addr != sym_addr) { in kallsyms_cb()
7579 sym_name, ext->ksym.addr, sym_addr); in kallsyms_cb()
7580 return -EINVAL; in kallsyms_cb()
7582 if (!ext->is_set) { in kallsyms_cb()
7583 ext->is_set = true; in kallsyms_cb()
7584 ext->ksym.addr = sym_addr; in kallsyms_cb()
7603 btf = obj->btf_vmlinux; in find_ksym_btf_id()
7607 if (id == -ENOENT) { in find_ksym_btf_id()
7612 for (i = 0; i < obj->btf_module_cnt; i++) { in find_ksym_btf_id()
7614 mod_btf = &obj->btf_modules[i]; in find_ksym_btf_id()
7615 btf = mod_btf->btf; in find_ksym_btf_id()
7617 if (id != -ENOENT) in find_ksym_btf_id()
7622 return -ESRCH; in find_ksym_btf_id()
7630 struct extern_desc *ext) in bpf_object__resolve_ksym_var_btf_id() argument
7639 id = find_ksym_btf_id(obj, ext->name, BTF_KIND_VAR, &btf, &mod_btf); in bpf_object__resolve_ksym_var_btf_id()
7641 if (id == -ESRCH && ext->is_weak) in bpf_object__resolve_ksym_var_btf_id()
7644 ext->name); in bpf_object__resolve_ksym_var_btf_id()
7649 local_type_id = ext->ksym.type_id; in bpf_object__resolve_ksym_var_btf_id()
7653 targ_var_name = btf__name_by_offset(btf, targ_var->name_off); in bpf_object__resolve_ksym_var_btf_id()
7654 targ_type = skip_mods_and_typedefs(btf, targ_var->type, &targ_type_id); in bpf_object__resolve_ksym_var_btf_id()
7656 err = bpf_core_types_are_compat(obj->btf, local_type_id, in bpf_object__resolve_ksym_var_btf_id()
7662 local_type = btf__type_by_id(obj->btf, local_type_id); in bpf_object__resolve_ksym_var_btf_id()
7663 local_name = btf__name_by_offset(obj->btf, local_type->name_off); in bpf_object__resolve_ksym_var_btf_id()
7664 targ_name = btf__name_by_offset(btf, targ_type->name_off); in bpf_object__resolve_ksym_var_btf_id()
7667 ext->name, local_type_id, in bpf_object__resolve_ksym_var_btf_id()
7670 return -EINVAL; in bpf_object__resolve_ksym_var_btf_id()
7673 ext->is_set = true; in bpf_object__resolve_ksym_var_btf_id()
7674 ext->ksym.kernel_btf_obj_fd = mod_btf ? mod_btf->fd : 0; in bpf_object__resolve_ksym_var_btf_id()
7675 ext->ksym.kernel_btf_id = id; in bpf_object__resolve_ksym_var_btf_id()
7677 ext->name, id, btf_kind_str(targ_var), targ_var_name); in bpf_object__resolve_ksym_var_btf_id()
7683 struct extern_desc *ext) in bpf_object__resolve_ksym_func_btf_id() argument
7691 local_func_proto_id = ext->ksym.type_id; in bpf_object__resolve_ksym_func_btf_id()
7693 kfunc_id = find_ksym_btf_id(obj, ext->essent_name ?: ext->name, BTF_KIND_FUNC, &kern_btf, in bpf_object__resolve_ksym_func_btf_id()
7696 if (kfunc_id == -ESRCH && ext->is_weak) in bpf_object__resolve_ksym_func_btf_id()
7699 ext->name); in bpf_object__resolve_ksym_func_btf_id()
7704 kfunc_proto_id = kern_func->type; in bpf_object__resolve_ksym_func_btf_id()
7706 ret = bpf_core_types_are_compat(obj->btf, local_func_proto_id, in bpf_object__resolve_ksym_func_btf_id()
7709 if (ext->is_weak) in bpf_object__resolve_ksym_func_btf_id()
7713 ext->name, local_func_proto_id, in bpf_object__resolve_ksym_func_btf_id()
7714 mod_btf ? mod_btf->name : "vmlinux", kfunc_proto_id); in bpf_object__resolve_ksym_func_btf_id()
7715 return -EINVAL; in bpf_object__resolve_ksym_func_btf_id()
7719 if (mod_btf && !mod_btf->fd_array_idx) { in bpf_object__resolve_ksym_func_btf_id()
7720 /* insn->off is s16 */ in bpf_object__resolve_ksym_func_btf_id()
7721 if (obj->fd_array_cnt == INT16_MAX) { in bpf_object__resolve_ksym_func_btf_id()
7723 ext->name, mod_btf->fd_array_idx); in bpf_object__resolve_ksym_func_btf_id()
7724 return -E2BIG; in bpf_object__resolve_ksym_func_btf_id()
7727 if (!obj->fd_array_cnt) in bpf_object__resolve_ksym_func_btf_id()
7728 obj->fd_array_cnt = 1; in bpf_object__resolve_ksym_func_btf_id()
7730 ret = libbpf_ensure_mem((void **)&obj->fd_array, &obj->fd_array_cap, sizeof(int), in bpf_object__resolve_ksym_func_btf_id()
7731 obj->fd_array_cnt + 1); in bpf_object__resolve_ksym_func_btf_id()
7734 mod_btf->fd_array_idx = obj->fd_array_cnt; in bpf_object__resolve_ksym_func_btf_id()
7736 obj->fd_array[obj->fd_array_cnt++] = mod_btf->fd; in bpf_object__resolve_ksym_func_btf_id()
7739 ext->is_set = true; in bpf_object__resolve_ksym_func_btf_id()
7740 ext->ksym.kernel_btf_id = kfunc_id; in bpf_object__resolve_ksym_func_btf_id()
7741 ext->ksym.btf_fd_idx = mod_btf ? mod_btf->fd_array_idx : 0; in bpf_object__resolve_ksym_func_btf_id()
7744 * {kernel_btf_id, btf_fd_idx} -> fixup bpf_call. in bpf_object__resolve_ksym_func_btf_id()
7745 * {kernel_btf_id, kernel_btf_obj_fd} -> fixup ld_imm64. in bpf_object__resolve_ksym_func_btf_id()
7747 ext->ksym.kernel_btf_obj_fd = mod_btf ? mod_btf->fd : 0; in bpf_object__resolve_ksym_func_btf_id()
7749 ext->name, mod_btf ? mod_btf->name : "vmlinux", kfunc_id); in bpf_object__resolve_ksym_func_btf_id()
7757 struct extern_desc *ext; in bpf_object__resolve_ksyms_btf_id() local
7760 for (i = 0; i < obj->nr_extern; i++) { in bpf_object__resolve_ksyms_btf_id()
7761 ext = &obj->externs[i]; in bpf_object__resolve_ksyms_btf_id()
7762 if (ext->type != EXT_KSYM || !ext->ksym.type_id) in bpf_object__resolve_ksyms_btf_id()
7765 if (obj->gen_loader) { in bpf_object__resolve_ksyms_btf_id()
7766 ext->is_set = true; in bpf_object__resolve_ksyms_btf_id()
7767 ext->ksym.kernel_btf_obj_fd = 0; in bpf_object__resolve_ksyms_btf_id()
7768 ext->ksym.kernel_btf_id = 0; in bpf_object__resolve_ksyms_btf_id()
7771 t = btf__type_by_id(obj->btf, ext->btf_id); in bpf_object__resolve_ksyms_btf_id()
7773 err = bpf_object__resolve_ksym_var_btf_id(obj, ext); in bpf_object__resolve_ksyms_btf_id()
7775 err = bpf_object__resolve_ksym_func_btf_id(obj, ext); in bpf_object__resolve_ksyms_btf_id()
7787 struct extern_desc *ext; in bpf_object__resolve_externs() local
7791 if (obj->nr_extern == 0) in bpf_object__resolve_externs()
7794 if (obj->kconfig_map_idx >= 0) in bpf_object__resolve_externs()
7795 kcfg_data = obj->maps[obj->kconfig_map_idx].mmaped; in bpf_object__resolve_externs()
7797 for (i = 0; i < obj->nr_extern; i++) { in bpf_object__resolve_externs()
7798 ext = &obj->externs[i]; in bpf_object__resolve_externs()
7800 if (ext->type == EXT_KSYM) { in bpf_object__resolve_externs()
7801 if (ext->ksym.type_id) in bpf_object__resolve_externs()
7806 } else if (ext->type == EXT_KCFG) { in bpf_object__resolve_externs()
7807 void *ext_ptr = kcfg_data + ext->kcfg.data_off; in bpf_object__resolve_externs()
7811 if (str_has_pfx(ext->name, "CONFIG_")) { in bpf_object__resolve_externs()
7817 if (strcmp(ext->name, "LINUX_KERNEL_VERSION") == 0) { in bpf_object__resolve_externs()
7820 pr_warn("extern (kcfg) '%s': failed to get kernel version\n", ext->name); in bpf_object__resolve_externs()
7821 return -EINVAL; in bpf_object__resolve_externs()
7823 } else if (strcmp(ext->name, "LINUX_HAS_BPF_COOKIE") == 0) { in bpf_object__resolve_externs()
7825 } else if (strcmp(ext->name, "LINUX_HAS_SYSCALL_WRAPPER") == 0) { in bpf_object__resolve_externs()
7827 } else if (!str_has_pfx(ext->name, "LINUX_") || !ext->is_weak) { in bpf_object__resolve_externs()
7835 pr_warn("extern (kcfg) '%s': unrecognized virtual extern\n", ext->name); in bpf_object__resolve_externs()
7836 return -EINVAL; in bpf_object__resolve_externs()
7839 err = set_kcfg_value_num(ext, ext_ptr, value); in bpf_object__resolve_externs()
7843 ext->name, (long long)value); in bpf_object__resolve_externs()
7845 pr_warn("extern '%s': unrecognized extern kind\n", ext->name); in bpf_object__resolve_externs()
7846 return -EINVAL; in bpf_object__resolve_externs()
7852 return -EINVAL; in bpf_object__resolve_externs()
7854 for (i = 0; i < obj->nr_extern; i++) { in bpf_object__resolve_externs()
7855 ext = &obj->externs[i]; in bpf_object__resolve_externs()
7856 if (ext->type == EXT_KCFG && !ext->is_set) { in bpf_object__resolve_externs()
7865 return -EINVAL; in bpf_object__resolve_externs()
7870 return -EINVAL; in bpf_object__resolve_externs()
7875 return -EINVAL; in bpf_object__resolve_externs()
7877 for (i = 0; i < obj->nr_extern; i++) { in bpf_object__resolve_externs()
7878 ext = &obj->externs[i]; in bpf_object__resolve_externs()
7880 if (!ext->is_set && !ext->is_weak) { in bpf_object__resolve_externs()
7881 pr_warn("extern '%s' (strong): not resolved\n", ext->name); in bpf_object__resolve_externs()
7882 return -ESRCH; in bpf_object__resolve_externs()
7883 } else if (!ext->is_set) { in bpf_object__resolve_externs()
7885 ext->name); in bpf_object__resolve_externs()
7897 st_ops = map->st_ops; in bpf_map_prepare_vdata()
7898 for (i = 0; i < btf_vlen(st_ops->type); i++) { in bpf_map_prepare_vdata()
7899 struct bpf_program *prog = st_ops->progs[i]; in bpf_map_prepare_vdata()
7907 kern_data = st_ops->kern_vdata + st_ops->kern_func_off[i]; in bpf_map_prepare_vdata()
7916 for (i = 0; i < obj->nr_maps; i++) in bpf_object_prepare_struct_ops()
7917 if (bpf_map__is_struct_ops(&obj->maps[i])) in bpf_object_prepare_struct_ops()
7918 bpf_map_prepare_vdata(&obj->maps[i]); in bpf_object_prepare_struct_ops()
7928 return libbpf_err(-EINVAL); in bpf_object_load()
7930 if (obj->loaded) { in bpf_object_load()
7931 pr_warn("object '%s': load can't be attempted twice\n", obj->name); in bpf_object_load()
7932 return libbpf_err(-EINVAL); in bpf_object_load()
7935 if (obj->gen_loader) in bpf_object_load()
7936 bpf_gen__init(obj->gen_loader, extra_log_level, obj->nr_programs, obj->nr_maps); in bpf_object_load()
7940 err = err ? : bpf_object__resolve_externs(obj, obj->kconfig); in bpf_object_load()
7945 err = err ? : bpf_object__relocate(obj, obj->btf_custom_path ? : target_btf_path); in bpf_object_load()
7950 if (obj->gen_loader) { in bpf_object_load()
7952 if (obj->btf) in bpf_object_load()
7953 btf__set_fd(obj->btf, -1); in bpf_object_load()
7954 for (i = 0; i < obj->nr_maps; i++) in bpf_object_load()
7955 obj->maps[i].fd = -1; in bpf_object_load()
7957 err = bpf_gen__finish(obj->gen_loader, obj->nr_programs, obj->nr_maps); in bpf_object_load()
7961 zfree(&obj->fd_array); in bpf_object_load()
7964 for (i = 0; i < obj->btf_module_cnt; i++) { in bpf_object_load()
7965 close(obj->btf_modules[i].fd); in bpf_object_load()
7966 btf__free(obj->btf_modules[i].btf); in bpf_object_load()
7967 free(obj->btf_modules[i].name); in bpf_object_load()
7969 free(obj->btf_modules); in bpf_object_load()
7972 btf__free(obj->btf_vmlinux); in bpf_object_load()
7973 obj->btf_vmlinux = NULL; in bpf_object_load()
7975 obj->loaded = true; /* doesn't matter if successfully or not */ in bpf_object_load()
7982 /* unpin any maps that were auto-pinned during load */ in bpf_object_load()
7983 for (i = 0; i < obj->nr_maps; i++) in bpf_object_load()
7984 if (obj->maps[i].pinned && !obj->maps[i].reused) in bpf_object_load()
7985 bpf_map__unpin(&obj->maps[i], NULL); in bpf_object_load()
7988 pr_warn("failed to load object '%s'\n", obj->path); in bpf_object_load()
8005 return -ENOMEM; in make_parent_dir()
8009 err = -errno; in make_parent_dir()
8013 cp = libbpf_strerror_r(-err, errmsg, sizeof(errmsg)); in make_parent_dir()
8027 return -EINVAL; in check_path()
8031 return -ENOMEM; in check_path()
8037 err = -errno; in check_path()
8043 err = -EINVAL; in check_path()
8054 if (prog->fd < 0) { in bpf_program__pin()
8055 pr_warn("prog '%s': can't pin program that wasn't loaded\n", prog->name); in bpf_program__pin()
8056 return libbpf_err(-EINVAL); in bpf_program__pin()
8067 if (bpf_obj_pin(prog->fd, path)) { in bpf_program__pin()
8068 err = -errno; in bpf_program__pin()
8070 pr_warn("prog '%s': failed to pin at '%s': %s\n", prog->name, path, cp); in bpf_program__pin()
8074 pr_debug("prog '%s': pinned at '%s'\n", prog->name, path); in bpf_program__pin()
8082 if (prog->fd < 0) { in bpf_program__unpin()
8083 pr_warn("prog '%s': can't unpin program that wasn't loaded\n", prog->name); in bpf_program__unpin()
8084 return libbpf_err(-EINVAL); in bpf_program__unpin()
8093 return libbpf_err(-errno); in bpf_program__unpin()
8095 pr_debug("prog '%s': unpinned from '%s'\n", prog->name, path); in bpf_program__unpin()
8106 return libbpf_err(-EINVAL); in bpf_map__pin()
8109 if (map->pin_path) { in bpf_map__pin()
8110 if (path && strcmp(path, map->pin_path)) { in bpf_map__pin()
8112 bpf_map__name(map), map->pin_path, path); in bpf_map__pin()
8113 return libbpf_err(-EINVAL); in bpf_map__pin()
8114 } else if (map->pinned) { in bpf_map__pin()
8115 pr_debug("map '%s' already pinned at '%s'; not re-pinning\n", in bpf_map__pin()
8116 bpf_map__name(map), map->pin_path); in bpf_map__pin()
8123 return libbpf_err(-EINVAL); in bpf_map__pin()
8124 } else if (map->pinned) { in bpf_map__pin()
8126 return libbpf_err(-EEXIST); in bpf_map__pin()
8129 map->pin_path = strdup(path); in bpf_map__pin()
8130 if (!map->pin_path) { in bpf_map__pin()
8131 err = -errno; in bpf_map__pin()
8136 err = make_parent_dir(map->pin_path); in bpf_map__pin()
8140 err = check_path(map->pin_path); in bpf_map__pin()
8144 if (bpf_obj_pin(map->fd, map->pin_path)) { in bpf_map__pin()
8145 err = -errno; in bpf_map__pin()
8149 map->pinned = true; in bpf_map__pin()
8150 pr_debug("pinned map '%s'\n", map->pin_path); in bpf_map__pin()
8155 cp = libbpf_strerror_r(-err, errmsg, sizeof(errmsg)); in bpf_map__pin()
8166 return libbpf_err(-EINVAL); in bpf_map__unpin()
8169 if (map->pin_path) { in bpf_map__unpin()
8170 if (path && strcmp(path, map->pin_path)) { in bpf_map__unpin()
8172 bpf_map__name(map), map->pin_path, path); in bpf_map__unpin()
8173 return libbpf_err(-EINVAL); in bpf_map__unpin()
8175 path = map->pin_path; in bpf_map__unpin()
8179 return libbpf_err(-EINVAL); in bpf_map__unpin()
8188 return libbpf_err(-errno); in bpf_map__unpin()
8190 map->pinned = false; in bpf_map__unpin()
8203 return libbpf_err(-errno); in bpf_map__set_pin_path()
8206 free(map->pin_path); in bpf_map__set_pin_path()
8207 map->pin_path = new; in bpf_map__set_pin_path()
8216 return map->pin_path; in bpf_map__pin_path()
8221 return map->pinned; in bpf_map__is_pinned()
8240 return libbpf_err(-ENOENT); in bpf_object__pin_maps()
8242 if (!obj->loaded) { in bpf_object__pin_maps()
8244 return libbpf_err(-ENOENT); in bpf_object__pin_maps()
8251 if (!map->autocreate) in bpf_object__pin_maps()
8260 } else if (!map->pin_path) { in bpf_object__pin_maps()
8273 if (!map->pin_path) in bpf_object__pin_maps()
8288 return libbpf_err(-ENOENT); in bpf_object__unpin_maps()
8300 } else if (!map->pin_path) { in bpf_object__unpin_maps()
8319 return libbpf_err(-ENOENT); in bpf_object__pin_programs()
8321 if (!obj->loaded) { in bpf_object__pin_programs()
8323 return libbpf_err(-ENOENT); in bpf_object__pin_programs()
8327 err = pathname_concat(buf, sizeof(buf), path, prog->name); in bpf_object__pin_programs()
8340 if (pathname_concat(buf, sizeof(buf), path, prog->name)) in bpf_object__pin_programs()
8355 return libbpf_err(-ENOENT); in bpf_object__unpin_programs()
8360 err = pathname_concat(buf, sizeof(buf), path, prog->name); in bpf_object__unpin_programs()
8406 if (map->inner_map) { in bpf_map__destroy()
8407 bpf_map__destroy(map->inner_map); in bpf_map__destroy()
8408 zfree(&map->inner_map); in bpf_map__destroy()
8411 zfree(&map->init_slots); in bpf_map__destroy()
8412 map->init_slots_sz = 0; in bpf_map__destroy()
8414 if (map->mmaped) { in bpf_map__destroy()
8417 mmap_sz = bpf_map_mmap_sz(map->def.value_size, map->def.max_entries); in bpf_map__destroy()
8418 munmap(map->mmaped, mmap_sz); in bpf_map__destroy()
8419 map->mmaped = NULL; in bpf_map__destroy()
8422 if (map->st_ops) { in bpf_map__destroy()
8423 zfree(&map->st_ops->data); in bpf_map__destroy()
8424 zfree(&map->st_ops->progs); in bpf_map__destroy()
8425 zfree(&map->st_ops->kern_func_off); in bpf_map__destroy()
8426 zfree(&map->st_ops); in bpf_map__destroy()
8429 zfree(&map->name); in bpf_map__destroy()
8430 zfree(&map->real_name); in bpf_map__destroy()
8431 zfree(&map->pin_path); in bpf_map__destroy()
8433 if (map->fd >= 0) in bpf_map__destroy()
8434 zclose(map->fd); in bpf_map__destroy()
8444 usdt_manager_free(obj->usdt_man); in bpf_object__close()
8445 obj->usdt_man = NULL; in bpf_object__close()
8447 bpf_gen__free(obj->gen_loader); in bpf_object__close()
8450 btf__free(obj->btf); in bpf_object__close()
8451 btf__free(obj->btf_vmlinux); in bpf_object__close()
8452 btf_ext__free(obj->btf_ext); in bpf_object__close()
8454 for (i = 0; i < obj->nr_maps; i++) in bpf_object__close()
8455 bpf_map__destroy(&obj->maps[i]); in bpf_object__close()
8457 zfree(&obj->btf_custom_path); in bpf_object__close()
8458 zfree(&obj->kconfig); in bpf_object__close()
8460 for (i = 0; i < obj->nr_extern; i++) in bpf_object__close()
8461 zfree(&obj->externs[i].essent_name); in bpf_object__close()
8463 zfree(&obj->externs); in bpf_object__close()
8464 obj->nr_extern = 0; in bpf_object__close()
8466 zfree(&obj->maps); in bpf_object__close()
8467 obj->nr_maps = 0; in bpf_object__close()
8469 if (obj->programs && obj->nr_programs) { in bpf_object__close()
8470 for (i = 0; i < obj->nr_programs; i++) in bpf_object__close()
8471 bpf_program__exit(&obj->programs[i]); in bpf_object__close()
8473 zfree(&obj->programs); in bpf_object__close()
8480 return obj ? obj->name : libbpf_err_ptr(-EINVAL); in bpf_object__name()
8485 return obj ? obj->kern_version : 0; in bpf_object__kversion()
8490 return obj ? obj->btf : NULL; in bpf_object__btf()
8495 return obj->btf ? btf__fd(obj->btf) : -1; in bpf_object__btf_fd()
8500 if (obj->loaded) in bpf_object__set_kversion()
8501 return libbpf_err(-EINVAL); in bpf_object__set_kversion()
8503 obj->kern_version = kern_version; in bpf_object__set_kversion()
8510 struct bpf_gen *gen; in bpf_object__gen_loader() local
8513 return -EFAULT; in bpf_object__gen_loader()
8515 return -EINVAL; in bpf_object__gen_loader()
8516 gen = calloc(sizeof(*gen), 1); in bpf_object__gen_loader()
8517 if (!gen) in bpf_object__gen_loader()
8518 return -ENOMEM; in bpf_object__gen_loader()
8519 gen->opts = opts; in bpf_object__gen_loader()
8520 obj->gen_loader = gen; in bpf_object__gen_loader()
8528 size_t nr_programs = obj->nr_programs; in __bpf_program__iter()
8536 return forward ? &obj->programs[0] : in __bpf_program__iter()
8537 &obj->programs[nr_programs - 1]; in __bpf_program__iter()
8539 if (p->obj != obj) { in __bpf_program__iter()
8544 idx = (p - obj->programs) + (forward ? 1 : -1); in __bpf_program__iter()
8545 if (idx >= obj->nr_programs || idx < 0) in __bpf_program__iter()
8547 return &obj->programs[idx]; in __bpf_program__iter()
8576 prog->prog_ifindex = ifindex; in bpf_program__set_ifindex()
8581 return prog->name; in bpf_program__name()
8586 return prog->sec_name; in bpf_program__section_name()
8591 return prog->autoload; in bpf_program__autoload()
8596 if (prog->obj->loaded) in bpf_program__set_autoload()
8597 return libbpf_err(-EINVAL); in bpf_program__set_autoload()
8599 prog->autoload = autoload; in bpf_program__set_autoload()
8605 return prog->autoattach; in bpf_program__autoattach()
8610 prog->autoattach = autoattach; in bpf_program__set_autoattach()
8615 return prog->insns; in bpf_program__insns()
8620 return prog->insns_cnt; in bpf_program__insn_cnt()
8628 if (prog->obj->loaded) in bpf_program__set_insns()
8629 return -EBUSY; in bpf_program__set_insns()
8631 insns = libbpf_reallocarray(prog->insns, new_insn_cnt, sizeof(*insns)); in bpf_program__set_insns()
8634 pr_warn("prog '%s': failed to realloc prog code\n", prog->name); in bpf_program__set_insns()
8635 return -ENOMEM; in bpf_program__set_insns()
8639 prog->insns = insns; in bpf_program__set_insns()
8640 prog->insns_cnt = new_insn_cnt; in bpf_program__set_insns()
8647 return libbpf_err(-EINVAL); in bpf_program__fd()
8649 if (prog->fd < 0) in bpf_program__fd()
8650 return libbpf_err(-ENOENT); in bpf_program__fd()
8652 return prog->fd; in bpf_program__fd()
8660 return prog->type; in bpf_program__type()
8671 if (prog->obj->loaded) in bpf_program__set_type()
8672 return libbpf_err(-EBUSY); in bpf_program__set_type()
8675 if (prog->type == type) in bpf_program__set_type()
8678 prog->type = type; in bpf_program__set_type()
8682 * fallback handler, which by definition is program type-agnostic and in bpf_program__set_type()
8683 * is a catch-all custom handler, optionally set by the application, in bpf_program__set_type()
8686 if (prog->sec_def != &custom_fallback_def) in bpf_program__set_type()
8687 prog->sec_def = NULL; in bpf_program__set_type()
8696 return prog->expected_attach_type; in bpf_program__expected_attach_type()
8702 if (prog->obj->loaded) in bpf_program__set_expected_attach_type()
8703 return libbpf_err(-EBUSY); in bpf_program__set_expected_attach_type()
8705 prog->expected_attach_type = type; in bpf_program__set_expected_attach_type()
8711 return prog->prog_flags; in bpf_program__flags()
8716 if (prog->obj->loaded) in bpf_program__set_flags()
8717 return libbpf_err(-EBUSY); in bpf_program__set_flags()
8719 prog->prog_flags = flags; in bpf_program__set_flags()
8725 return prog->log_level; in bpf_program__log_level()
8730 if (prog->obj->loaded) in bpf_program__set_log_level()
8731 return libbpf_err(-EBUSY); in bpf_program__set_log_level()
8733 prog->log_level = log_level; in bpf_program__set_log_level()
8739 *log_size = prog->log_size; in bpf_program__log_buf()
8740 return prog->log_buf; in bpf_program__log_buf()
8746 return -EINVAL; in bpf_program__set_log_buf()
8747 if (prog->log_size > UINT_MAX) in bpf_program__set_log_buf()
8748 return -EINVAL; in bpf_program__set_log_buf()
8749 if (prog->obj->loaded) in bpf_program__set_log_buf()
8750 return -EBUSY; in bpf_program__set_log_buf()
8752 prog->log_buf = log_buf; in bpf_program__set_log_buf()
8753 prog->log_size = log_size; in bpf_program__set_log_buf()
8818 SEC_DEF("freplace+", EXT, 0, SEC_ATTACH_BTF, attach_trace),
8881 return libbpf_err(-EINVAL); in libbpf_register_prog_handler()
8884 return libbpf_err(-E2BIG); in libbpf_register_prog_handler()
8890 return libbpf_err(-ENOMEM); in libbpf_register_prog_handler()
8896 return libbpf_err(-EBUSY); in libbpf_register_prog_handler()
8901 sec_def->sec = sec ? strdup(sec) : NULL; in libbpf_register_prog_handler()
8902 if (sec && !sec_def->sec) in libbpf_register_prog_handler()
8903 return libbpf_err(-ENOMEM); in libbpf_register_prog_handler()
8905 sec_def->prog_type = prog_type; in libbpf_register_prog_handler()
8906 sec_def->expected_attach_type = exp_attach_type; in libbpf_register_prog_handler()
8907 sec_def->cookie = OPTS_GET(opts, cookie, 0); in libbpf_register_prog_handler()
8909 sec_def->prog_setup_fn = OPTS_GET(opts, prog_setup_fn, NULL); in libbpf_register_prog_handler()
8910 sec_def->prog_prepare_load_fn = OPTS_GET(opts, prog_prepare_load_fn, NULL); in libbpf_register_prog_handler()
8911 sec_def->prog_attach_fn = OPTS_GET(opts, prog_attach_fn, NULL); in libbpf_register_prog_handler()
8913 sec_def->handler_id = ++last_custom_sec_def_handler_id; in libbpf_register_prog_handler()
8920 return sec_def->handler_id; in libbpf_register_prog_handler()
8929 return libbpf_err(-EINVAL); in libbpf_unregister_prog_handler()
8943 return libbpf_err(-ENOENT); in libbpf_unregister_prog_handler()
8947 custom_sec_defs[i - 1] = custom_sec_defs[i]; in libbpf_unregister_prog_handler()
8948 custom_sec_def_cnt--; in libbpf_unregister_prog_handler()
8964 size_t len = strlen(sec_def->sec); in sec_def_matches()
8967 if (sec_def->sec[len - 1] == '/') { in sec_def_matches()
8968 if (str_has_pfx(sec_name, sec_def->sec)) in sec_def_matches()
8974 * well-formed SEC("type/extras") with proper '/' separator in sec_def_matches()
8976 if (sec_def->sec[len - 1] == '+') { in sec_def_matches()
8977 len--; in sec_def_matches()
8979 if (strncmp(sec_name, sec_def->sec, len) != 0) in sec_def_matches()
8987 return strcmp(sec_name, sec_def->sec) == 0; in sec_def_matches()
9032 if (sec_def->prog_prepare_load_fn != libbpf_prepare_prog_load) in libbpf_get_type_names()
9035 if (!(sec_def->cookie & SEC_ATTACHABLE)) in libbpf_get_type_names()
9057 return libbpf_err(-EINVAL); in libbpf_prog_type_by_name()
9061 *prog_type = sec_def->prog_type; in libbpf_prog_type_by_name()
9062 *expected_attach_type = sec_def->expected_attach_type; in libbpf_prog_type_by_name()
9073 return libbpf_err(-ESRCH); in libbpf_prog_type_by_name()
9115 for (i = 0; i < obj->nr_maps; i++) { in find_struct_ops_map_by_offset()
9116 map = &obj->maps[i]; in find_struct_ops_map_by_offset()
9119 if (map->sec_idx == sec_idx && in find_struct_ops_map_by_offset()
9120 map->sec_offset <= offset && in find_struct_ops_map_by_offset()
9121 offset - map->sec_offset < map->def.value_size) in find_struct_ops_map_by_offset()
9128 /* Collect the reloc from ELF and populate the st_ops->progs[] */
9145 btf = obj->btf; in bpf_object__collect_st_ops_relos()
9146 nrels = shdr->sh_size / shdr->sh_entsize; in bpf_object__collect_st_ops_relos()
9151 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_st_ops_relos()
9154 sym = elf_sym_by_idx(obj, ELF64_R_SYM(rel->r_info)); in bpf_object__collect_st_ops_relos()
9157 (size_t)ELF64_R_SYM(rel->r_info)); in bpf_object__collect_st_ops_relos()
9158 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_st_ops_relos()
9161 name = elf_sym_str(obj, sym->st_name) ?: "<?>"; in bpf_object__collect_st_ops_relos()
9162 map = find_struct_ops_map_by_offset(obj, shdr->sh_info, rel->r_offset); in bpf_object__collect_st_ops_relos()
9164 pr_warn("struct_ops reloc: cannot find map at rel->r_offset %zu\n", in bpf_object__collect_st_ops_relos()
9165 (size_t)rel->r_offset); in bpf_object__collect_st_ops_relos()
9166 return -EINVAL; in bpf_object__collect_st_ops_relos()
9169 moff = rel->r_offset - map->sec_offset; in bpf_object__collect_st_ops_relos()
9170 shdr_idx = sym->st_shndx; in bpf_object__collect_st_ops_relos()
9171 st_ops = map->st_ops; in bpf_object__collect_st_ops_relos()
9172 …pr_debug("struct_ops reloc %s: for %lld value %lld shdr_idx %u rel->r_offset %zu map->sec_offset %… in bpf_object__collect_st_ops_relos()
9173 map->name, in bpf_object__collect_st_ops_relos()
9174 (long long)(rel->r_info >> 32), in bpf_object__collect_st_ops_relos()
9175 (long long)sym->st_value, in bpf_object__collect_st_ops_relos()
9176 shdr_idx, (size_t)rel->r_offset, in bpf_object__collect_st_ops_relos()
9177 map->sec_offset, sym->st_name, name); in bpf_object__collect_st_ops_relos()
9180 pr_warn("struct_ops reloc %s: rel->r_offset %zu shdr_idx %u unsupported non-static function\n", in bpf_object__collect_st_ops_relos()
9181 map->name, (size_t)rel->r_offset, shdr_idx); in bpf_object__collect_st_ops_relos()
9182 return -LIBBPF_ERRNO__RELOC; in bpf_object__collect_st_ops_relos()
9184 if (sym->st_value % BPF_INSN_SZ) { in bpf_object__collect_st_ops_relos()
9186 map->name, (unsigned long long)sym->st_value); in bpf_object__collect_st_ops_relos()
9187 return -LIBBPF_ERRNO__FORMAT; in bpf_object__collect_st_ops_relos()
9189 insn_idx = sym->st_value / BPF_INSN_SZ; in bpf_object__collect_st_ops_relos()
9191 member = find_member_by_offset(st_ops->type, moff * 8); in bpf_object__collect_st_ops_relos()
9194 map->name, moff); in bpf_object__collect_st_ops_relos()
9195 return -EINVAL; in bpf_object__collect_st_ops_relos()
9197 member_idx = member - btf_members(st_ops->type); in bpf_object__collect_st_ops_relos()
9198 name = btf__name_by_offset(btf, member->name_off); in bpf_object__collect_st_ops_relos()
9200 if (!resolve_func_ptr(btf, member->type, NULL)) { in bpf_object__collect_st_ops_relos()
9202 map->name, name); in bpf_object__collect_st_ops_relos()
9203 return -EINVAL; in bpf_object__collect_st_ops_relos()
9209 map->name, shdr_idx, name); in bpf_object__collect_st_ops_relos()
9210 return -EINVAL; in bpf_object__collect_st_ops_relos()
9214 if (prog->type != BPF_PROG_TYPE_STRUCT_OPS) { in bpf_object__collect_st_ops_relos()
9216 map->name, prog->name); in bpf_object__collect_st_ops_relos()
9217 return -EINVAL; in bpf_object__collect_st_ops_relos()
9223 if (!prog->attach_btf_id) { in bpf_object__collect_st_ops_relos()
9224 prog->attach_btf_id = st_ops->type_id; in bpf_object__collect_st_ops_relos()
9225 prog->expected_attach_type = member_idx; in bpf_object__collect_st_ops_relos()
9228 /* struct_ops BPF prog can be re-used between multiple in bpf_object__collect_st_ops_relos()
9233 if (prog->attach_btf_id != st_ops->type_id || in bpf_object__collect_st_ops_relos()
9234 prog->expected_attach_type != member_idx) { in bpf_object__collect_st_ops_relos()
9236 map->name, prog->name, prog->sec_name, prog->type, in bpf_object__collect_st_ops_relos()
9237 prog->attach_btf_id, prog->expected_attach_type, name); in bpf_object__collect_st_ops_relos()
9238 return -EINVAL; in bpf_object__collect_st_ops_relos()
9241 st_ops->progs[member_idx] = prog; in bpf_object__collect_st_ops_relos()
9288 return -ENAMETOOLONG; in find_btf_by_prefix_kind()
9338 err = -EINVAL; in libbpf_find_prog_btf_id()
9365 ret = find_attach_btf_id(obj->btf_vmlinux, attach_name, attach_type); in find_kernel_btf_id()
9371 if (ret != -ENOENT) in find_kernel_btf_id()
9378 for (i = 0; i < obj->btf_module_cnt; i++) { in find_kernel_btf_id()
9379 const struct module_btf *mod = &obj->btf_modules[i]; in find_kernel_btf_id()
9381 ret = find_attach_btf_id(mod->btf, attach_name, attach_type); in find_kernel_btf_id()
9383 *btf_obj_fd = mod->fd; in find_kernel_btf_id()
9387 if (ret == -ENOENT) in find_kernel_btf_id()
9393 return -ESRCH; in find_kernel_btf_id()
9399 enum bpf_attach_type attach_type = prog->expected_attach_type; in libbpf_find_attach_btf_id()
9400 __u32 attach_prog_fd = prog->attach_prog_fd; in libbpf_find_attach_btf_id()
9404 if (prog->type == BPF_PROG_TYPE_EXT || attach_prog_fd) { in libbpf_find_attach_btf_id()
9406 pr_warn("prog '%s': attach program FD is not set\n", prog->name); in libbpf_find_attach_btf_id()
9407 return -EINVAL; in libbpf_find_attach_btf_id()
9412 prog->name, attach_prog_fd, attach_name, err); in libbpf_find_attach_btf_id()
9421 if (prog->obj->gen_loader) { in libbpf_find_attach_btf_id()
9422 bpf_gen__record_attach_target(prog->obj->gen_loader, attach_name, attach_type); in libbpf_find_attach_btf_id()
9426 err = find_kernel_btf_id(prog->obj, attach_name, attach_type, btf_obj_fd, btf_type_id); in libbpf_find_attach_btf_id()
9430 prog->name, attach_name, err); in libbpf_find_attach_btf_id()
9443 return libbpf_err(-EINVAL); in libbpf_attach_type_by_name()
9454 return libbpf_err(-EINVAL); in libbpf_attach_type_by_name()
9457 if (sec_def->prog_prepare_load_fn != libbpf_prepare_prog_load) in libbpf_attach_type_by_name()
9458 return libbpf_err(-EINVAL); in libbpf_attach_type_by_name()
9459 if (!(sec_def->cookie & SEC_ATTACHABLE)) in libbpf_attach_type_by_name()
9460 return libbpf_err(-EINVAL); in libbpf_attach_type_by_name()
9462 *attach_type = sec_def->expected_attach_type; in libbpf_attach_type_by_name()
9468 return map ? map->fd : libbpf_err(-EINVAL); in bpf_map__fd()
9474 * their user-visible name differs from kernel-visible name. Users see in map_uses_real_name()
9479 if (map->libbpf_type == LIBBPF_MAP_DATA && strcmp(map->real_name, DATA_SEC) != 0) in map_uses_real_name()
9481 if (map->libbpf_type == LIBBPF_MAP_RODATA && strcmp(map->real_name, RODATA_SEC) != 0) in map_uses_real_name()
9492 return map->real_name; in bpf_map__name()
9494 return map->name; in bpf_map__name()
9499 return map->def.type; in bpf_map__type()
9504 if (map->fd >= 0) in bpf_map__set_type()
9505 return libbpf_err(-EBUSY); in bpf_map__set_type()
9506 map->def.type = type; in bpf_map__set_type()
9512 return map->def.map_flags; in bpf_map__map_flags()
9517 if (map->fd >= 0) in bpf_map__set_map_flags()
9518 return libbpf_err(-EBUSY); in bpf_map__set_map_flags()
9519 map->def.map_flags = flags; in bpf_map__set_map_flags()
9525 return map->map_extra; in bpf_map__map_extra()
9530 if (map->fd >= 0) in bpf_map__set_map_extra()
9531 return libbpf_err(-EBUSY); in bpf_map__set_map_extra()
9532 map->map_extra = map_extra; in bpf_map__set_map_extra()
9538 return map->numa_node; in bpf_map__numa_node()
9543 if (map->fd >= 0) in bpf_map__set_numa_node()
9544 return libbpf_err(-EBUSY); in bpf_map__set_numa_node()
9545 map->numa_node = numa_node; in bpf_map__set_numa_node()
9551 return map->def.key_size; in bpf_map__key_size()
9556 if (map->fd >= 0) in bpf_map__set_key_size()
9557 return libbpf_err(-EBUSY); in bpf_map__set_key_size()
9558 map->def.key_size = size; in bpf_map__set_key_size()
9564 return map->def.value_size; in bpf_map__value_size()
9578 btf = bpf_object__btf(map->obj); in map_btf_datasec_resize()
9580 return -ENOENT; in map_btf_datasec_resize()
9587 return -EINVAL; in map_btf_datasec_resize()
9595 return -EINVAL; in map_btf_datasec_resize()
9599 var = &btf_var_secinfos(datasec_type)[vlen - 1]; in map_btf_datasec_resize()
9600 var_type = btf_type_by_id(btf, var->type); in map_btf_datasec_resize()
9601 array_type = skip_mods_and_typedefs(btf, var_type->type, NULL); in map_btf_datasec_resize()
9605 return -EINVAL; in map_btf_datasec_resize()
9610 element_sz = btf__resolve_size(btf, array->type); in map_btf_datasec_resize()
9611 if (element_sz <= 0 || (size - var->offset) % element_sz != 0) { in map_btf_datasec_resize()
9614 return -EINVAL; in map_btf_datasec_resize()
9618 nr_elements = (size - var->offset) / element_sz; in map_btf_datasec_resize()
9619 new_array_id = btf__add_array(btf, array->index_type, array->type, nr_elements); in map_btf_datasec_resize()
9626 datasec_type = btf_type_by_id(btf, map->btf_value_type_id); in map_btf_datasec_resize()
9627 var = &btf_var_secinfos(datasec_type)[vlen - 1]; in map_btf_datasec_resize()
9628 var_type = btf_type_by_id(btf, var->type); in map_btf_datasec_resize()
9631 datasec_type->size = size; in map_btf_datasec_resize()
9632 var->size = size - var->offset; in map_btf_datasec_resize()
9633 var_type->type = new_array_id; in map_btf_datasec_resize()
9640 if (map->fd >= 0) in bpf_map__set_value_size()
9641 return libbpf_err(-EBUSY); in bpf_map__set_value_size()
9643 if (map->mmaped) { in bpf_map__set_value_size()
9647 mmap_old_sz = bpf_map_mmap_sz(map->def.value_size, map->def.max_entries); in bpf_map__set_value_size()
9648 mmap_new_sz = bpf_map_mmap_sz(size, map->def.max_entries); in bpf_map__set_value_size()
9651 pr_warn("map '%s': failed to resize memory-mapped region: %d\n", in bpf_map__set_value_size()
9656 if (err && err != -ENOENT) { in bpf_map__set_value_size()
9659 map->btf_value_type_id = 0; in bpf_map__set_value_size()
9660 map->btf_key_type_id = 0; in bpf_map__set_value_size()
9664 map->def.value_size = size; in bpf_map__set_value_size()
9670 return map ? map->btf_key_type_id : 0; in bpf_map__btf_key_type_id()
9675 return map ? map->btf_value_type_id : 0; in bpf_map__btf_value_type_id()
9681 if (!map->mmaped || map->libbpf_type == LIBBPF_MAP_KCONFIG || in bpf_map__set_initial_value()
9682 size != map->def.value_size || map->fd >= 0) in bpf_map__set_initial_value()
9683 return libbpf_err(-EINVAL); in bpf_map__set_initial_value()
9685 memcpy(map->mmaped, data, size); in bpf_map__set_initial_value()
9691 if (!map->mmaped) in bpf_map__initial_value()
9693 *psize = map->def.value_size; in bpf_map__initial_value()
9694 return map->mmaped; in bpf_map__initial_value()
9699 return map->libbpf_type != LIBBPF_MAP_UNSPEC; in bpf_map__is_internal()
9704 return map->map_ifindex; in bpf_map__ifindex()
9709 if (map->fd >= 0) in bpf_map__set_ifindex()
9710 return libbpf_err(-EBUSY); in bpf_map__set_ifindex()
9711 map->map_ifindex = ifindex; in bpf_map__set_ifindex()
9717 if (!bpf_map_type__is_map_in_map(map->def.type)) { in bpf_map__set_inner_map_fd()
9719 return libbpf_err(-EINVAL); in bpf_map__set_inner_map_fd()
9721 if (map->inner_map_fd != -1) { in bpf_map__set_inner_map_fd()
9723 return libbpf_err(-EINVAL); in bpf_map__set_inner_map_fd()
9725 if (map->inner_map) { in bpf_map__set_inner_map_fd()
9726 bpf_map__destroy(map->inner_map); in bpf_map__set_inner_map_fd()
9727 zfree(&map->inner_map); in bpf_map__set_inner_map_fd()
9729 map->inner_map_fd = fd; in bpf_map__set_inner_map_fd()
9739 if (!obj || !obj->maps) in __bpf_map__iter()
9742 s = obj->maps; in __bpf_map__iter()
9743 e = obj->maps + obj->nr_maps; in __bpf_map__iter()
9751 idx = (m - obj->maps) + i; in __bpf_map__iter()
9752 if (idx >= obj->nr_maps || idx < 0) in __bpf_map__iter()
9754 return &obj->maps[idx]; in __bpf_map__iter()
9761 return obj->maps; in bpf_object__next_map()
9770 if (!obj->nr_maps) in bpf_object__prev_map()
9772 return obj->maps + obj->nr_maps - 1; in bpf_object__prev_map()
9775 return __bpf_map__iter(next, obj, -1); in bpf_object__prev_map()
9789 if (pos->real_name && strcmp(pos->real_name, name) == 0) in bpf_object__find_map_by_name()
9795 if (strcmp(pos->real_name, name) == 0) in bpf_object__find_map_by_name()
9799 if (strcmp(pos->name, name) == 0) in bpf_object__find_map_by_name()
9814 if (map->fd <= 0) in validate_map_op()
9815 return -ENOENT; in validate_map_op()
9817 if (map->def.key_size != key_sz) { in validate_map_op()
9819 map->name, key_sz, map->def.key_size); in validate_map_op()
9820 return -EINVAL; in validate_map_op()
9826 switch (map->def.type) { in validate_map_op()
9832 size_t elem_sz = roundup(map->def.value_size, 8); in validate_map_op()
9835 … pr_warn("map '%s': unexpected value size %zu provided for per-CPU map, expected %d * %zu = %zd\n", in validate_map_op()
9836 map->name, value_sz, num_cpu, elem_sz, num_cpu * elem_sz); in validate_map_op()
9837 return -EINVAL; in validate_map_op()
9842 if (map->def.value_size != value_sz) { in validate_map_op()
9844 map->name, value_sz, map->def.value_size); in validate_map_op()
9845 return -EINVAL; in validate_map_op()
9862 return bpf_map_lookup_elem_flags(map->fd, key, value, flags); in bpf_map__lookup_elem()
9875 return bpf_map_update_elem(map->fd, key, value, flags); in bpf_map__update_elem()
9887 return bpf_map_delete_elem_flags(map->fd, key, flags); in bpf_map__delete_elem()
9900 return bpf_map_lookup_and_delete_elem_flags(map->fd, key, value, flags); in bpf_map__lookup_and_delete_elem()
9912 return bpf_map_get_next_key(map->fd, cur_key, next_key); in bpf_map__get_next_key()
9921 errno = -PTR_ERR(ptr); in libbpf_get_error()
9928 return -errno; in libbpf_get_error()
9952 link->disconnected = true; in bpf_link__disconnect()
9962 if (!link->disconnected && link->detach) in bpf_link__destroy()
9963 err = link->detach(link); in bpf_link__destroy()
9964 if (link->pin_path) in bpf_link__destroy()
9965 free(link->pin_path); in bpf_link__destroy()
9966 if (link->dealloc) in bpf_link__destroy()
9967 link->dealloc(link); in bpf_link__destroy()
9976 return link->fd; in bpf_link__fd()
9981 return link->pin_path; in bpf_link__pin_path()
9986 return libbpf_err_errno(close(link->fd)); in bpf_link__detach_fd()
9996 fd = -errno; in bpf_link__open()
10004 return libbpf_err_ptr(-ENOMEM); in bpf_link__open()
10006 link->detach = &bpf_link__detach_fd; in bpf_link__open()
10007 link->fd = fd; in bpf_link__open()
10009 link->pin_path = strdup(path); in bpf_link__open()
10010 if (!link->pin_path) { in bpf_link__open()
10012 return libbpf_err_ptr(-ENOMEM); in bpf_link__open()
10020 return bpf_link_detach(link->fd) ? -errno : 0; in bpf_link__detach()
10027 if (link->pin_path) in bpf_link__pin()
10028 return libbpf_err(-EBUSY); in bpf_link__pin()
10036 link->pin_path = strdup(path); in bpf_link__pin()
10037 if (!link->pin_path) in bpf_link__pin()
10038 return libbpf_err(-ENOMEM); in bpf_link__pin()
10040 if (bpf_obj_pin(link->fd, link->pin_path)) { in bpf_link__pin()
10041 err = -errno; in bpf_link__pin()
10042 zfree(&link->pin_path); in bpf_link__pin()
10046 pr_debug("link fd=%d: pinned at %s\n", link->fd, link->pin_path); in bpf_link__pin()
10054 if (!link->pin_path) in bpf_link__unpin()
10055 return libbpf_err(-EINVAL); in bpf_link__unpin()
10057 err = unlink(link->pin_path); in bpf_link__unpin()
10059 return -errno; in bpf_link__unpin()
10061 pr_debug("link fd=%d: unpinned from %s\n", link->fd, link->pin_path); in bpf_link__unpin()
10062 zfree(&link->pin_path); in bpf_link__unpin()
10083 if (ioctl(perf_link->perf_event_fd, PERF_EVENT_IOC_DISABLE, 0) < 0) in bpf_link_perf_detach()
10084 err = -errno; in bpf_link_perf_detach()
10086 if (perf_link->perf_event_fd != link->fd) in bpf_link_perf_detach()
10087 close(perf_link->perf_event_fd); in bpf_link_perf_detach()
10088 close(link->fd); in bpf_link_perf_detach()
10091 if (perf_link->legacy_probe_name) { in bpf_link_perf_detach()
10092 if (perf_link->legacy_is_kprobe) { in bpf_link_perf_detach()
10093 err = remove_kprobe_event_legacy(perf_link->legacy_probe_name, in bpf_link_perf_detach()
10094 perf_link->legacy_is_retprobe); in bpf_link_perf_detach()
10096 err = remove_uprobe_event_legacy(perf_link->legacy_probe_name, in bpf_link_perf_detach()
10097 perf_link->legacy_is_retprobe); in bpf_link_perf_detach()
10108 free(perf_link->legacy_probe_name); in bpf_link_perf_dealloc()
10117 int prog_fd, link_fd = -1, err; in bpf_program__attach_perf_event_opts()
10121 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_perf_event_opts()
10125 prog->name, pfd); in bpf_program__attach_perf_event_opts()
10126 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_perf_event_opts()
10131 prog->name); in bpf_program__attach_perf_event_opts()
10132 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_perf_event_opts()
10137 return libbpf_err_ptr(-ENOMEM); in bpf_program__attach_perf_event_opts()
10138 link->link.detach = &bpf_link_perf_detach; in bpf_program__attach_perf_event_opts()
10139 link->link.dealloc = &bpf_link_perf_dealloc; in bpf_program__attach_perf_event_opts()
10140 link->perf_event_fd = pfd; in bpf_program__attach_perf_event_opts()
10143 if (kernel_supports(prog->obj, FEAT_PERF_LINK) && !force_ioctl_attach) { in bpf_program__attach_perf_event_opts()
10149 err = -errno; in bpf_program__attach_perf_event_opts()
10151 prog->name, pfd, in bpf_program__attach_perf_event_opts()
10155 link->link.fd = link_fd; in bpf_program__attach_perf_event_opts()
10158 pr_warn("prog '%s': user context value is not supported\n", prog->name); in bpf_program__attach_perf_event_opts()
10159 err = -EOPNOTSUPP; in bpf_program__attach_perf_event_opts()
10164 err = -errno; in bpf_program__attach_perf_event_opts()
10166 prog->name, pfd, libbpf_strerror_r(err, errmsg, sizeof(errmsg))); in bpf_program__attach_perf_event_opts()
10167 if (err == -EPROTO) in bpf_program__attach_perf_event_opts()
10169 prog->name, pfd); in bpf_program__attach_perf_event_opts()
10172 link->link.fd = pfd; in bpf_program__attach_perf_event_opts()
10175 err = -errno; in bpf_program__attach_perf_event_opts()
10177 prog->name, pfd, libbpf_strerror_r(err, errmsg, sizeof(errmsg))); in bpf_program__attach_perf_event_opts()
10181 return &link->link; in bpf_program__attach_perf_event_opts()
10195 * this function is expected to parse integer in the range of [0, 2^31-1] from
10207 err = -errno; in parse_uint_from_file()
10214 err = err == EOF ? -EIO : -errno; in parse_uint_from_file()
10264 return -EINVAL; in perf_event_open_probe()
10296 pid < 0 ? -1 : pid /* pid */, in perf_event_open_probe()
10297 pid == -1 ? 0 : -1 /* cpu */, in perf_event_open_probe()
10298 -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC); in perf_event_open_probe()
10299 return pfd >= 0 ? pfd : -errno; in perf_event_open_probe()
10313 return -EINVAL; in append_to_file()
10317 return -errno; in append_to_file()
10320 err = -errno; in append_to_file()
10331 static int has_debugfs = -1; in use_debugfs()
10393 return append_to_file(tracefs_kprobe_events(), "-:%s/%s", in remove_kprobe_event_legacy()
10437 pid < 0 ? -1 : pid, /* pid */ in perf_event_kprobe_open_legacy()
10438 pid == -1 ? 0 : -1, /* cpu */ in perf_event_kprobe_open_legacy()
10439 -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC); in perf_event_kprobe_open_legacy()
10441 err = -errno; in perf_event_kprobe_open_legacy()
10527 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_kprobe_opts()
10542 return libbpf_err_ptr(-ENOTSUP); in bpf_program__attach_kprobe_opts()
10546 if (legacy || !kernel_supports(prog->obj, FEAT_PERF_LINK)) in bpf_program__attach_kprobe_opts()
10547 return libbpf_err_ptr(-ENOTSUP); in bpf_program__attach_kprobe_opts()
10552 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_kprobe_opts()
10558 -1 /* pid */, 0 /* ref_ctr_off */); in bpf_program__attach_kprobe_opts()
10567 return libbpf_err_ptr(-ENOMEM); in bpf_program__attach_kprobe_opts()
10570 offset, -1 /* pid */); in bpf_program__attach_kprobe_opts()
10573 err = -errno; in bpf_program__attach_kprobe_opts()
10575 prog->name, retprobe ? "kretprobe" : "kprobe", in bpf_program__attach_kprobe_opts()
10585 prog->name, retprobe ? "kretprobe" : "kprobe", in bpf_program__attach_kprobe_opts()
10593 perf_link->legacy_probe_name = legacy_probe; in bpf_program__attach_kprobe_opts()
10594 perf_link->legacy_is_kprobe = true; in bpf_program__attach_kprobe_opts()
10595 perf_link->legacy_is_retprobe = retprobe; in bpf_program__attach_kprobe_opts()
10627 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_ksyscall()
10629 if (kernel_supports(prog->obj, FEAT_SYSCALL_WRAPPER)) { in bpf_program__attach_ksyscall()
10696 struct kprobe_multi_resolve *res = data->res; in avail_kallsyms_cb()
10699 if (!bsearch(&sym_name, data->syms, data->cnt, sizeof(*data->syms), avail_func_cmp)) in avail_kallsyms_cb()
10702 err = libbpf_ensure_mem((void **)&res->addrs, &res->cap, sizeof(*res->addrs), res->cnt + 1); in avail_kallsyms_cb()
10706 res->addrs[res->cnt++] = (unsigned long)sym_addr; in avail_kallsyms_cb()
10722 err = -errno; in libbpf_available_kallsyms_parse()
10736 err = -EINVAL; in libbpf_available_kallsyms_parse()
10740 if (!glob_match(sym_name, res->pattern)) in libbpf_available_kallsyms_parse()
10749 err = -errno; in libbpf_available_kallsyms_parse()
10758 err = -ENOENT; in libbpf_available_kallsyms_parse()
10770 if (res->cnt == 0) in libbpf_available_kallsyms_parse()
10771 err = -ENOENT; in libbpf_available_kallsyms_parse()
10784 return access(tracefs_available_filter_functions_addrs(), R_OK) != -1; in has_available_filter_functions_addrs()
10797 err = -errno; in libbpf_available_kprobes_parse()
10810 err = -EINVAL; in libbpf_available_kprobes_parse()
10814 if (!glob_match(sym_name, res->pattern)) in libbpf_available_kprobes_parse()
10817 err = libbpf_ensure_mem((void **)&res->addrs, &res->cap, in libbpf_available_kprobes_parse()
10818 sizeof(*res->addrs), res->cnt + 1); in libbpf_available_kprobes_parse()
10822 res->addrs[res->cnt++] = (unsigned long)sym_addr; in libbpf_available_kprobes_parse()
10825 if (res->cnt == 0) in libbpf_available_kprobes_parse()
10826 err = -ENOENT; in libbpf_available_kprobes_parse()
10852 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_kprobe_multi_opts()
10860 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_kprobe_multi_opts()
10862 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_kprobe_multi_opts()
10864 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_kprobe_multi_opts()
10866 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_kprobe_multi_opts()
10889 err = -ENOMEM; in bpf_program__attach_kprobe_multi_opts()
10892 link->detach = &bpf_link__detach_fd; in bpf_program__attach_kprobe_multi_opts()
10897 err = -errno; in bpf_program__attach_kprobe_multi_opts()
10899 prog->name, libbpf_strerror_r(err, errmsg, sizeof(errmsg))); in bpf_program__attach_kprobe_multi_opts()
10902 link->fd = link_fd; in bpf_program__attach_kprobe_multi_opts()
10922 /* no auto-attach for SEC("kprobe") and SEC("kretprobe") */ in attach_kprobe()
10923 if (strcmp(prog->sec_name, "kprobe") == 0 || strcmp(prog->sec_name, "kretprobe") == 0) in attach_kprobe()
10926 opts.retprobe = str_has_pfx(prog->sec_name, "kretprobe/"); in attach_kprobe()
10928 func_name = prog->sec_name + sizeof("kretprobe/") - 1; in attach_kprobe()
10930 func_name = prog->sec_name + sizeof("kprobe/") - 1; in attach_kprobe()
10932 n = sscanf(func_name, "%m[a-zA-Z0-9_.]+%li", &func, &offset); in attach_kprobe()
10935 return -EINVAL; in attach_kprobe()
10940 return -EINVAL; in attach_kprobe()
10956 /* no auto-attach for SEC("ksyscall") and SEC("kretsyscall") */ in attach_ksyscall()
10957 if (strcmp(prog->sec_name, "ksyscall") == 0 || strcmp(prog->sec_name, "kretsyscall") == 0) in attach_ksyscall()
10960 opts.retprobe = str_has_pfx(prog->sec_name, "kretsyscall/"); in attach_ksyscall()
10962 syscall_name = prog->sec_name + sizeof("kretsyscall/") - 1; in attach_ksyscall()
10964 syscall_name = prog->sec_name + sizeof("ksyscall/") - 1; in attach_ksyscall()
10967 return *link ? 0 : -errno; in attach_ksyscall()
10979 /* no auto-attach for SEC("kprobe.multi") and SEC("kretprobe.multi") */ in attach_kprobe_multi()
10980 if (strcmp(prog->sec_name, "kprobe.multi") == 0 || in attach_kprobe_multi()
10981 strcmp(prog->sec_name, "kretprobe.multi") == 0) in attach_kprobe_multi()
10984 opts.retprobe = str_has_pfx(prog->sec_name, "kretprobe.multi/"); in attach_kprobe_multi()
10986 spec = prog->sec_name + sizeof("kretprobe.multi/") - 1; in attach_kprobe_multi()
10988 spec = prog->sec_name + sizeof("kprobe.multi/") - 1; in attach_kprobe_multi()
10990 n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern); in attach_kprobe_multi()
10993 return -EINVAL; in attach_kprobe_multi()
11005 int n, ret = -EINVAL; in attach_uprobe_multi()
11009 n = sscanf(prog->sec_name, "%m[^/]/%m[^:]:%ms", in attach_uprobe_multi()
11013 /* handle SEC("u[ret]probe") - format is valid, but auto-attach is impossible. */ in attach_uprobe_multi()
11018 *link = bpf_program__attach_uprobe_multi(prog, -1, binary_path, func_name, &opts); in attach_uprobe_multi()
11022 pr_warn("prog '%s': invalid format of section definition '%s'\n", prog->name, in attach_uprobe_multi()
11023 prog->sec_name); in attach_uprobe_multi()
11057 return append_to_file(tracefs_uprobe_events(), "-:%s/%s", in remove_uprobe_event_legacy()
11098 pid < 0 ? -1 : pid, /* pid */ in perf_event_uprobe_open_legacy()
11099 pid == -1 ? 0 : -1, /* cpu */ in perf_event_uprobe_open_legacy()
11100 -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC); in perf_event_uprobe_open_legacy()
11102 err = -errno; in perf_event_uprobe_open_legacy()
11150 ret = -LIBBPF_ERRNO__FORMAT; in elf_find_func_offset_from_archive()
11157 elf_errmsg(-1)); in elf_find_func_offset_from_archive()
11158 ret = -LIBBPF_ERRNO__LIBELF; in elf_find_func_offset_from_archive()
11185 return "/lib/x86_64-linux-gnu"; in arch_specific_lib_paths()
11187 return "/lib/i386-linux-gnu"; in arch_specific_lib_paths()
11189 return "/lib/s390x-linux-gnu"; in arch_specific_lib_paths()
11191 return "/lib/s390-linux-gnu"; in arch_specific_lib_paths()
11193 return "/lib/arm-linux-gnueabi"; in arch_specific_lib_paths()
11195 return "/lib/arm-linux-gnueabihf"; in arch_specific_lib_paths()
11197 return "/lib/aarch64-linux-gnu"; in arch_specific_lib_paths()
11199 return "/lib/mips64el-linux-gnuabi64"; in arch_specific_lib_paths()
11201 return "/lib/mipsel-linux-gnu"; in arch_specific_lib_paths()
11203 return "/lib/powerpc64le-linux-gnu"; in arch_specific_lib_paths()
11205 return "/lib/sparc64-linux-gnu"; in arch_specific_lib_paths()
11207 return "/lib/riscv64-linux-gnu"; in arch_specific_lib_paths()
11242 seg_len = next_path ? next_path - s : strlen(s); in resolve_full_path()
11253 return -ENOENT; in resolve_full_path()
11275 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_uprobe_multi()
11291 * - syms and offsets are mutually exclusive in bpf_program__attach_uprobe_multi()
11292 * - ref_ctr_offsets and cookies are optional in bpf_program__attach_uprobe_multi()
11298 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_uprobe_multi()
11300 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_uprobe_multi()
11304 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_uprobe_multi()
11307 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_uprobe_multi()
11315 prog->name, path, err); in bpf_program__attach_uprobe_multi()
11347 err = -ENOMEM; in bpf_program__attach_uprobe_multi()
11350 link->detach = &bpf_link__detach_fd; in bpf_program__attach_uprobe_multi()
11355 err = -errno; in bpf_program__attach_uprobe_multi()
11356 pr_warn("prog '%s': failed to attach multi-uprobe: %s\n", in bpf_program__attach_uprobe_multi()
11357 prog->name, libbpf_strerror_r(err, errmsg, sizeof(errmsg))); in bpf_program__attach_uprobe_multi()
11360 link->fd = link_fd; in bpf_program__attach_uprobe_multi()
11387 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_uprobe_opts()
11395 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_uprobe_opts()
11402 min(sizeof(full_path), (size_t)(archive_sep - binary_path + 1))); in bpf_program__attach_uprobe_opts()
11409 prog->name, binary_path, err); in bpf_program__attach_uprobe_opts()
11438 return libbpf_err_ptr(-ENOTSUP); in bpf_program__attach_uprobe_opts()
11442 if (legacy || !kernel_supports(prog->obj, FEAT_PERF_LINK)) in bpf_program__attach_uprobe_opts()
11443 return libbpf_err_ptr(-ENOTSUP); in bpf_program__attach_uprobe_opts()
11448 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_uprobe_opts()
11458 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_uprobe_opts()
11465 return libbpf_err_ptr(-ENOMEM); in bpf_program__attach_uprobe_opts()
11471 err = -errno; in bpf_program__attach_uprobe_opts()
11473 prog->name, retprobe ? "uretprobe" : "uprobe", in bpf_program__attach_uprobe_opts()
11484 prog->name, retprobe ? "uretprobe" : "uprobe", in bpf_program__attach_uprobe_opts()
11492 perf_link->legacy_probe_name = legacy_probe; in bpf_program__attach_uprobe_opts()
11493 perf_link->legacy_is_kprobe = false; in bpf_program__attach_uprobe_opts()
11494 perf_link->legacy_is_retprobe = retprobe; in bpf_program__attach_uprobe_opts()
11506 /* Format of u[ret]probe section definition supporting auto-attach:
11513 * specified (and auto-attach is not possible) or the above format is specified for
11514 * auto-attach.
11520 int n, ret = -EINVAL; in attach_uprobe()
11525 n = sscanf(prog->sec_name, "%m[^/]/%m[^:]:%m[a-zA-Z0-9_.]+%li", in attach_uprobe()
11529 /* handle SEC("u[ret]probe") - format is valid, but auto-attach is impossible. */ in attach_uprobe()
11534 prog->name, prog->sec_name); in attach_uprobe()
11542 prog->name); in attach_uprobe()
11546 *link = bpf_program__attach_uprobe_opts(prog, -1, binary_path, offset, &opts); in attach_uprobe()
11550 pr_warn("prog '%s': invalid format of section definition '%s'\n", prog->name, in attach_uprobe()
11551 prog->sec_name); in attach_uprobe()
11577 struct bpf_object *obj = prog->obj; in bpf_program__attach_usdt()
11583 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_usdt()
11587 prog->name); in bpf_program__attach_usdt()
11588 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_usdt()
11592 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_usdt()
11598 prog->name, binary_path, err); in bpf_program__attach_usdt()
11607 if (IS_ERR(obj->usdt_man)) in bpf_program__attach_usdt()
11608 return libbpf_ptr(obj->usdt_man); in bpf_program__attach_usdt()
11609 if (!obj->usdt_man) { in bpf_program__attach_usdt()
11610 obj->usdt_man = usdt_manager_new(obj); in bpf_program__attach_usdt()
11611 if (IS_ERR(obj->usdt_man)) in bpf_program__attach_usdt()
11612 return libbpf_ptr(obj->usdt_man); in bpf_program__attach_usdt()
11616 link = usdt_manager_attach_usdt(obj->usdt_man, prog, pid, binary_path, in bpf_program__attach_usdt()
11632 /* no auto-attach for just SEC("usdt") */ in attach_usdt()
11641 err = -EINVAL; in attach_usdt()
11643 *link = bpf_program__attach_usdt(prog, -1 /* any process */, path, in attach_usdt()
11662 return -errno; in determine_tracepoint_id()
11666 return -E2BIG; in determine_tracepoint_id()
11692 pfd = syscall(__NR_perf_event_open, &attr, -1 /* pid */, 0 /* cpu */, in perf_event_open_tracepoint()
11693 -1 /* group_fd */, PERF_FLAG_FD_CLOEXEC); in perf_event_open_tracepoint()
11695 err = -errno; in perf_event_open_tracepoint()
11715 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_tracepoint_opts()
11722 prog->name, tp_category, tp_name, in bpf_program__attach_tracepoint_opts()
11731 prog->name, tp_category, tp_name, in bpf_program__attach_tracepoint_opts()
11751 /* no auto-attach for SEC("tp") or SEC("tracepoint") */ in attach_tp()
11752 if (strcmp(prog->sec_name, "tp") == 0 || strcmp(prog->sec_name, "tracepoint") == 0) in attach_tp()
11755 sec_name = strdup(prog->sec_name); in attach_tp()
11757 return -ENOMEM; in attach_tp()
11760 if (str_has_pfx(prog->sec_name, "tp/")) in attach_tp()
11761 tp_cat = sec_name + sizeof("tp/") - 1; in attach_tp()
11763 tp_cat = sec_name + sizeof("tracepoint/") - 1; in attach_tp()
11767 return -EINVAL; in attach_tp()
11786 pr_warn("prog '%s': can't attach before loaded\n", prog->name); in bpf_program__attach_raw_tracepoint()
11787 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_raw_tracepoint()
11792 return libbpf_err_ptr(-ENOMEM); in bpf_program__attach_raw_tracepoint()
11793 link->detach = &bpf_link__detach_fd; in bpf_program__attach_raw_tracepoint()
11797 pfd = -errno; in bpf_program__attach_raw_tracepoint()
11800 prog->name, tp_name, libbpf_strerror_r(pfd, errmsg, sizeof(errmsg))); in bpf_program__attach_raw_tracepoint()
11803 link->fd = pfd; in bpf_program__attach_raw_tracepoint()
11823 if (!str_has_pfx(prog->sec_name, prefixes[i])) in attach_raw_tp()
11827 /* no auto-attach case of, e.g., SEC("raw_tp") */ in attach_raw_tp()
11828 if (prog->sec_name[pfx_len] == '\0') in attach_raw_tp()
11831 if (prog->sec_name[pfx_len] != '/') in attach_raw_tp()
11834 tp_name = prog->sec_name + pfx_len + 1; in attach_raw_tp()
11840 prog->name, prog->sec_name); in attach_raw_tp()
11841 return -EINVAL; in attach_raw_tp()
11858 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_btf_id()
11862 pr_warn("prog '%s': can't attach before loaded\n", prog->name); in bpf_program__attach_btf_id()
11863 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_btf_id()
11868 return libbpf_err_ptr(-ENOMEM); in bpf_program__attach_btf_id()
11869 link->detach = &bpf_link__detach_fd; in bpf_program__attach_btf_id()
11875 pfd = -errno; in bpf_program__attach_btf_id()
11878 prog->name, libbpf_strerror_r(pfd, errmsg, sizeof(errmsg))); in bpf_program__attach_btf_id()
11881 link->fd = pfd; in bpf_program__attach_btf_id()
11925 pr_warn("prog '%s': can't attach before loaded\n", prog->name); in bpf_program_attach_fd()
11926 return libbpf_err_ptr(-EINVAL); in bpf_program_attach_fd()
11931 return libbpf_err_ptr(-ENOMEM); in bpf_program_attach_fd()
11932 link->detach = &bpf_link__detach_fd; in bpf_program_attach_fd()
11937 link_fd = -errno; in bpf_program_attach_fd()
11940 prog->name, target_name, in bpf_program_attach_fd()
11944 link->fd = link_fd; in bpf_program_attach_fd()
11975 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_tcx()
11980 /* validate we don't have unexpected combinations of non-zero fields */ in bpf_program__attach_tcx()
11983 prog->name); in bpf_program__attach_tcx()
11984 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_tcx()
11988 prog->name); in bpf_program__attach_tcx()
11989 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_tcx()
12009 prog->name); in bpf_program__attach_freplace()
12010 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_freplace()
12013 if (prog->type != BPF_PROG_TYPE_EXT) { in bpf_program__attach_freplace()
12015 prog->name); in bpf_program__attach_freplace()
12016 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_freplace()
12049 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_iter()
12056 pr_warn("prog '%s': can't attach before loaded\n", prog->name); in bpf_program__attach_iter()
12057 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_iter()
12062 return libbpf_err_ptr(-ENOMEM); in bpf_program__attach_iter()
12063 link->detach = &bpf_link__detach_fd; in bpf_program__attach_iter()
12068 link_fd = -errno; in bpf_program__attach_iter()
12071 prog->name, libbpf_strerror_r(link_fd, errmsg, sizeof(errmsg))); in bpf_program__attach_iter()
12074 link->fd = link_fd; in bpf_program__attach_iter()
12092 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_netfilter()
12096 pr_warn("prog '%s': can't attach before loaded\n", prog->name); in bpf_program__attach_netfilter()
12097 return libbpf_err_ptr(-EINVAL); in bpf_program__attach_netfilter()
12102 return libbpf_err_ptr(-ENOMEM); in bpf_program__attach_netfilter()
12104 link->detach = &bpf_link__detach_fd; in bpf_program__attach_netfilter()
12115 link_fd = -errno; in bpf_program__attach_netfilter()
12118 prog->name, libbpf_strerror_r(link_fd, errmsg, sizeof(errmsg))); in bpf_program__attach_netfilter()
12121 link->fd = link_fd; in bpf_program__attach_netfilter()
12131 if (!prog->sec_def || !prog->sec_def->prog_attach_fn) in bpf_program__attach()
12132 return libbpf_err_ptr(-EOPNOTSUPP); in bpf_program__attach()
12134 err = prog->sec_def->prog_attach_fn(prog, prog->sec_def->cookie, &link); in bpf_program__attach()
12138 /* When calling bpf_program__attach() explicitly, auto-attach support in bpf_program__attach()
12144 return libbpf_err_ptr(-EOPNOTSUPP); in bpf_program__attach()
12161 if (st_link->map_fd < 0) in bpf_link__detach_struct_ops()
12163 return bpf_map_delete_elem(link->fd, &zero); in bpf_link__detach_struct_ops()
12165 return close(link->fd); in bpf_link__detach_struct_ops()
12174 if (!bpf_map__is_struct_ops(map) || map->fd == -1) in bpf_map__attach_struct_ops()
12175 return libbpf_err_ptr(-EINVAL); in bpf_map__attach_struct_ops()
12179 return libbpf_err_ptr(-EINVAL); in bpf_map__attach_struct_ops()
12182 err = bpf_map_update_elem(map->fd, &zero, map->st_ops->kern_vdata, 0); in bpf_map__attach_struct_ops()
12188 if (err && (!(map->def.map_flags & BPF_F_LINK) || err != -EBUSY)) { in bpf_map__attach_struct_ops()
12193 link->link.detach = bpf_link__detach_struct_ops; in bpf_map__attach_struct_ops()
12195 if (!(map->def.map_flags & BPF_F_LINK)) { in bpf_map__attach_struct_ops()
12197 link->link.fd = map->fd; in bpf_map__attach_struct_ops()
12198 link->map_fd = -1; in bpf_map__attach_struct_ops()
12199 return &link->link; in bpf_map__attach_struct_ops()
12202 fd = bpf_link_create(map->fd, 0, BPF_STRUCT_OPS, NULL); in bpf_map__attach_struct_ops()
12208 link->link.fd = fd; in bpf_map__attach_struct_ops()
12209 link->map_fd = map->fd; in bpf_map__attach_struct_ops()
12211 return &link->link; in bpf_map__attach_struct_ops()
12223 if (!bpf_map__is_struct_ops(map) || map->fd < 0) in bpf_link__update_map()
12224 return -EINVAL; in bpf_link__update_map()
12228 if (st_ops_link->map_fd < 0) in bpf_link__update_map()
12229 return -EINVAL; in bpf_link__update_map()
12231 err = bpf_map_update_elem(map->fd, &zero, map->st_ops->kern_vdata, 0); in bpf_link__update_map()
12237 if (err && err != -EBUSY) in bpf_link__update_map()
12240 err = bpf_link_update(link->fd, map->fd, NULL); in bpf_link__update_map()
12244 st_ops_link->map_fd = map->fd; in bpf_link__update_map()
12259 __u64 data_tail = header->data_tail;
12266 ehdr = base + (data_tail & (mmap_size - 1));
12267 ehdr_size = ehdr->size;
12271 size_t len_first = base + mmap_size - copy_start;
12272 size_t len_secnd = ehdr_size - len_first;
12306 /* sample_cb and lost_cb are higher-level common-case callbacks */
12345 if (cpu_buf->base && in perf_buffer__free_cpu_buf()
12346 munmap(cpu_buf->base, pb->mmap_size + pb->page_size)) in perf_buffer__free_cpu_buf()
12347 pr_warn("failed to munmap cpu_buf #%d\n", cpu_buf->cpu); in perf_buffer__free_cpu_buf()
12348 if (cpu_buf->fd >= 0) { in perf_buffer__free_cpu_buf()
12349 ioctl(cpu_buf->fd, PERF_EVENT_IOC_DISABLE, 0); in perf_buffer__free_cpu_buf()
12350 close(cpu_buf->fd); in perf_buffer__free_cpu_buf()
12352 free(cpu_buf->buf); in perf_buffer__free_cpu_buf()
12362 if (pb->cpu_bufs) { in perf_buffer__free()
12363 for (i = 0; i < pb->cpu_cnt; i++) { in perf_buffer__free()
12364 struct perf_cpu_buf *cpu_buf = pb->cpu_bufs[i]; in perf_buffer__free()
12369 bpf_map_delete_elem(pb->map_fd, &cpu_buf->map_key); in perf_buffer__free()
12372 free(pb->cpu_bufs); in perf_buffer__free()
12374 if (pb->epoll_fd >= 0) in perf_buffer__free()
12375 close(pb->epoll_fd); in perf_buffer__free()
12376 free(pb->events); in perf_buffer__free()
12390 return ERR_PTR(-ENOMEM); in perf_buffer__open_cpu_buf()
12392 cpu_buf->pb = pb; in perf_buffer__open_cpu_buf()
12393 cpu_buf->cpu = cpu; in perf_buffer__open_cpu_buf()
12394 cpu_buf->map_key = map_key; in perf_buffer__open_cpu_buf()
12396 cpu_buf->fd = syscall(__NR_perf_event_open, attr, -1 /* pid */, cpu, in perf_buffer__open_cpu_buf()
12397 -1, PERF_FLAG_FD_CLOEXEC); in perf_buffer__open_cpu_buf()
12398 if (cpu_buf->fd < 0) { in perf_buffer__open_cpu_buf()
12399 err = -errno; in perf_buffer__open_cpu_buf()
12405 cpu_buf->base = mmap(NULL, pb->mmap_size + pb->page_size, in perf_buffer__open_cpu_buf()
12407 cpu_buf->fd, 0); in perf_buffer__open_cpu_buf()
12408 if (cpu_buf->base == MAP_FAILED) { in perf_buffer__open_cpu_buf()
12409 cpu_buf->base = NULL; in perf_buffer__open_cpu_buf()
12410 err = -errno; in perf_buffer__open_cpu_buf()
12416 if (ioctl(cpu_buf->fd, PERF_EVENT_IOC_ENABLE, 0) < 0) { in perf_buffer__open_cpu_buf()
12417 err = -errno; in perf_buffer__open_cpu_buf()
12445 return libbpf_err_ptr(-EINVAL); in perf_buffer__new()
12475 return libbpf_err_ptr(-EINVAL); in perf_buffer__new_raw()
12478 return libbpf_err_ptr(-EINVAL); in perf_buffer__new_raw()
12501 if (page_cnt == 0 || (page_cnt & (page_cnt - 1))) { in __perf_buffer__new()
12504 return ERR_PTR(-EINVAL); in __perf_buffer__new()
12507 /* best-effort sanity checks */ in __perf_buffer__new()
12512 err = -errno; in __perf_buffer__new()
12514 * -EBADFD, -EFAULT, or -E2BIG on real error in __perf_buffer__new()
12516 if (err != -EINVAL) { in __perf_buffer__new()
12527 return ERR_PTR(-EINVAL); in __perf_buffer__new()
12533 return ERR_PTR(-ENOMEM); in __perf_buffer__new()
12535 pb->event_cb = p->event_cb; in __perf_buffer__new()
12536 pb->sample_cb = p->sample_cb; in __perf_buffer__new()
12537 pb->lost_cb = p->lost_cb; in __perf_buffer__new()
12538 pb->ctx = p->ctx; in __perf_buffer__new()
12540 pb->page_size = getpagesize(); in __perf_buffer__new()
12541 pb->mmap_size = pb->page_size * page_cnt; in __perf_buffer__new()
12542 pb->map_fd = map_fd; in __perf_buffer__new()
12544 pb->epoll_fd = epoll_create1(EPOLL_CLOEXEC); in __perf_buffer__new()
12545 if (pb->epoll_fd < 0) { in __perf_buffer__new()
12546 err = -errno; in __perf_buffer__new()
12552 if (p->cpu_cnt > 0) { in __perf_buffer__new()
12553 pb->cpu_cnt = p->cpu_cnt; in __perf_buffer__new()
12555 pb->cpu_cnt = libbpf_num_possible_cpus(); in __perf_buffer__new()
12556 if (pb->cpu_cnt < 0) { in __perf_buffer__new()
12557 err = pb->cpu_cnt; in __perf_buffer__new()
12560 if (map.max_entries && map.max_entries < pb->cpu_cnt) in __perf_buffer__new()
12561 pb->cpu_cnt = map.max_entries; in __perf_buffer__new()
12564 pb->events = calloc(pb->cpu_cnt, sizeof(*pb->events)); in __perf_buffer__new()
12565 if (!pb->events) { in __perf_buffer__new()
12566 err = -ENOMEM; in __perf_buffer__new()
12570 pb->cpu_bufs = calloc(pb->cpu_cnt, sizeof(*pb->cpu_bufs)); in __perf_buffer__new()
12571 if (!pb->cpu_bufs) { in __perf_buffer__new()
12572 err = -ENOMEM; in __perf_buffer__new()
12583 for (i = 0, j = 0; i < pb->cpu_cnt; i++) { in __perf_buffer__new()
12587 cpu = p->cpu_cnt > 0 ? p->cpus[i] : i; in __perf_buffer__new()
12588 map_key = p->cpu_cnt > 0 ? p->map_keys[i] : i; in __perf_buffer__new()
12593 if (p->cpu_cnt <= 0 && (cpu >= n || !online[cpu])) in __perf_buffer__new()
12596 cpu_buf = perf_buffer__open_cpu_buf(pb, p->attr, cpu, map_key); in __perf_buffer__new()
12602 pb->cpu_bufs[j] = cpu_buf; in __perf_buffer__new()
12604 err = bpf_map_update_elem(pb->map_fd, &map_key, in __perf_buffer__new()
12605 &cpu_buf->fd, 0); in __perf_buffer__new()
12607 err = -errno; in __perf_buffer__new()
12608 pr_warn("failed to set cpu #%d, key %d -> perf FD %d: %s\n", in __perf_buffer__new()
12609 cpu, map_key, cpu_buf->fd, in __perf_buffer__new()
12614 pb->events[j].events = EPOLLIN; in __perf_buffer__new()
12615 pb->events[j].data.ptr = cpu_buf; in __perf_buffer__new()
12616 if (epoll_ctl(pb->epoll_fd, EPOLL_CTL_ADD, cpu_buf->fd, in __perf_buffer__new()
12617 &pb->events[j]) < 0) { in __perf_buffer__new()
12618 err = -errno; in __perf_buffer__new()
12620 cpu, cpu_buf->fd, in __perf_buffer__new()
12626 pb->cpu_cnt = j; in __perf_buffer__new()
12655 struct perf_buffer *pb = cpu_buf->pb; in perf_buffer__process_record()
12659 if (pb->event_cb) in perf_buffer__process_record()
12660 return pb->event_cb(pb->ctx, cpu_buf->cpu, e); in perf_buffer__process_record()
12662 switch (e->type) { in perf_buffer__process_record()
12666 if (pb->sample_cb) in perf_buffer__process_record()
12667 pb->sample_cb(pb->ctx, cpu_buf->cpu, s->data, s->size); in perf_buffer__process_record()
12673 if (pb->lost_cb) in perf_buffer__process_record()
12674 pb->lost_cb(pb->ctx, cpu_buf->cpu, s->lost); in perf_buffer__process_record()
12678 pr_warn("unknown perf sample type %d\n", e->type); in perf_buffer__process_record()
12689 ret = perf_event_read_simple(cpu_buf->base, pb->mmap_size, in perf_buffer__process_records()
12690 pb->page_size, &cpu_buf->buf, in perf_buffer__process_records()
12691 &cpu_buf->buf_size, in perf_buffer__process_records()
12700 return pb->epoll_fd; in perf_buffer__epoll_fd()
12707 cnt = epoll_wait(pb->epoll_fd, pb->events, pb->cpu_cnt, timeout_ms); in perf_buffer__poll()
12709 return -errno; in perf_buffer__poll()
12712 struct perf_cpu_buf *cpu_buf = pb->events[i].data.ptr; in perf_buffer__poll()
12728 return pb->cpu_cnt; in perf_buffer__buffer_cnt()
12740 if (buf_idx >= pb->cpu_cnt) in perf_buffer__buffer_fd()
12741 return libbpf_err(-EINVAL); in perf_buffer__buffer_fd()
12743 cpu_buf = pb->cpu_bufs[buf_idx]; in perf_buffer__buffer_fd()
12745 return libbpf_err(-ENOENT); in perf_buffer__buffer_fd()
12747 return cpu_buf->fd; in perf_buffer__buffer_fd()
12754 if (buf_idx >= pb->cpu_cnt) in perf_buffer__buffer()
12755 return libbpf_err(-EINVAL); in perf_buffer__buffer()
12757 cpu_buf = pb->cpu_bufs[buf_idx]; in perf_buffer__buffer()
12759 return libbpf_err(-ENOENT); in perf_buffer__buffer()
12761 *buf = cpu_buf->base; in perf_buffer__buffer()
12762 *buf_size = pb->mmap_size; in perf_buffer__buffer()
12771 * - 0 on success;
12772 * - <0 on failure.
12778 if (buf_idx >= pb->cpu_cnt) in perf_buffer__consume_buffer()
12779 return libbpf_err(-EINVAL); in perf_buffer__consume_buffer()
12781 cpu_buf = pb->cpu_bufs[buf_idx]; in perf_buffer__consume_buffer()
12783 return libbpf_err(-ENOENT); in perf_buffer__consume_buffer()
12792 for (i = 0; i < pb->cpu_cnt; i++) { in perf_buffer__consume()
12793 struct perf_cpu_buf *cpu_buf = pb->cpu_bufs[i]; in perf_buffer__consume()
12814 return libbpf_err(-EINVAL); in bpf_program__set_attach_target()
12816 if (prog->obj->loaded) in bpf_program__set_attach_target()
12817 return libbpf_err(-EINVAL); in bpf_program__set_attach_target()
12823 prog->attach_prog_fd = attach_prog_fd; in bpf_program__set_attach_target()
12834 return libbpf_err(-EINVAL); in bpf_program__set_attach_target()
12837 err = bpf_object__load_vmlinux_btf(prog->obj, true); in bpf_program__set_attach_target()
12840 err = find_kernel_btf_id(prog->obj, attach_func_name, in bpf_program__set_attach_target()
12841 prog->expected_attach_type, in bpf_program__set_attach_target()
12847 prog->attach_btf_id = btf_id; in bpf_program__set_attach_target()
12848 prog->attach_btf_obj_fd = btf_obj_fd; in bpf_program__set_attach_target()
12849 prog->attach_prog_fd = attach_prog_fd; in bpf_program__set_attach_target()
12855 int err = 0, n, len, start, end = -1; in parse_cpu_mask_str()
12861 /* Each sub string separated by ',' has format \d+-\d+ or \d+ */ in parse_cpu_mask_str()
12867 n = sscanf(s, "%d%n-%d%n", &start, &len, &end, &len); in parse_cpu_mask_str()
12870 err = -EINVAL; in parse_cpu_mask_str()
12878 err = -EINVAL; in parse_cpu_mask_str()
12883 err = -ENOMEM; in parse_cpu_mask_str()
12887 memset(tmp + *mask_sz, 0, start - *mask_sz); in parse_cpu_mask_str()
12888 memset(tmp + start, 1, end - start + 1); in parse_cpu_mask_str()
12894 return -EINVAL; in parse_cpu_mask_str()
12910 err = -errno; in parse_cpu_mask_file()
12917 err = len ? -errno : -EINVAL; in parse_cpu_mask_file()
12923 return -E2BIG; in parse_cpu_mask_file()
12970 return -ESRCH; in populate_skeleton_maps()
12973 /* externs shouldn't be pre-setup from user code */ in populate_skeleton_maps()
12974 if (mmaped && (*map)->libbpf_type != LIBBPF_MAP_KCONFIG) in populate_skeleton_maps()
12975 *mmaped = (*map)->mmaped; in populate_skeleton_maps()
12993 return -ESRCH; in populate_skeleton_progs()
13003 .object_name = s->name, in bpf_object__open_skeleton()
13008 /* Attempt to preserve opts->object_name, unless overriden by user in bpf_object__open_skeleton()
13016 if (!opts->object_name) in bpf_object__open_skeleton()
13017 skel_opts.object_name = s->name; in bpf_object__open_skeleton()
13020 obj = bpf_object__open_mem(s->data, s->data_sz, &skel_opts); in bpf_object__open_skeleton()
13024 s->name, err); in bpf_object__open_skeleton()
13028 *s->obj = obj; in bpf_object__open_skeleton()
13029 err = populate_skeleton_maps(obj, s->maps, s->map_cnt); in bpf_object__open_skeleton()
13031 pr_warn("failed to populate skeleton maps for '%s': %d\n", s->name, err); in bpf_object__open_skeleton()
13035 err = populate_skeleton_progs(obj, s->progs, s->prog_cnt); in bpf_object__open_skeleton()
13037 pr_warn("failed to populate skeleton progs for '%s': %d\n", s->name, err); in bpf_object__open_skeleton()
13055 if (!s->obj) in bpf_object__open_subskeleton()
13056 return libbpf_err(-EINVAL); in bpf_object__open_subskeleton()
13058 btf = bpf_object__btf(s->obj); in bpf_object__open_subskeleton()
13061 bpf_object__name(s->obj)); in bpf_object__open_subskeleton()
13062 return libbpf_err(-errno); in bpf_object__open_subskeleton()
13065 err = populate_skeleton_maps(s->obj, s->maps, s->map_cnt); in bpf_object__open_subskeleton()
13071 err = populate_skeleton_progs(s->obj, s->progs, s->prog_cnt); in bpf_object__open_subskeleton()
13077 for (var_idx = 0; var_idx < s->var_cnt; var_idx++) { in bpf_object__open_subskeleton()
13078 var_skel = &s->vars[var_idx]; in bpf_object__open_subskeleton()
13079 map = *var_skel->map; in bpf_object__open_subskeleton()
13087 return libbpf_err(-EINVAL); in bpf_object__open_subskeleton()
13093 var_type = btf__type_by_id(btf, var->type); in bpf_object__open_subskeleton()
13094 var_name = btf__name_by_offset(btf, var_type->name_off); in bpf_object__open_subskeleton()
13095 if (strcmp(var_name, var_skel->name) == 0) { in bpf_object__open_subskeleton()
13096 *var_skel->addr = map->mmaped + var->offset; in bpf_object__open_subskeleton()
13108 free(s->maps); in bpf_object__destroy_subskeleton()
13109 free(s->progs); in bpf_object__destroy_subskeleton()
13110 free(s->vars); in bpf_object__destroy_subskeleton()
13118 err = bpf_object__load(*s->obj); in bpf_object__load_skeleton()
13120 pr_warn("failed to load BPF skeleton '%s': %d\n", s->name, err); in bpf_object__load_skeleton()
13124 for (i = 0; i < s->map_cnt; i++) { in bpf_object__load_skeleton()
13125 struct bpf_map *map = *s->maps[i].map; in bpf_object__load_skeleton()
13126 size_t mmap_sz = bpf_map_mmap_sz(map->def.value_size, map->def.max_entries); in bpf_object__load_skeleton()
13128 void **mmaped = s->maps[i].mmaped; in bpf_object__load_skeleton()
13133 if (!(map->def.map_flags & BPF_F_MMAPABLE)) { in bpf_object__load_skeleton()
13138 if (map->def.map_flags & BPF_F_RDONLY_PROG) in bpf_object__load_skeleton()
13143 /* Remap anonymous mmap()-ed "map initialization image" as in bpf_object__load_skeleton()
13144 * a BPF map-backed mmap()-ed memory, but preserving the same in bpf_object__load_skeleton()
13153 *mmaped = mmap(map->mmaped, mmap_sz, prot, MAP_SHARED | MAP_FIXED, map_fd, 0); in bpf_object__load_skeleton()
13155 err = -errno; in bpf_object__load_skeleton()
13157 pr_warn("failed to re-mmap() map '%s': %d\n", in bpf_object__load_skeleton()
13170 for (i = 0; i < s->prog_cnt; i++) { in bpf_object__attach_skeleton()
13171 struct bpf_program *prog = *s->progs[i].prog; in bpf_object__attach_skeleton()
13172 struct bpf_link **link = s->progs[i].link; in bpf_object__attach_skeleton()
13174 if (!prog->autoload || !prog->autoattach) in bpf_object__attach_skeleton()
13177 /* auto-attaching not supported for this program */ in bpf_object__attach_skeleton()
13178 if (!prog->sec_def || !prog->sec_def->prog_attach_fn) in bpf_object__attach_skeleton()
13181 /* if user already set the link manually, don't attempt auto-attach */ in bpf_object__attach_skeleton()
13185 err = prog->sec_def->prog_attach_fn(prog, prog->sec_def->cookie, link); in bpf_object__attach_skeleton()
13187 pr_warn("prog '%s': failed to auto-attach: %d\n", in bpf_object__attach_skeleton()
13192 /* It's possible that for some SEC() definitions auto-attach in bpf_object__attach_skeleton()
13197 * auto-attached. But if not, it shouldn't trigger skeleton's in bpf_object__attach_skeleton()
13211 for (i = 0; i < s->prog_cnt; i++) { in bpf_object__detach_skeleton()
13212 struct bpf_link **link = s->progs[i].link; in bpf_object__detach_skeleton()
13224 if (s->progs) in bpf_object__destroy_skeleton()
13226 if (s->obj) in bpf_object__destroy_skeleton()
13227 bpf_object__close(*s->obj); in bpf_object__destroy_skeleton()
13228 free(s->maps); in bpf_object__destroy_skeleton()
13229 free(s->progs); in bpf_object__destroy_skeleton()