diff options
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
| -rw-r--r-- | tools/lib/bpf/libbpf.c | 635 |
1 files changed, 582 insertions, 53 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index d6e62e90e8d4..169e347c76f6 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
| @@ -9,7 +9,9 @@ | |||
| 9 | * Copyright (C) 2017 Nicira, Inc. | 9 | * Copyright (C) 2017 Nicira, Inc. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #ifndef _GNU_SOURCE | ||
| 12 | #define _GNU_SOURCE | 13 | #define _GNU_SOURCE |
| 14 | #endif | ||
| 13 | #include <stdlib.h> | 15 | #include <stdlib.h> |
| 14 | #include <stdio.h> | 16 | #include <stdio.h> |
| 15 | #include <stdarg.h> | 17 | #include <stdarg.h> |
| @@ -24,6 +26,7 @@ | |||
| 24 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 25 | #include <linux/bpf.h> | 27 | #include <linux/bpf.h> |
| 26 | #include <linux/btf.h> | 28 | #include <linux/btf.h> |
| 29 | #include <linux/filter.h> | ||
| 27 | #include <linux/list.h> | 30 | #include <linux/list.h> |
| 28 | #include <linux/limits.h> | 31 | #include <linux/limits.h> |
| 29 | #include <linux/perf_event.h> | 32 | #include <linux/perf_event.h> |
| @@ -114,6 +117,11 @@ void libbpf_set_print(libbpf_print_fn_t warn, | |||
| 114 | # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ | 117 | # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ |
| 115 | #endif | 118 | #endif |
| 116 | 119 | ||
| 120 | struct bpf_capabilities { | ||
| 121 | /* v4.14: kernel support for program & map names. */ | ||
| 122 | __u32 name:1; | ||
| 123 | }; | ||
| 124 | |||
| 117 | /* | 125 | /* |
| 118 | * bpf_prog should be a better name but it has been used in | 126 | * bpf_prog should be a better name but it has been used in |
| 119 | * linux/filter.h. | 127 | * linux/filter.h. |
| @@ -124,6 +132,10 @@ struct bpf_program { | |||
| 124 | char *name; | 132 | char *name; |
| 125 | int prog_ifindex; | 133 | int prog_ifindex; |
| 126 | char *section_name; | 134 | char *section_name; |
| 135 | /* section_name with / replaced by _; makes recursive pinning | ||
| 136 | * in bpf_object__pin_programs easier | ||
| 137 | */ | ||
| 138 | char *pin_name; | ||
| 127 | struct bpf_insn *insns; | 139 | struct bpf_insn *insns; |
| 128 | size_t insns_cnt, main_prog_cnt; | 140 | size_t insns_cnt, main_prog_cnt; |
| 129 | enum bpf_prog_type type; | 141 | enum bpf_prog_type type; |
| @@ -152,6 +164,16 @@ struct bpf_program { | |||
| 152 | bpf_program_clear_priv_t clear_priv; | 164 | bpf_program_clear_priv_t clear_priv; |
| 153 | 165 | ||
| 154 | enum bpf_attach_type expected_attach_type; | 166 | enum bpf_attach_type expected_attach_type; |
| 167 | int btf_fd; | ||
| 168 | void *func_info; | ||
| 169 | __u32 func_info_rec_size; | ||
| 170 | __u32 func_info_cnt; | ||
| 171 | |||
| 172 | struct bpf_capabilities *caps; | ||
| 173 | |||
| 174 | void *line_info; | ||
| 175 | __u32 line_info_rec_size; | ||
| 176 | __u32 line_info_cnt; | ||
| 155 | }; | 177 | }; |
| 156 | 178 | ||
| 157 | struct bpf_map { | 179 | struct bpf_map { |
| @@ -159,6 +181,7 @@ struct bpf_map { | |||
| 159 | char *name; | 181 | char *name; |
| 160 | size_t offset; | 182 | size_t offset; |
| 161 | int map_ifindex; | 183 | int map_ifindex; |
| 184 | int inner_map_fd; | ||
| 162 | struct bpf_map_def def; | 185 | struct bpf_map_def def; |
| 163 | __u32 btf_key_type_id; | 186 | __u32 btf_key_type_id; |
| 164 | __u32 btf_value_type_id; | 187 | __u32 btf_value_type_id; |
| @@ -208,10 +231,13 @@ struct bpf_object { | |||
| 208 | struct list_head list; | 231 | struct list_head list; |
| 209 | 232 | ||
| 210 | struct btf *btf; | 233 | struct btf *btf; |
| 234 | struct btf_ext *btf_ext; | ||
| 211 | 235 | ||
| 212 | void *priv; | 236 | void *priv; |
| 213 | bpf_object_clear_priv_t clear_priv; | 237 | bpf_object_clear_priv_t clear_priv; |
| 214 | 238 | ||
| 239 | struct bpf_capabilities caps; | ||
| 240 | |||
| 215 | char path[]; | 241 | char path[]; |
| 216 | }; | 242 | }; |
| 217 | #define obj_elf_valid(o) ((o)->efile.elf) | 243 | #define obj_elf_valid(o) ((o)->efile.elf) |
| @@ -237,6 +263,10 @@ void bpf_program__unload(struct bpf_program *prog) | |||
| 237 | 263 | ||
| 238 | prog->instances.nr = -1; | 264 | prog->instances.nr = -1; |
| 239 | zfree(&prog->instances.fds); | 265 | zfree(&prog->instances.fds); |
| 266 | |||
| 267 | zclose(prog->btf_fd); | ||
| 268 | zfree(&prog->func_info); | ||
| 269 | zfree(&prog->line_info); | ||
| 240 | } | 270 | } |
| 241 | 271 | ||
| 242 | static void bpf_program__exit(struct bpf_program *prog) | 272 | static void bpf_program__exit(struct bpf_program *prog) |
| @@ -253,6 +283,7 @@ static void bpf_program__exit(struct bpf_program *prog) | |||
| 253 | bpf_program__unload(prog); | 283 | bpf_program__unload(prog); |
| 254 | zfree(&prog->name); | 284 | zfree(&prog->name); |
| 255 | zfree(&prog->section_name); | 285 | zfree(&prog->section_name); |
| 286 | zfree(&prog->pin_name); | ||
| 256 | zfree(&prog->insns); | 287 | zfree(&prog->insns); |
| 257 | zfree(&prog->reloc_desc); | 288 | zfree(&prog->reloc_desc); |
| 258 | 289 | ||
| @@ -261,6 +292,17 @@ static void bpf_program__exit(struct bpf_program *prog) | |||
| 261 | prog->idx = -1; | 292 | prog->idx = -1; |
| 262 | } | 293 | } |
| 263 | 294 | ||
| 295 | static char *__bpf_program__pin_name(struct bpf_program *prog) | ||
| 296 | { | ||
| 297 | char *name, *p; | ||
| 298 | |||
| 299 | name = p = strdup(prog->section_name); | ||
| 300 | while ((p = strchr(p, '/'))) | ||
| 301 | *p = '_'; | ||
| 302 | |||
| 303 | return name; | ||
| 304 | } | ||
| 305 | |||
| 264 | static int | 306 | static int |
| 265 | bpf_program__init(void *data, size_t size, char *section_name, int idx, | 307 | bpf_program__init(void *data, size_t size, char *section_name, int idx, |
| 266 | struct bpf_program *prog) | 308 | struct bpf_program *prog) |
| @@ -279,6 +321,13 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx, | |||
| 279 | goto errout; | 321 | goto errout; |
| 280 | } | 322 | } |
| 281 | 323 | ||
| 324 | prog->pin_name = __bpf_program__pin_name(prog); | ||
| 325 | if (!prog->pin_name) { | ||
| 326 | pr_warning("failed to alloc pin name for prog under section(%d) %s\n", | ||
| 327 | idx, section_name); | ||
| 328 | goto errout; | ||
| 329 | } | ||
| 330 | |||
| 282 | prog->insns = malloc(size); | 331 | prog->insns = malloc(size); |
| 283 | if (!prog->insns) { | 332 | if (!prog->insns) { |
| 284 | pr_warning("failed to alloc insns for prog under section %s\n", | 333 | pr_warning("failed to alloc insns for prog under section %s\n", |
| @@ -291,7 +340,8 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx, | |||
| 291 | prog->idx = idx; | 340 | prog->idx = idx; |
| 292 | prog->instances.fds = NULL; | 341 | prog->instances.fds = NULL; |
| 293 | prog->instances.nr = -1; | 342 | prog->instances.nr = -1; |
| 294 | prog->type = BPF_PROG_TYPE_KPROBE; | 343 | prog->type = BPF_PROG_TYPE_UNSPEC; |
| 344 | prog->btf_fd = -1; | ||
| 295 | 345 | ||
| 296 | return 0; | 346 | return 0; |
| 297 | errout: | 347 | errout: |
| @@ -310,6 +360,7 @@ bpf_object__add_program(struct bpf_object *obj, void *data, size_t size, | |||
| 310 | if (err) | 360 | if (err) |
| 311 | return err; | 361 | return err; |
| 312 | 362 | ||
| 363 | prog.caps = &obj->caps; | ||
| 313 | progs = obj->programs; | 364 | progs = obj->programs; |
| 314 | nr_progs = obj->nr_programs; | 365 | nr_progs = obj->nr_programs; |
| 315 | 366 | ||
| @@ -562,6 +613,14 @@ static int compare_bpf_map(const void *_a, const void *_b) | |||
| 562 | return a->offset - b->offset; | 613 | return a->offset - b->offset; |
| 563 | } | 614 | } |
| 564 | 615 | ||
| 616 | static bool bpf_map_type__is_map_in_map(enum bpf_map_type type) | ||
| 617 | { | ||
| 618 | if (type == BPF_MAP_TYPE_ARRAY_OF_MAPS || | ||
| 619 | type == BPF_MAP_TYPE_HASH_OF_MAPS) | ||
| 620 | return true; | ||
| 621 | return false; | ||
| 622 | } | ||
| 623 | |||
| 565 | static int | 624 | static int |
| 566 | bpf_object__init_maps(struct bpf_object *obj, int flags) | 625 | bpf_object__init_maps(struct bpf_object *obj, int flags) |
| 567 | { | 626 | { |
| @@ -625,13 +684,15 @@ bpf_object__init_maps(struct bpf_object *obj, int flags) | |||
| 625 | } | 684 | } |
| 626 | obj->nr_maps = nr_maps; | 685 | obj->nr_maps = nr_maps; |
| 627 | 686 | ||
| 628 | /* | 687 | for (i = 0; i < nr_maps; i++) { |
| 629 | * fill all fd with -1 so won't close incorrect | 688 | /* |
| 630 | * fd (fd=0 is stdin) when failure (zclose won't close | 689 | * fill all fd with -1 so won't close incorrect |
| 631 | * negative fd)). | 690 | * fd (fd=0 is stdin) when failure (zclose won't close |
| 632 | */ | 691 | * negative fd)). |
| 633 | for (i = 0; i < nr_maps; i++) | 692 | */ |
| 634 | obj->maps[i].fd = -1; | 693 | obj->maps[i].fd = -1; |
| 694 | obj->maps[i].inner_map_fd = -1; | ||
| 695 | } | ||
| 635 | 696 | ||
| 636 | /* | 697 | /* |
| 637 | * Fill obj->maps using data in "maps" section. | 698 | * Fill obj->maps using data in "maps" section. |
| @@ -723,6 +784,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags) | |||
| 723 | { | 784 | { |
| 724 | Elf *elf = obj->efile.elf; | 785 | Elf *elf = obj->efile.elf; |
| 725 | GElf_Ehdr *ep = &obj->efile.ehdr; | 786 | GElf_Ehdr *ep = &obj->efile.ehdr; |
| 787 | Elf_Data *btf_ext_data = NULL; | ||
| 726 | Elf_Scn *scn = NULL; | 788 | Elf_Scn *scn = NULL; |
| 727 | int idx = 0, err = 0; | 789 | int idx = 0, err = 0; |
| 728 | 790 | ||
| @@ -784,6 +846,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags) | |||
| 784 | BTF_ELF_SEC, PTR_ERR(obj->btf)); | 846 | BTF_ELF_SEC, PTR_ERR(obj->btf)); |
| 785 | obj->btf = NULL; | 847 | obj->btf = NULL; |
| 786 | } | 848 | } |
| 849 | } else if (strcmp(name, BTF_EXT_ELF_SEC) == 0) { | ||
| 850 | btf_ext_data = data; | ||
| 787 | } else if (sh.sh_type == SHT_SYMTAB) { | 851 | } else if (sh.sh_type == SHT_SYMTAB) { |
| 788 | if (obj->efile.symbols) { | 852 | if (obj->efile.symbols) { |
| 789 | pr_warning("bpf: multiple SYMTAB in %s\n", | 853 | pr_warning("bpf: multiple SYMTAB in %s\n", |
| @@ -845,6 +909,22 @@ static int bpf_object__elf_collect(struct bpf_object *obj, int flags) | |||
| 845 | pr_warning("Corrupted ELF file: index of strtab invalid\n"); | 909 | pr_warning("Corrupted ELF file: index of strtab invalid\n"); |
| 846 | return LIBBPF_ERRNO__FORMAT; | 910 | return LIBBPF_ERRNO__FORMAT; |
| 847 | } | 911 | } |
| 912 | if (btf_ext_data) { | ||
| 913 | if (!obj->btf) { | ||
| 914 | pr_debug("Ignore ELF section %s because its depending ELF section %s is not found.\n", | ||
| 915 | BTF_EXT_ELF_SEC, BTF_ELF_SEC); | ||
| 916 | } else { | ||
| 917 | obj->btf_ext = btf_ext__new(btf_ext_data->d_buf, | ||
| 918 | btf_ext_data->d_size, | ||
| 919 | __pr_debug); | ||
| 920 | if (IS_ERR(obj->btf_ext)) { | ||
| 921 | pr_warning("Error loading ELF section %s: %ld. Ignored and continue.\n", | ||
| 922 | BTF_EXT_ELF_SEC, | ||
| 923 | PTR_ERR(obj->btf_ext)); | ||
| 924 | obj->btf_ext = NULL; | ||
| 925 | } | ||
| 926 | } | ||
| 927 | } | ||
| 848 | if (obj->efile.maps_shndx >= 0) { | 928 | if (obj->efile.maps_shndx >= 0) { |
| 849 | err = bpf_object__init_maps(obj, flags); | 929 | err = bpf_object__init_maps(obj, flags); |
| 850 | if (err) | 930 | if (err) |
| @@ -1095,6 +1175,52 @@ err_free_new_name: | |||
| 1095 | } | 1175 | } |
| 1096 | 1176 | ||
| 1097 | static int | 1177 | static int |
| 1178 | bpf_object__probe_name(struct bpf_object *obj) | ||
| 1179 | { | ||
| 1180 | struct bpf_load_program_attr attr; | ||
| 1181 | char *cp, errmsg[STRERR_BUFSIZE]; | ||
| 1182 | struct bpf_insn insns[] = { | ||
| 1183 | BPF_MOV64_IMM(BPF_REG_0, 0), | ||
| 1184 | BPF_EXIT_INSN(), | ||
| 1185 | }; | ||
| 1186 | int ret; | ||
| 1187 | |||
| 1188 | /* make sure basic loading works */ | ||
| 1189 | |||
| 1190 | memset(&attr, 0, sizeof(attr)); | ||
| 1191 | attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; | ||
| 1192 | attr.insns = insns; | ||
| 1193 | attr.insns_cnt = ARRAY_SIZE(insns); | ||
| 1194 | attr.license = "GPL"; | ||
| 1195 | |||
| 1196 | ret = bpf_load_program_xattr(&attr, NULL, 0); | ||
| 1197 | if (ret < 0) { | ||
| 1198 | cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg)); | ||
| 1199 | pr_warning("Error in %s():%s(%d). Couldn't load basic 'r0 = 0' BPF program.\n", | ||
| 1200 | __func__, cp, errno); | ||
| 1201 | return -errno; | ||
| 1202 | } | ||
| 1203 | close(ret); | ||
| 1204 | |||
| 1205 | /* now try the same program, but with the name */ | ||
| 1206 | |||
| 1207 | attr.name = "test"; | ||
| 1208 | ret = bpf_load_program_xattr(&attr, NULL, 0); | ||
| 1209 | if (ret >= 0) { | ||
| 1210 | obj->caps.name = 1; | ||
| 1211 | close(ret); | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | return 0; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | static int | ||
| 1218 | bpf_object__probe_caps(struct bpf_object *obj) | ||
| 1219 | { | ||
| 1220 | return bpf_object__probe_name(obj); | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | static int | ||
| 1098 | bpf_object__create_maps(struct bpf_object *obj) | 1224 | bpf_object__create_maps(struct bpf_object *obj) |
| 1099 | { | 1225 | { |
| 1100 | struct bpf_create_map_attr create_attr = {}; | 1226 | struct bpf_create_map_attr create_attr = {}; |
| @@ -1113,7 +1239,8 @@ bpf_object__create_maps(struct bpf_object *obj) | |||
| 1113 | continue; | 1239 | continue; |
| 1114 | } | 1240 | } |
| 1115 | 1241 | ||
| 1116 | create_attr.name = map->name; | 1242 | if (obj->caps.name) |
| 1243 | create_attr.name = map->name; | ||
| 1117 | create_attr.map_ifindex = map->map_ifindex; | 1244 | create_attr.map_ifindex = map->map_ifindex; |
| 1118 | create_attr.map_type = def->type; | 1245 | create_attr.map_type = def->type; |
| 1119 | create_attr.map_flags = def->map_flags; | 1246 | create_attr.map_flags = def->map_flags; |
| @@ -1123,6 +1250,9 @@ bpf_object__create_maps(struct bpf_object *obj) | |||
| 1123 | create_attr.btf_fd = 0; | 1250 | create_attr.btf_fd = 0; |
| 1124 | create_attr.btf_key_type_id = 0; | 1251 | create_attr.btf_key_type_id = 0; |
| 1125 | create_attr.btf_value_type_id = 0; | 1252 | create_attr.btf_value_type_id = 0; |
| 1253 | if (bpf_map_type__is_map_in_map(def->type) && | ||
| 1254 | map->inner_map_fd >= 0) | ||
| 1255 | create_attr.inner_map_fd = map->inner_map_fd; | ||
| 1126 | 1256 | ||
| 1127 | if (obj->btf && !bpf_map_find_btf_info(map, obj->btf)) { | 1257 | if (obj->btf && !bpf_map_find_btf_info(map, obj->btf)) { |
| 1128 | create_attr.btf_fd = btf__fd(obj->btf); | 1258 | create_attr.btf_fd = btf__fd(obj->btf); |
| @@ -1161,12 +1291,89 @@ bpf_object__create_maps(struct bpf_object *obj) | |||
| 1161 | } | 1291 | } |
| 1162 | 1292 | ||
| 1163 | static int | 1293 | static int |
| 1294 | check_btf_ext_reloc_err(struct bpf_program *prog, int err, | ||
| 1295 | void *btf_prog_info, const char *info_name) | ||
| 1296 | { | ||
| 1297 | if (err != -ENOENT) { | ||
| 1298 | pr_warning("Error in loading %s for sec %s.\n", | ||
| 1299 | info_name, prog->section_name); | ||
| 1300 | return err; | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | /* err == -ENOENT (i.e. prog->section_name not found in btf_ext) */ | ||
| 1304 | |||
| 1305 | if (btf_prog_info) { | ||
| 1306 | /* | ||
| 1307 | * Some info has already been found but has problem | ||
| 1308 | * in the last btf_ext reloc. Must have to error | ||
| 1309 | * out. | ||
| 1310 | */ | ||
| 1311 | pr_warning("Error in relocating %s for sec %s.\n", | ||
| 1312 | info_name, prog->section_name); | ||
| 1313 | return err; | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | /* | ||
| 1317 | * Have problem loading the very first info. Ignore | ||
| 1318 | * the rest. | ||
| 1319 | */ | ||
| 1320 | pr_warning("Cannot find %s for main program sec %s. Ignore all %s.\n", | ||
| 1321 | info_name, prog->section_name, info_name); | ||
| 1322 | return 0; | ||
| 1323 | } | ||
| 1324 | |||
| 1325 | static int | ||
| 1326 | bpf_program_reloc_btf_ext(struct bpf_program *prog, struct bpf_object *obj, | ||
| 1327 | const char *section_name, __u32 insn_offset) | ||
| 1328 | { | ||
| 1329 | int err; | ||
| 1330 | |||
| 1331 | if (!insn_offset || prog->func_info) { | ||
| 1332 | /* | ||
| 1333 | * !insn_offset => main program | ||
| 1334 | * | ||
| 1335 | * For sub prog, the main program's func_info has to | ||
| 1336 | * be loaded first (i.e. prog->func_info != NULL) | ||
| 1337 | */ | ||
| 1338 | err = btf_ext__reloc_func_info(obj->btf, obj->btf_ext, | ||
| 1339 | section_name, insn_offset, | ||
| 1340 | &prog->func_info, | ||
| 1341 | &prog->func_info_cnt); | ||
| 1342 | if (err) | ||
| 1343 | return check_btf_ext_reloc_err(prog, err, | ||
| 1344 | prog->func_info, | ||
| 1345 | "bpf_func_info"); | ||
| 1346 | |||
| 1347 | prog->func_info_rec_size = btf_ext__func_info_rec_size(obj->btf_ext); | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | if (!insn_offset || prog->line_info) { | ||
| 1351 | err = btf_ext__reloc_line_info(obj->btf, obj->btf_ext, | ||
| 1352 | section_name, insn_offset, | ||
| 1353 | &prog->line_info, | ||
| 1354 | &prog->line_info_cnt); | ||
| 1355 | if (err) | ||
| 1356 | return check_btf_ext_reloc_err(prog, err, | ||
| 1357 | prog->line_info, | ||
| 1358 | "bpf_line_info"); | ||
| 1359 | |||
| 1360 | prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext); | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | if (!insn_offset) | ||
| 1364 | prog->btf_fd = btf__fd(obj->btf); | ||
| 1365 | |||
| 1366 | return 0; | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | static int | ||
| 1164 | bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj, | 1370 | bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj, |
| 1165 | struct reloc_desc *relo) | 1371 | struct reloc_desc *relo) |
| 1166 | { | 1372 | { |
| 1167 | struct bpf_insn *insn, *new_insn; | 1373 | struct bpf_insn *insn, *new_insn; |
| 1168 | struct bpf_program *text; | 1374 | struct bpf_program *text; |
| 1169 | size_t new_cnt; | 1375 | size_t new_cnt; |
| 1376 | int err; | ||
| 1170 | 1377 | ||
| 1171 | if (relo->type != RELO_CALL) | 1378 | if (relo->type != RELO_CALL) |
| 1172 | return -LIBBPF_ERRNO__RELOC; | 1379 | return -LIBBPF_ERRNO__RELOC; |
| @@ -1189,6 +1396,15 @@ bpf_program__reloc_text(struct bpf_program *prog, struct bpf_object *obj, | |||
| 1189 | pr_warning("oom in prog realloc\n"); | 1396 | pr_warning("oom in prog realloc\n"); |
| 1190 | return -ENOMEM; | 1397 | return -ENOMEM; |
| 1191 | } | 1398 | } |
| 1399 | |||
| 1400 | if (obj->btf_ext) { | ||
| 1401 | err = bpf_program_reloc_btf_ext(prog, obj, | ||
| 1402 | text->section_name, | ||
| 1403 | prog->insns_cnt); | ||
| 1404 | if (err) | ||
| 1405 | return err; | ||
| 1406 | } | ||
| 1407 | |||
| 1192 | memcpy(new_insn + prog->insns_cnt, text->insns, | 1408 | memcpy(new_insn + prog->insns_cnt, text->insns, |
| 1193 | text->insns_cnt * sizeof(*insn)); | 1409 | text->insns_cnt * sizeof(*insn)); |
| 1194 | prog->insns = new_insn; | 1410 | prog->insns = new_insn; |
| @@ -1208,7 +1424,17 @@ bpf_program__relocate(struct bpf_program *prog, struct bpf_object *obj) | |||
| 1208 | { | 1424 | { |
| 1209 | int i, err; | 1425 | int i, err; |
| 1210 | 1426 | ||
| 1211 | if (!prog || !prog->reloc_desc) | 1427 | if (!prog) |
| 1428 | return 0; | ||
| 1429 | |||
| 1430 | if (obj->btf_ext) { | ||
| 1431 | err = bpf_program_reloc_btf_ext(prog, obj, | ||
| 1432 | prog->section_name, 0); | ||
| 1433 | if (err) | ||
| 1434 | return err; | ||
| 1435 | } | ||
| 1436 | |||
| 1437 | if (!prog->reloc_desc) | ||
| 1212 | return 0; | 1438 | return 0; |
| 1213 | 1439 | ||
| 1214 | for (i = 0; i < prog->nr_reloc; i++) { | 1440 | for (i = 0; i < prog->nr_reloc; i++) { |
| @@ -1296,9 +1522,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) | |||
| 1296 | } | 1522 | } |
| 1297 | 1523 | ||
| 1298 | static int | 1524 | static int |
| 1299 | load_program(enum bpf_prog_type type, enum bpf_attach_type expected_attach_type, | 1525 | load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt, |
| 1300 | const char *name, struct bpf_insn *insns, int insns_cnt, | 1526 | char *license, __u32 kern_version, int *pfd) |
| 1301 | char *license, __u32 kern_version, int *pfd, int prog_ifindex) | ||
| 1302 | { | 1527 | { |
| 1303 | struct bpf_load_program_attr load_attr; | 1528 | struct bpf_load_program_attr load_attr; |
| 1304 | char *cp, errmsg[STRERR_BUFSIZE]; | 1529 | char *cp, errmsg[STRERR_BUFSIZE]; |
| @@ -1306,15 +1531,22 @@ load_program(enum bpf_prog_type type, enum bpf_attach_type expected_attach_type, | |||
| 1306 | int ret; | 1531 | int ret; |
| 1307 | 1532 | ||
| 1308 | memset(&load_attr, 0, sizeof(struct bpf_load_program_attr)); | 1533 | memset(&load_attr, 0, sizeof(struct bpf_load_program_attr)); |
| 1309 | load_attr.prog_type = type; | 1534 | load_attr.prog_type = prog->type; |
| 1310 | load_attr.expected_attach_type = expected_attach_type; | 1535 | load_attr.expected_attach_type = prog->expected_attach_type; |
| 1311 | load_attr.name = name; | 1536 | if (prog->caps->name) |
| 1537 | load_attr.name = prog->name; | ||
| 1312 | load_attr.insns = insns; | 1538 | load_attr.insns = insns; |
| 1313 | load_attr.insns_cnt = insns_cnt; | 1539 | load_attr.insns_cnt = insns_cnt; |
| 1314 | load_attr.license = license; | 1540 | load_attr.license = license; |
| 1315 | load_attr.kern_version = kern_version; | 1541 | load_attr.kern_version = kern_version; |
| 1316 | load_attr.prog_ifindex = prog_ifindex; | 1542 | load_attr.prog_ifindex = prog->prog_ifindex; |
| 1317 | 1543 | load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0; | |
| 1544 | load_attr.func_info = prog->func_info; | ||
| 1545 | load_attr.func_info_rec_size = prog->func_info_rec_size; | ||
| 1546 | load_attr.func_info_cnt = prog->func_info_cnt; | ||
| 1547 | load_attr.line_info = prog->line_info; | ||
| 1548 | load_attr.line_info_rec_size = prog->line_info_rec_size; | ||
| 1549 | load_attr.line_info_cnt = prog->line_info_cnt; | ||
| 1318 | if (!load_attr.insns || !load_attr.insns_cnt) | 1550 | if (!load_attr.insns || !load_attr.insns_cnt) |
| 1319 | return -EINVAL; | 1551 | return -EINVAL; |
| 1320 | 1552 | ||
| @@ -1394,10 +1626,8 @@ bpf_program__load(struct bpf_program *prog, | |||
| 1394 | pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", | 1626 | pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", |
| 1395 | prog->section_name, prog->instances.nr); | 1627 | prog->section_name, prog->instances.nr); |
| 1396 | } | 1628 | } |
| 1397 | err = load_program(prog->type, prog->expected_attach_type, | 1629 | err = load_program(prog, prog->insns, prog->insns_cnt, |
| 1398 | prog->name, prog->insns, prog->insns_cnt, | 1630 | license, kern_version, &fd); |
| 1399 | license, kern_version, &fd, | ||
| 1400 | prog->prog_ifindex); | ||
| 1401 | if (!err) | 1631 | if (!err) |
| 1402 | prog->instances.fds[0] = fd; | 1632 | prog->instances.fds[0] = fd; |
| 1403 | goto out; | 1633 | goto out; |
| @@ -1425,11 +1655,9 @@ bpf_program__load(struct bpf_program *prog, | |||
| 1425 | continue; | 1655 | continue; |
| 1426 | } | 1656 | } |
| 1427 | 1657 | ||
| 1428 | err = load_program(prog->type, prog->expected_attach_type, | 1658 | err = load_program(prog, result.new_insn_ptr, |
| 1429 | prog->name, result.new_insn_ptr, | ||
| 1430 | result.new_insn_cnt, | 1659 | result.new_insn_cnt, |
| 1431 | license, kern_version, &fd, | 1660 | license, kern_version, &fd); |
| 1432 | prog->prog_ifindex); | ||
| 1433 | 1661 | ||
| 1434 | if (err) { | 1662 | if (err) { |
| 1435 | pr_warning("Loading the %dth instance of program '%s' failed\n", | 1663 | pr_warning("Loading the %dth instance of program '%s' failed\n", |
| @@ -1495,12 +1723,12 @@ static bool bpf_prog_type__needs_kver(enum bpf_prog_type type) | |||
| 1495 | case BPF_PROG_TYPE_LIRC_MODE2: | 1723 | case BPF_PROG_TYPE_LIRC_MODE2: |
| 1496 | case BPF_PROG_TYPE_SK_REUSEPORT: | 1724 | case BPF_PROG_TYPE_SK_REUSEPORT: |
| 1497 | case BPF_PROG_TYPE_FLOW_DISSECTOR: | 1725 | case BPF_PROG_TYPE_FLOW_DISSECTOR: |
| 1498 | return false; | ||
| 1499 | case BPF_PROG_TYPE_UNSPEC: | 1726 | case BPF_PROG_TYPE_UNSPEC: |
| 1500 | case BPF_PROG_TYPE_KPROBE: | ||
| 1501 | case BPF_PROG_TYPE_TRACEPOINT: | 1727 | case BPF_PROG_TYPE_TRACEPOINT: |
| 1502 | case BPF_PROG_TYPE_PERF_EVENT: | ||
| 1503 | case BPF_PROG_TYPE_RAW_TRACEPOINT: | 1728 | case BPF_PROG_TYPE_RAW_TRACEPOINT: |
| 1729 | case BPF_PROG_TYPE_PERF_EVENT: | ||
| 1730 | return false; | ||
| 1731 | case BPF_PROG_TYPE_KPROBE: | ||
| 1504 | default: | 1732 | default: |
| 1505 | return true; | 1733 | return true; |
| 1506 | } | 1734 | } |
| @@ -1627,6 +1855,7 @@ int bpf_object__load(struct bpf_object *obj) | |||
| 1627 | 1855 | ||
| 1628 | obj->loaded = true; | 1856 | obj->loaded = true; |
| 1629 | 1857 | ||
| 1858 | CHECK_ERR(bpf_object__probe_caps(obj), err, out); | ||
| 1630 | CHECK_ERR(bpf_object__create_maps(obj), err, out); | 1859 | CHECK_ERR(bpf_object__create_maps(obj), err, out); |
| 1631 | CHECK_ERR(bpf_object__relocate(obj), err, out); | 1860 | CHECK_ERR(bpf_object__relocate(obj), err, out); |
| 1632 | CHECK_ERR(bpf_object__load_progs(obj), err, out); | 1861 | CHECK_ERR(bpf_object__load_progs(obj), err, out); |
| @@ -1699,6 +1928,34 @@ int bpf_program__pin_instance(struct bpf_program *prog, const char *path, | |||
| 1699 | return 0; | 1928 | return 0; |
| 1700 | } | 1929 | } |
| 1701 | 1930 | ||
| 1931 | int bpf_program__unpin_instance(struct bpf_program *prog, const char *path, | ||
| 1932 | int instance) | ||
| 1933 | { | ||
| 1934 | int err; | ||
| 1935 | |||
| 1936 | err = check_path(path); | ||
| 1937 | if (err) | ||
| 1938 | return err; | ||
| 1939 | |||
| 1940 | if (prog == NULL) { | ||
| 1941 | pr_warning("invalid program pointer\n"); | ||
| 1942 | return -EINVAL; | ||
| 1943 | } | ||
| 1944 | |||
| 1945 | if (instance < 0 || instance >= prog->instances.nr) { | ||
| 1946 | pr_warning("invalid prog instance %d of prog %s (max %d)\n", | ||
| 1947 | instance, prog->section_name, prog->instances.nr); | ||
| 1948 | return -EINVAL; | ||
| 1949 | } | ||
| 1950 | |||
| 1951 | err = unlink(path); | ||
| 1952 | if (err != 0) | ||
| 1953 | return -errno; | ||
| 1954 | pr_debug("unpinned program '%s'\n", path); | ||
| 1955 | |||
| 1956 | return 0; | ||
| 1957 | } | ||
| 1958 | |||
| 1702 | static int make_dir(const char *path) | 1959 | static int make_dir(const char *path) |
| 1703 | { | 1960 | { |
| 1704 | char *cp, errmsg[STRERR_BUFSIZE]; | 1961 | char *cp, errmsg[STRERR_BUFSIZE]; |
| @@ -1733,6 +1990,11 @@ int bpf_program__pin(struct bpf_program *prog, const char *path) | |||
| 1733 | return -EINVAL; | 1990 | return -EINVAL; |
| 1734 | } | 1991 | } |
| 1735 | 1992 | ||
| 1993 | if (prog->instances.nr == 1) { | ||
| 1994 | /* don't create subdirs when pinning single instance */ | ||
| 1995 | return bpf_program__pin_instance(prog, path, 0); | ||
| 1996 | } | ||
| 1997 | |||
| 1736 | err = make_dir(path); | 1998 | err = make_dir(path); |
| 1737 | if (err) | 1999 | if (err) |
| 1738 | return err; | 2000 | return err; |
| @@ -1742,16 +2004,83 @@ int bpf_program__pin(struct bpf_program *prog, const char *path) | |||
| 1742 | int len; | 2004 | int len; |
| 1743 | 2005 | ||
| 1744 | len = snprintf(buf, PATH_MAX, "%s/%d", path, i); | 2006 | len = snprintf(buf, PATH_MAX, "%s/%d", path, i); |
| 2007 | if (len < 0) { | ||
| 2008 | err = -EINVAL; | ||
| 2009 | goto err_unpin; | ||
| 2010 | } else if (len >= PATH_MAX) { | ||
| 2011 | err = -ENAMETOOLONG; | ||
| 2012 | goto err_unpin; | ||
| 2013 | } | ||
| 2014 | |||
| 2015 | err = bpf_program__pin_instance(prog, buf, i); | ||
| 2016 | if (err) | ||
| 2017 | goto err_unpin; | ||
| 2018 | } | ||
| 2019 | |||
| 2020 | return 0; | ||
| 2021 | |||
| 2022 | err_unpin: | ||
| 2023 | for (i = i - 1; i >= 0; i--) { | ||
| 2024 | char buf[PATH_MAX]; | ||
| 2025 | int len; | ||
| 2026 | |||
| 2027 | len = snprintf(buf, PATH_MAX, "%s/%d", path, i); | ||
| 2028 | if (len < 0) | ||
| 2029 | continue; | ||
| 2030 | else if (len >= PATH_MAX) | ||
| 2031 | continue; | ||
| 2032 | |||
| 2033 | bpf_program__unpin_instance(prog, buf, i); | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | rmdir(path); | ||
| 2037 | |||
| 2038 | return err; | ||
| 2039 | } | ||
| 2040 | |||
| 2041 | int bpf_program__unpin(struct bpf_program *prog, const char *path) | ||
| 2042 | { | ||
| 2043 | int i, err; | ||
| 2044 | |||
| 2045 | err = check_path(path); | ||
| 2046 | if (err) | ||
| 2047 | return err; | ||
| 2048 | |||
| 2049 | if (prog == NULL) { | ||
| 2050 | pr_warning("invalid program pointer\n"); | ||
| 2051 | return -EINVAL; | ||
| 2052 | } | ||
| 2053 | |||
| 2054 | if (prog->instances.nr <= 0) { | ||
| 2055 | pr_warning("no instances of prog %s to pin\n", | ||
| 2056 | prog->section_name); | ||
| 2057 | return -EINVAL; | ||
| 2058 | } | ||
| 2059 | |||
| 2060 | if (prog->instances.nr == 1) { | ||
| 2061 | /* don't create subdirs when pinning single instance */ | ||
| 2062 | return bpf_program__unpin_instance(prog, path, 0); | ||
| 2063 | } | ||
| 2064 | |||
| 2065 | for (i = 0; i < prog->instances.nr; i++) { | ||
| 2066 | char buf[PATH_MAX]; | ||
| 2067 | int len; | ||
| 2068 | |||
| 2069 | len = snprintf(buf, PATH_MAX, "%s/%d", path, i); | ||
| 1745 | if (len < 0) | 2070 | if (len < 0) |
| 1746 | return -EINVAL; | 2071 | return -EINVAL; |
| 1747 | else if (len >= PATH_MAX) | 2072 | else if (len >= PATH_MAX) |
| 1748 | return -ENAMETOOLONG; | 2073 | return -ENAMETOOLONG; |
| 1749 | 2074 | ||
| 1750 | err = bpf_program__pin_instance(prog, buf, i); | 2075 | err = bpf_program__unpin_instance(prog, buf, i); |
| 1751 | if (err) | 2076 | if (err) |
| 1752 | return err; | 2077 | return err; |
| 1753 | } | 2078 | } |
| 1754 | 2079 | ||
| 2080 | err = rmdir(path); | ||
| 2081 | if (err) | ||
| 2082 | return -errno; | ||
| 2083 | |||
| 1755 | return 0; | 2084 | return 0; |
| 1756 | } | 2085 | } |
| 1757 | 2086 | ||
| @@ -1776,12 +2105,33 @@ int bpf_map__pin(struct bpf_map *map, const char *path) | |||
| 1776 | } | 2105 | } |
| 1777 | 2106 | ||
| 1778 | pr_debug("pinned map '%s'\n", path); | 2107 | pr_debug("pinned map '%s'\n", path); |
| 2108 | |||
| 1779 | return 0; | 2109 | return 0; |
| 1780 | } | 2110 | } |
| 1781 | 2111 | ||
| 1782 | int bpf_object__pin(struct bpf_object *obj, const char *path) | 2112 | int bpf_map__unpin(struct bpf_map *map, const char *path) |
| 2113 | { | ||
| 2114 | int err; | ||
| 2115 | |||
| 2116 | err = check_path(path); | ||
| 2117 | if (err) | ||
| 2118 | return err; | ||
| 2119 | |||
| 2120 | if (map == NULL) { | ||
| 2121 | pr_warning("invalid map pointer\n"); | ||
| 2122 | return -EINVAL; | ||
| 2123 | } | ||
| 2124 | |||
| 2125 | err = unlink(path); | ||
| 2126 | if (err != 0) | ||
| 2127 | return -errno; | ||
| 2128 | pr_debug("unpinned map '%s'\n", path); | ||
| 2129 | |||
| 2130 | return 0; | ||
| 2131 | } | ||
| 2132 | |||
| 2133 | int bpf_object__pin_maps(struct bpf_object *obj, const char *path) | ||
| 1783 | { | 2134 | { |
| 1784 | struct bpf_program *prog; | ||
| 1785 | struct bpf_map *map; | 2135 | struct bpf_map *map; |
| 1786 | int err; | 2136 | int err; |
| 1787 | 2137 | ||
| @@ -1803,28 +2153,142 @@ int bpf_object__pin(struct bpf_object *obj, const char *path) | |||
| 1803 | 2153 | ||
| 1804 | len = snprintf(buf, PATH_MAX, "%s/%s", path, | 2154 | len = snprintf(buf, PATH_MAX, "%s/%s", path, |
| 1805 | bpf_map__name(map)); | 2155 | bpf_map__name(map)); |
| 2156 | if (len < 0) { | ||
| 2157 | err = -EINVAL; | ||
| 2158 | goto err_unpin_maps; | ||
| 2159 | } else if (len >= PATH_MAX) { | ||
| 2160 | err = -ENAMETOOLONG; | ||
| 2161 | goto err_unpin_maps; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | err = bpf_map__pin(map, buf); | ||
| 2165 | if (err) | ||
| 2166 | goto err_unpin_maps; | ||
| 2167 | } | ||
| 2168 | |||
| 2169 | return 0; | ||
| 2170 | |||
| 2171 | err_unpin_maps: | ||
| 2172 | while ((map = bpf_map__prev(map, obj))) { | ||
| 2173 | char buf[PATH_MAX]; | ||
| 2174 | int len; | ||
| 2175 | |||
| 2176 | len = snprintf(buf, PATH_MAX, "%s/%s", path, | ||
| 2177 | bpf_map__name(map)); | ||
| 2178 | if (len < 0) | ||
| 2179 | continue; | ||
| 2180 | else if (len >= PATH_MAX) | ||
| 2181 | continue; | ||
| 2182 | |||
| 2183 | bpf_map__unpin(map, buf); | ||
| 2184 | } | ||
| 2185 | |||
| 2186 | return err; | ||
| 2187 | } | ||
| 2188 | |||
| 2189 | int bpf_object__unpin_maps(struct bpf_object *obj, const char *path) | ||
| 2190 | { | ||
| 2191 | struct bpf_map *map; | ||
| 2192 | int err; | ||
| 2193 | |||
| 2194 | if (!obj) | ||
| 2195 | return -ENOENT; | ||
| 2196 | |||
| 2197 | bpf_map__for_each(map, obj) { | ||
| 2198 | char buf[PATH_MAX]; | ||
| 2199 | int len; | ||
| 2200 | |||
| 2201 | len = snprintf(buf, PATH_MAX, "%s/%s", path, | ||
| 2202 | bpf_map__name(map)); | ||
| 1806 | if (len < 0) | 2203 | if (len < 0) |
| 1807 | return -EINVAL; | 2204 | return -EINVAL; |
| 1808 | else if (len >= PATH_MAX) | 2205 | else if (len >= PATH_MAX) |
| 1809 | return -ENAMETOOLONG; | 2206 | return -ENAMETOOLONG; |
| 1810 | 2207 | ||
| 1811 | err = bpf_map__pin(map, buf); | 2208 | err = bpf_map__unpin(map, buf); |
| 1812 | if (err) | 2209 | if (err) |
| 1813 | return err; | 2210 | return err; |
| 1814 | } | 2211 | } |
| 1815 | 2212 | ||
| 2213 | return 0; | ||
| 2214 | } | ||
| 2215 | |||
| 2216 | int bpf_object__pin_programs(struct bpf_object *obj, const char *path) | ||
| 2217 | { | ||
| 2218 | struct bpf_program *prog; | ||
| 2219 | int err; | ||
| 2220 | |||
| 2221 | if (!obj) | ||
| 2222 | return -ENOENT; | ||
| 2223 | |||
| 2224 | if (!obj->loaded) { | ||
| 2225 | pr_warning("object not yet loaded; load it first\n"); | ||
| 2226 | return -ENOENT; | ||
| 2227 | } | ||
| 2228 | |||
| 2229 | err = make_dir(path); | ||
| 2230 | if (err) | ||
| 2231 | return err; | ||
| 2232 | |||
| 1816 | bpf_object__for_each_program(prog, obj) { | 2233 | bpf_object__for_each_program(prog, obj) { |
| 1817 | char buf[PATH_MAX]; | 2234 | char buf[PATH_MAX]; |
| 1818 | int len; | 2235 | int len; |
| 1819 | 2236 | ||
| 1820 | len = snprintf(buf, PATH_MAX, "%s/%s", path, | 2237 | len = snprintf(buf, PATH_MAX, "%s/%s", path, |
| 1821 | prog->section_name); | 2238 | prog->pin_name); |
| 2239 | if (len < 0) { | ||
| 2240 | err = -EINVAL; | ||
| 2241 | goto err_unpin_programs; | ||
| 2242 | } else if (len >= PATH_MAX) { | ||
| 2243 | err = -ENAMETOOLONG; | ||
| 2244 | goto err_unpin_programs; | ||
| 2245 | } | ||
| 2246 | |||
| 2247 | err = bpf_program__pin(prog, buf); | ||
| 2248 | if (err) | ||
| 2249 | goto err_unpin_programs; | ||
| 2250 | } | ||
| 2251 | |||
| 2252 | return 0; | ||
| 2253 | |||
| 2254 | err_unpin_programs: | ||
| 2255 | while ((prog = bpf_program__prev(prog, obj))) { | ||
| 2256 | char buf[PATH_MAX]; | ||
| 2257 | int len; | ||
| 2258 | |||
| 2259 | len = snprintf(buf, PATH_MAX, "%s/%s", path, | ||
| 2260 | prog->pin_name); | ||
| 2261 | if (len < 0) | ||
| 2262 | continue; | ||
| 2263 | else if (len >= PATH_MAX) | ||
| 2264 | continue; | ||
| 2265 | |||
| 2266 | bpf_program__unpin(prog, buf); | ||
| 2267 | } | ||
| 2268 | |||
| 2269 | return err; | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | int bpf_object__unpin_programs(struct bpf_object *obj, const char *path) | ||
| 2273 | { | ||
| 2274 | struct bpf_program *prog; | ||
| 2275 | int err; | ||
| 2276 | |||
| 2277 | if (!obj) | ||
| 2278 | return -ENOENT; | ||
| 2279 | |||
| 2280 | bpf_object__for_each_program(prog, obj) { | ||
| 2281 | char buf[PATH_MAX]; | ||
| 2282 | int len; | ||
| 2283 | |||
| 2284 | len = snprintf(buf, PATH_MAX, "%s/%s", path, | ||
| 2285 | prog->pin_name); | ||
| 1822 | if (len < 0) | 2286 | if (len < 0) |
| 1823 | return -EINVAL; | 2287 | return -EINVAL; |
| 1824 | else if (len >= PATH_MAX) | 2288 | else if (len >= PATH_MAX) |
| 1825 | return -ENAMETOOLONG; | 2289 | return -ENAMETOOLONG; |
| 1826 | 2290 | ||
| 1827 | err = bpf_program__pin(prog, buf); | 2291 | err = bpf_program__unpin(prog, buf); |
| 1828 | if (err) | 2292 | if (err) |
| 1829 | return err; | 2293 | return err; |
| 1830 | } | 2294 | } |
| @@ -1832,6 +2296,23 @@ int bpf_object__pin(struct bpf_object *obj, const char *path) | |||
| 1832 | return 0; | 2296 | return 0; |
| 1833 | } | 2297 | } |
| 1834 | 2298 | ||
| 2299 | int bpf_object__pin(struct bpf_object *obj, const char *path) | ||
| 2300 | { | ||
| 2301 | int err; | ||
| 2302 | |||
| 2303 | err = bpf_object__pin_maps(obj, path); | ||
| 2304 | if (err) | ||
| 2305 | return err; | ||
| 2306 | |||
| 2307 | err = bpf_object__pin_programs(obj, path); | ||
| 2308 | if (err) { | ||
| 2309 | bpf_object__unpin_maps(obj, path); | ||
| 2310 | return err; | ||
| 2311 | } | ||
| 2312 | |||
| 2313 | return 0; | ||
| 2314 | } | ||
| 2315 | |||
| 1835 | void bpf_object__close(struct bpf_object *obj) | 2316 | void bpf_object__close(struct bpf_object *obj) |
| 1836 | { | 2317 | { |
| 1837 | size_t i; | 2318 | size_t i; |
| @@ -1845,6 +2326,7 @@ void bpf_object__close(struct bpf_object *obj) | |||
| 1845 | bpf_object__elf_finish(obj); | 2326 | bpf_object__elf_finish(obj); |
| 1846 | bpf_object__unload(obj); | 2327 | bpf_object__unload(obj); |
| 1847 | btf__free(obj->btf); | 2328 | btf__free(obj->btf); |
| 2329 | btf_ext__free(obj->btf_ext); | ||
| 1848 | 2330 | ||
| 1849 | for (i = 0; i < obj->nr_maps; i++) { | 2331 | for (i = 0; i < obj->nr_maps; i++) { |
| 1850 | zfree(&obj->maps[i].name); | 2332 | zfree(&obj->maps[i].name); |
| @@ -1918,23 +2400,26 @@ void *bpf_object__priv(struct bpf_object *obj) | |||
| 1918 | } | 2400 | } |
| 1919 | 2401 | ||
| 1920 | static struct bpf_program * | 2402 | static struct bpf_program * |
| 1921 | __bpf_program__next(struct bpf_program *prev, struct bpf_object *obj) | 2403 | __bpf_program__iter(struct bpf_program *p, struct bpf_object *obj, bool forward) |
| 1922 | { | 2404 | { |
| 1923 | size_t idx; | 2405 | size_t nr_programs = obj->nr_programs; |
| 2406 | ssize_t idx; | ||
| 1924 | 2407 | ||
| 1925 | if (!obj->programs) | 2408 | if (!nr_programs) |
| 1926 | return NULL; | 2409 | return NULL; |
| 1927 | /* First handler */ | ||
| 1928 | if (prev == NULL) | ||
| 1929 | return &obj->programs[0]; | ||
| 1930 | 2410 | ||
| 1931 | if (prev->obj != obj) { | 2411 | if (!p) |
| 2412 | /* Iter from the beginning */ | ||
| 2413 | return forward ? &obj->programs[0] : | ||
| 2414 | &obj->programs[nr_programs - 1]; | ||
| 2415 | |||
| 2416 | if (p->obj != obj) { | ||
| 1932 | pr_warning("error: program handler doesn't match object\n"); | 2417 | pr_warning("error: program handler doesn't match object\n"); |
| 1933 | return NULL; | 2418 | return NULL; |
| 1934 | } | 2419 | } |
| 1935 | 2420 | ||
| 1936 | idx = (prev - obj->programs) + 1; | 2421 | idx = (p - obj->programs) + (forward ? 1 : -1); |
| 1937 | if (idx >= obj->nr_programs) | 2422 | if (idx >= obj->nr_programs || idx < 0) |
| 1938 | return NULL; | 2423 | return NULL; |
| 1939 | return &obj->programs[idx]; | 2424 | return &obj->programs[idx]; |
| 1940 | } | 2425 | } |
| @@ -1945,7 +2430,19 @@ bpf_program__next(struct bpf_program *prev, struct bpf_object *obj) | |||
| 1945 | struct bpf_program *prog = prev; | 2430 | struct bpf_program *prog = prev; |
| 1946 | 2431 | ||
| 1947 | do { | 2432 | do { |
| 1948 | prog = __bpf_program__next(prog, obj); | 2433 | prog = __bpf_program__iter(prog, obj, true); |
| 2434 | } while (prog && bpf_program__is_function_storage(prog, obj)); | ||
| 2435 | |||
| 2436 | return prog; | ||
| 2437 | } | ||
| 2438 | |||
| 2439 | struct bpf_program * | ||
| 2440 | bpf_program__prev(struct bpf_program *next, struct bpf_object *obj) | ||
| 2441 | { | ||
| 2442 | struct bpf_program *prog = next; | ||
| 2443 | |||
| 2444 | do { | ||
| 2445 | prog = __bpf_program__iter(prog, obj, false); | ||
| 1949 | } while (prog && bpf_program__is_function_storage(prog, obj)); | 2446 | } while (prog && bpf_program__is_function_storage(prog, obj)); |
| 1950 | 2447 | ||
| 1951 | return prog; | 2448 | return prog; |
| @@ -2272,10 +2769,24 @@ void bpf_map__set_ifindex(struct bpf_map *map, __u32 ifindex) | |||
| 2272 | map->map_ifindex = ifindex; | 2769 | map->map_ifindex = ifindex; |
| 2273 | } | 2770 | } |
| 2274 | 2771 | ||
| 2275 | struct bpf_map * | 2772 | int bpf_map__set_inner_map_fd(struct bpf_map *map, int fd) |
| 2276 | bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) | ||
| 2277 | { | 2773 | { |
| 2278 | size_t idx; | 2774 | if (!bpf_map_type__is_map_in_map(map->def.type)) { |
| 2775 | pr_warning("error: unsupported map type\n"); | ||
| 2776 | return -EINVAL; | ||
| 2777 | } | ||
| 2778 | if (map->inner_map_fd != -1) { | ||
| 2779 | pr_warning("error: inner_map_fd already specified\n"); | ||
| 2780 | return -EINVAL; | ||
| 2781 | } | ||
| 2782 | map->inner_map_fd = fd; | ||
| 2783 | return 0; | ||
| 2784 | } | ||
| 2785 | |||
| 2786 | static struct bpf_map * | ||
| 2787 | __bpf_map__iter(struct bpf_map *m, struct bpf_object *obj, int i) | ||
| 2788 | { | ||
| 2789 | ssize_t idx; | ||
| 2279 | struct bpf_map *s, *e; | 2790 | struct bpf_map *s, *e; |
| 2280 | 2791 | ||
| 2281 | if (!obj || !obj->maps) | 2792 | if (!obj || !obj->maps) |
| @@ -2284,22 +2795,40 @@ bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) | |||
| 2284 | s = obj->maps; | 2795 | s = obj->maps; |
| 2285 | e = obj->maps + obj->nr_maps; | 2796 | e = obj->maps + obj->nr_maps; |
| 2286 | 2797 | ||
| 2287 | if (prev == NULL) | 2798 | if ((m < s) || (m >= e)) { |
| 2288 | return s; | ||
| 2289 | |||
| 2290 | if ((prev < s) || (prev >= e)) { | ||
| 2291 | pr_warning("error in %s: map handler doesn't belong to object\n", | 2799 | pr_warning("error in %s: map handler doesn't belong to object\n", |
| 2292 | __func__); | 2800 | __func__); |
| 2293 | return NULL; | 2801 | return NULL; |
| 2294 | } | 2802 | } |
| 2295 | 2803 | ||
| 2296 | idx = (prev - obj->maps) + 1; | 2804 | idx = (m - obj->maps) + i; |
| 2297 | if (idx >= obj->nr_maps) | 2805 | if (idx >= obj->nr_maps || idx < 0) |
| 2298 | return NULL; | 2806 | return NULL; |
| 2299 | return &obj->maps[idx]; | 2807 | return &obj->maps[idx]; |
| 2300 | } | 2808 | } |
| 2301 | 2809 | ||
| 2302 | struct bpf_map * | 2810 | struct bpf_map * |
| 2811 | bpf_map__next(struct bpf_map *prev, struct bpf_object *obj) | ||
| 2812 | { | ||
| 2813 | if (prev == NULL) | ||
| 2814 | return obj->maps; | ||
| 2815 | |||
| 2816 | return __bpf_map__iter(prev, obj, 1); | ||
| 2817 | } | ||
| 2818 | |||
| 2819 | struct bpf_map * | ||
| 2820 | bpf_map__prev(struct bpf_map *next, struct bpf_object *obj) | ||
| 2821 | { | ||
| 2822 | if (next == NULL) { | ||
| 2823 | if (!obj->nr_maps) | ||
| 2824 | return NULL; | ||
| 2825 | return obj->maps + obj->nr_maps - 1; | ||
| 2826 | } | ||
| 2827 | |||
| 2828 | return __bpf_map__iter(next, obj, -1); | ||
| 2829 | } | ||
| 2830 | |||
| 2831 | struct bpf_map * | ||
| 2303 | bpf_object__find_map_by_name(struct bpf_object *obj, const char *name) | 2832 | bpf_object__find_map_by_name(struct bpf_object *obj, const char *name) |
| 2304 | { | 2833 | { |
| 2305 | struct bpf_map *pos; | 2834 | struct bpf_map *pos; |
