diff options
author | Wang Nan <wangnan0@huawei.com> | 2015-11-06 08:49:37 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-11-06 13:52:41 -0500 |
commit | 6371ca3b541c82d8aa6a9002bd52d92bcdda5944 (patch) | |
tree | a5cd09ea0ceb52772570d9ba7d24ccb971ed0c18 /tools/lib | |
parent | 0a62f6869f2768687af2c94d97f3b2fcf5b73367 (diff) |
bpf tools: Improve libbpf error reporting
In this patch, a series of libbpf specific error numbers and
libbpf_strerror() are introduced to help reporting errors.
Functions are updated to pass correct the error number through the
CHECK_ERR() macro.
All users of bpf_object__open{_buffer}() and bpf_program__title() in
perf are modified accordingly. In addition, due to the error codes
changing, bpf__strerror_load() is also modified to use them.
bpf__strerror_head() is also changed accordingly so it can parse libbpf
errors. bpf_loader_strerror() is introduced for that purpose, and will
be improved by the following patch.
load_program() is improved not to dump log buffer if it is empty. log
buffer is also used to deduce whether the error was caused by an invalid
program or other problem.
v1 -> v2:
- Using macro for error code.
- Fetch error message based on array index, eliminate for-loop.
- Use log buffer to detect the reason of failure. 3 new error code
are introduced to replace LIBBPF_ERRNO__LOAD.
In v1:
# perf record -e ./test_ill_program.o ls
event syntax error: './test_ill_program.o'
\___ Failed to load program: Validate your program and check 'license'/'version' sections in your object
SKIP
# perf record -e ./test_kversion_nomatch_program.o ls
event syntax error: './test_kversion_nomatch_program.o'
\___ Failed to load program: Validate your program and check 'license'/'version' sections in your object
SKIP
# perf record -e ./test_big_program.o ls
event syntax error: './test_big_program.o'
\___ Failed to load program: Validate your program and check 'license'/'version' sections in your object
SKIP
In v2:
# perf record -e ./test_ill_program.o ls
event syntax error: './test_ill_program.o'
\___ Kernel verifier blocks program loading
SKIP
# perf record -e ./test_kversion_nomatch_program.o
event syntax error: './test_kversion_nomatch_program.o'
\___ Incorrect kernel version
SKIP
(Will be further improved by following patches)
# perf record -e ./test_big_program.o
event syntax error: './test_big_program.o'
\___ Program too big
SKIP
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1446817783-86722-2-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib')
-rw-r--r-- | tools/lib/bpf/libbpf.c | 159 | ||||
-rw-r--r-- | tools/lib/bpf/libbpf.h | 20 |
2 files changed, 130 insertions, 49 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 9f3c8cf9249b..07b492d3dfaa 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -61,6 +61,60 @@ void libbpf_set_print(libbpf_print_fn_t warn, | |||
61 | __pr_debug = debug; | 61 | __pr_debug = debug; |
62 | } | 62 | } |
63 | 63 | ||
64 | #define STRERR_BUFSIZE 128 | ||
65 | |||
66 | #define ERRNO_OFFSET(e) ((e) - __LIBBPF_ERRNO__START) | ||
67 | #define ERRCODE_OFFSET(c) ERRNO_OFFSET(LIBBPF_ERRNO__##c) | ||
68 | #define NR_ERRNO (__LIBBPF_ERRNO__END - __LIBBPF_ERRNO__START) | ||
69 | |||
70 | static const char *libbpf_strerror_table[NR_ERRNO] = { | ||
71 | [ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf", | ||
72 | [ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid", | ||
73 | [ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost", | ||
74 | [ERRCODE_OFFSET(ENDIAN)] = "Endian missmatch", | ||
75 | [ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf", | ||
76 | [ERRCODE_OFFSET(RELOC)] = "Relocation failed", | ||
77 | [ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading", | ||
78 | [ERRCODE_OFFSET(PROG2BIG)] = "Program too big", | ||
79 | [ERRCODE_OFFSET(KVER)] = "Incorrect kernel version", | ||
80 | }; | ||
81 | |||
82 | int libbpf_strerror(int err, char *buf, size_t size) | ||
83 | { | ||
84 | if (!buf || !size) | ||
85 | return -1; | ||
86 | |||
87 | err = err > 0 ? err : -err; | ||
88 | |||
89 | if (err < __LIBBPF_ERRNO__START) { | ||
90 | int ret; | ||
91 | |||
92 | ret = strerror_r(err, buf, size); | ||
93 | buf[size - 1] = '\0'; | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | if (err < __LIBBPF_ERRNO__END) { | ||
98 | const char *msg; | ||
99 | |||
100 | msg = libbpf_strerror_table[ERRNO_OFFSET(err)]; | ||
101 | snprintf(buf, size, "%s", msg); | ||
102 | buf[size - 1] = '\0'; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | snprintf(buf, size, "Unknown libbpf error %d", err); | ||
107 | buf[size - 1] = '\0'; | ||
108 | return -1; | ||
109 | } | ||
110 | |||
111 | #define CHECK_ERR(action, err, out) do { \ | ||
112 | err = action; \ | ||
113 | if (err) \ | ||
114 | goto out; \ | ||
115 | } while(0) | ||
116 | |||
117 | |||
64 | /* Copied from tools/perf/util/util.h */ | 118 | /* Copied from tools/perf/util/util.h */ |
65 | #ifndef zfree | 119 | #ifndef zfree |
66 | # define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) | 120 | # define zfree(ptr) ({ free(*ptr); *ptr = NULL; }) |
@@ -258,7 +312,7 @@ static struct bpf_object *bpf_object__new(const char *path, | |||
258 | obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1); | 312 | obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1); |
259 | if (!obj) { | 313 | if (!obj) { |
260 | pr_warning("alloc memory failed for %s\n", path); | 314 | pr_warning("alloc memory failed for %s\n", path); |
261 | return NULL; | 315 | return ERR_PTR(-ENOMEM); |
262 | } | 316 | } |
263 | 317 | ||
264 | strcpy(obj->path, path); | 318 | strcpy(obj->path, path); |
@@ -305,7 +359,7 @@ static int bpf_object__elf_init(struct bpf_object *obj) | |||
305 | 359 | ||
306 | if (obj_elf_valid(obj)) { | 360 | if (obj_elf_valid(obj)) { |
307 | pr_warning("elf init: internal error\n"); | 361 | pr_warning("elf init: internal error\n"); |
308 | return -EEXIST; | 362 | return -LIBBPF_ERRNO__LIBELF; |
309 | } | 363 | } |
310 | 364 | ||
311 | if (obj->efile.obj_buf_sz > 0) { | 365 | if (obj->efile.obj_buf_sz > 0) { |
@@ -331,14 +385,14 @@ static int bpf_object__elf_init(struct bpf_object *obj) | |||
331 | if (!obj->efile.elf) { | 385 | if (!obj->efile.elf) { |
332 | pr_warning("failed to open %s as ELF file\n", | 386 | pr_warning("failed to open %s as ELF file\n", |
333 | obj->path); | 387 | obj->path); |
334 | err = -EINVAL; | 388 | err = -LIBBPF_ERRNO__LIBELF; |
335 | goto errout; | 389 | goto errout; |
336 | } | 390 | } |
337 | 391 | ||
338 | if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) { | 392 | if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) { |
339 | pr_warning("failed to get EHDR from %s\n", | 393 | pr_warning("failed to get EHDR from %s\n", |
340 | obj->path); | 394 | obj->path); |
341 | err = -EINVAL; | 395 | err = -LIBBPF_ERRNO__FORMAT; |
342 | goto errout; | 396 | goto errout; |
343 | } | 397 | } |
344 | ep = &obj->efile.ehdr; | 398 | ep = &obj->efile.ehdr; |
@@ -346,7 +400,7 @@ static int bpf_object__elf_init(struct bpf_object *obj) | |||
346 | if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) { | 400 | if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) { |
347 | pr_warning("%s is not an eBPF object file\n", | 401 | pr_warning("%s is not an eBPF object file\n", |
348 | obj->path); | 402 | obj->path); |
349 | err = -EINVAL; | 403 | err = -LIBBPF_ERRNO__FORMAT; |
350 | goto errout; | 404 | goto errout; |
351 | } | 405 | } |
352 | 406 | ||
@@ -374,14 +428,14 @@ bpf_object__check_endianness(struct bpf_object *obj) | |||
374 | goto mismatch; | 428 | goto mismatch; |
375 | break; | 429 | break; |
376 | default: | 430 | default: |
377 | return -EINVAL; | 431 | return -LIBBPF_ERRNO__ENDIAN; |
378 | } | 432 | } |
379 | 433 | ||
380 | return 0; | 434 | return 0; |
381 | 435 | ||
382 | mismatch: | 436 | mismatch: |
383 | pr_warning("Error: endianness mismatch.\n"); | 437 | pr_warning("Error: endianness mismatch.\n"); |
384 | return -EINVAL; | 438 | return -LIBBPF_ERRNO__ENDIAN; |
385 | } | 439 | } |
386 | 440 | ||
387 | static int | 441 | static int |
@@ -402,7 +456,7 @@ bpf_object__init_kversion(struct bpf_object *obj, | |||
402 | 456 | ||
403 | if (size != sizeof(kver)) { | 457 | if (size != sizeof(kver)) { |
404 | pr_warning("invalid kver section in %s\n", obj->path); | 458 | pr_warning("invalid kver section in %s\n", obj->path); |
405 | return -EINVAL; | 459 | return -LIBBPF_ERRNO__FORMAT; |
406 | } | 460 | } |
407 | memcpy(&kver, data, sizeof(kver)); | 461 | memcpy(&kver, data, sizeof(kver)); |
408 | obj->kern_version = kver; | 462 | obj->kern_version = kver; |
@@ -444,7 +498,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
444 | if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) { | 498 | if (!elf_rawdata(elf_getscn(elf, ep->e_shstrndx), NULL)) { |
445 | pr_warning("failed to get e_shstrndx from %s\n", | 499 | pr_warning("failed to get e_shstrndx from %s\n", |
446 | obj->path); | 500 | obj->path); |
447 | return -EINVAL; | 501 | return -LIBBPF_ERRNO__FORMAT; |
448 | } | 502 | } |
449 | 503 | ||
450 | while ((scn = elf_nextscn(elf, scn)) != NULL) { | 504 | while ((scn = elf_nextscn(elf, scn)) != NULL) { |
@@ -456,7 +510,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
456 | if (gelf_getshdr(scn, &sh) != &sh) { | 510 | if (gelf_getshdr(scn, &sh) != &sh) { |
457 | pr_warning("failed to get section header from %s\n", | 511 | pr_warning("failed to get section header from %s\n", |
458 | obj->path); | 512 | obj->path); |
459 | err = -EINVAL; | 513 | err = -LIBBPF_ERRNO__FORMAT; |
460 | goto out; | 514 | goto out; |
461 | } | 515 | } |
462 | 516 | ||
@@ -464,7 +518,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
464 | if (!name) { | 518 | if (!name) { |
465 | pr_warning("failed to get section name from %s\n", | 519 | pr_warning("failed to get section name from %s\n", |
466 | obj->path); | 520 | obj->path); |
467 | err = -EINVAL; | 521 | err = -LIBBPF_ERRNO__FORMAT; |
468 | goto out; | 522 | goto out; |
469 | } | 523 | } |
470 | 524 | ||
@@ -472,7 +526,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
472 | if (!data) { | 526 | if (!data) { |
473 | pr_warning("failed to get section data from %s(%s)\n", | 527 | pr_warning("failed to get section data from %s(%s)\n", |
474 | name, obj->path); | 528 | name, obj->path); |
475 | err = -EINVAL; | 529 | err = -LIBBPF_ERRNO__FORMAT; |
476 | goto out; | 530 | goto out; |
477 | } | 531 | } |
478 | pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n", | 532 | pr_debug("section %s, size %ld, link %d, flags %lx, type=%d\n", |
@@ -495,7 +549,7 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
495 | if (obj->efile.symbols) { | 549 | if (obj->efile.symbols) { |
496 | pr_warning("bpf: multiple SYMTAB in %s\n", | 550 | pr_warning("bpf: multiple SYMTAB in %s\n", |
497 | obj->path); | 551 | obj->path); |
498 | err = -EEXIST; | 552 | err = -LIBBPF_ERRNO__FORMAT; |
499 | } else | 553 | } else |
500 | obj->efile.symbols = data; | 554 | obj->efile.symbols = data; |
501 | } else if ((sh.sh_type == SHT_PROGBITS) && | 555 | } else if ((sh.sh_type == SHT_PROGBITS) && |
@@ -504,7 +558,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj) | |||
504 | err = bpf_object__add_program(obj, data->d_buf, | 558 | err = bpf_object__add_program(obj, data->d_buf, |
505 | data->d_size, name, idx); | 559 | data->d_size, name, idx); |
506 | if (err) { | 560 | if (err) { |
507 | char errmsg[128]; | 561 | char errmsg[STRERR_BUFSIZE]; |
562 | |||
508 | strerror_r(-err, errmsg, sizeof(errmsg)); | 563 | strerror_r(-err, errmsg, sizeof(errmsg)); |
509 | pr_warning("failed to alloc program %s (%s): %s", | 564 | pr_warning("failed to alloc program %s (%s): %s", |
510 | name, obj->path, errmsg); | 565 | name, obj->path, errmsg); |
@@ -576,7 +631,7 @@ bpf_program__collect_reloc(struct bpf_program *prog, | |||
576 | 631 | ||
577 | if (!gelf_getrel(data, i, &rel)) { | 632 | if (!gelf_getrel(data, i, &rel)) { |
578 | pr_warning("relocation: failed to get %d reloc\n", i); | 633 | pr_warning("relocation: failed to get %d reloc\n", i); |
579 | return -EINVAL; | 634 | return -LIBBPF_ERRNO__FORMAT; |
580 | } | 635 | } |
581 | 636 | ||
582 | insn_idx = rel.r_offset / sizeof(struct bpf_insn); | 637 | insn_idx = rel.r_offset / sizeof(struct bpf_insn); |
@@ -587,20 +642,20 @@ bpf_program__collect_reloc(struct bpf_program *prog, | |||
587 | &sym)) { | 642 | &sym)) { |
588 | pr_warning("relocation: symbol %"PRIx64" not found\n", | 643 | pr_warning("relocation: symbol %"PRIx64" not found\n", |
589 | GELF_R_SYM(rel.r_info)); | 644 | GELF_R_SYM(rel.r_info)); |
590 | return -EINVAL; | 645 | return -LIBBPF_ERRNO__FORMAT; |
591 | } | 646 | } |
592 | 647 | ||
593 | if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) { | 648 | if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) { |
594 | pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n", | 649 | pr_warning("bpf: relocation: invalid relo for insns[%d].code 0x%x\n", |
595 | insn_idx, insns[insn_idx].code); | 650 | insn_idx, insns[insn_idx].code); |
596 | return -EINVAL; | 651 | return -LIBBPF_ERRNO__RELOC; |
597 | } | 652 | } |
598 | 653 | ||
599 | map_idx = sym.st_value / sizeof(struct bpf_map_def); | 654 | map_idx = sym.st_value / sizeof(struct bpf_map_def); |
600 | if (map_idx >= nr_maps) { | 655 | if (map_idx >= nr_maps) { |
601 | pr_warning("bpf relocation: map_idx %d large than %d\n", | 656 | pr_warning("bpf relocation: map_idx %d large than %d\n", |
602 | (int)map_idx, (int)nr_maps - 1); | 657 | (int)map_idx, (int)nr_maps - 1); |
603 | return -EINVAL; | 658 | return -LIBBPF_ERRNO__RELOC; |
604 | } | 659 | } |
605 | 660 | ||
606 | prog->reloc_desc[i].insn_idx = insn_idx; | 661 | prog->reloc_desc[i].insn_idx = insn_idx; |
@@ -683,7 +738,7 @@ bpf_program__relocate(struct bpf_program *prog, int *map_fds) | |||
683 | if (insn_idx >= (int)prog->insns_cnt) { | 738 | if (insn_idx >= (int)prog->insns_cnt) { |
684 | pr_warning("relocation out of range: '%s'\n", | 739 | pr_warning("relocation out of range: '%s'\n", |
685 | prog->section_name); | 740 | prog->section_name); |
686 | return -ERANGE; | 741 | return -LIBBPF_ERRNO__RELOC; |
687 | } | 742 | } |
688 | insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; | 743 | insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; |
689 | insns[insn_idx].imm = map_fds[map_idx]; | 744 | insns[insn_idx].imm = map_fds[map_idx]; |
@@ -721,7 +776,7 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) | |||
721 | 776 | ||
722 | if (!obj_elf_valid(obj)) { | 777 | if (!obj_elf_valid(obj)) { |
723 | pr_warning("Internal error: elf object is closed\n"); | 778 | pr_warning("Internal error: elf object is closed\n"); |
724 | return -EINVAL; | 779 | return -LIBBPF_ERRNO__INTERNAL; |
725 | } | 780 | } |
726 | 781 | ||
727 | for (i = 0; i < obj->efile.nr_reloc; i++) { | 782 | for (i = 0; i < obj->efile.nr_reloc; i++) { |
@@ -734,21 +789,21 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) | |||
734 | 789 | ||
735 | if (shdr->sh_type != SHT_REL) { | 790 | if (shdr->sh_type != SHT_REL) { |
736 | pr_warning("internal error at %d\n", __LINE__); | 791 | pr_warning("internal error at %d\n", __LINE__); |
737 | return -EINVAL; | 792 | return -LIBBPF_ERRNO__INTERNAL; |
738 | } | 793 | } |
739 | 794 | ||
740 | prog = bpf_object__find_prog_by_idx(obj, idx); | 795 | prog = bpf_object__find_prog_by_idx(obj, idx); |
741 | if (!prog) { | 796 | if (!prog) { |
742 | pr_warning("relocation failed: no %d section\n", | 797 | pr_warning("relocation failed: no %d section\n", |
743 | idx); | 798 | idx); |
744 | return -ENOENT; | 799 | return -LIBBPF_ERRNO__RELOC; |
745 | } | 800 | } |
746 | 801 | ||
747 | err = bpf_program__collect_reloc(prog, nr_maps, | 802 | err = bpf_program__collect_reloc(prog, nr_maps, |
748 | shdr, data, | 803 | shdr, data, |
749 | obj->efile.symbols); | 804 | obj->efile.symbols); |
750 | if (err) | 805 | if (err) |
751 | return -EINVAL; | 806 | return err; |
752 | } | 807 | } |
753 | return 0; | 808 | return 0; |
754 | } | 809 | } |
@@ -777,13 +832,23 @@ load_program(struct bpf_insn *insns, int insns_cnt, | |||
777 | goto out; | 832 | goto out; |
778 | } | 833 | } |
779 | 834 | ||
780 | ret = -EINVAL; | 835 | ret = -LIBBPF_ERRNO__LOAD; |
781 | pr_warning("load bpf program failed: %s\n", strerror(errno)); | 836 | pr_warning("load bpf program failed: %s\n", strerror(errno)); |
782 | 837 | ||
783 | if (log_buf) { | 838 | if (log_buf && log_buf[0] != '\0') { |
839 | ret = -LIBBPF_ERRNO__VERIFY; | ||
784 | pr_warning("-- BEGIN DUMP LOG ---\n"); | 840 | pr_warning("-- BEGIN DUMP LOG ---\n"); |
785 | pr_warning("\n%s\n", log_buf); | 841 | pr_warning("\n%s\n", log_buf); |
786 | pr_warning("-- END LOG --\n"); | 842 | pr_warning("-- END LOG --\n"); |
843 | } else { | ||
844 | if (insns_cnt >= BPF_MAXINSNS) { | ||
845 | pr_warning("Program too large (%d insns), at most %d insns\n", | ||
846 | insns_cnt, BPF_MAXINSNS); | ||
847 | ret = -LIBBPF_ERRNO__PROG2BIG; | ||
848 | } else if (log_buf) { | ||
849 | pr_warning("log buffer is empty\n"); | ||
850 | ret = -LIBBPF_ERRNO__KVER; | ||
851 | } | ||
787 | } | 852 | } |
788 | 853 | ||
789 | out: | 854 | out: |
@@ -831,7 +896,7 @@ static int bpf_object__validate(struct bpf_object *obj) | |||
831 | if (obj->kern_version == 0) { | 896 | if (obj->kern_version == 0) { |
832 | pr_warning("%s doesn't provide kernel version\n", | 897 | pr_warning("%s doesn't provide kernel version\n", |
833 | obj->path); | 898 | obj->path); |
834 | return -EINVAL; | 899 | return -LIBBPF_ERRNO__KVERSION; |
835 | } | 900 | } |
836 | return 0; | 901 | return 0; |
837 | } | 902 | } |
@@ -840,32 +905,28 @@ static struct bpf_object * | |||
840 | __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz) | 905 | __bpf_object__open(const char *path, void *obj_buf, size_t obj_buf_sz) |
841 | { | 906 | { |
842 | struct bpf_object *obj; | 907 | struct bpf_object *obj; |
908 | int err; | ||
843 | 909 | ||
844 | if (elf_version(EV_CURRENT) == EV_NONE) { | 910 | if (elf_version(EV_CURRENT) == EV_NONE) { |
845 | pr_warning("failed to init libelf for %s\n", path); | 911 | pr_warning("failed to init libelf for %s\n", path); |
846 | return NULL; | 912 | return ERR_PTR(-LIBBPF_ERRNO__LIBELF); |
847 | } | 913 | } |
848 | 914 | ||
849 | obj = bpf_object__new(path, obj_buf, obj_buf_sz); | 915 | obj = bpf_object__new(path, obj_buf, obj_buf_sz); |
850 | if (!obj) | 916 | if (IS_ERR(obj)) |
851 | return NULL; | 917 | return obj; |
852 | 918 | ||
853 | if (bpf_object__elf_init(obj)) | 919 | CHECK_ERR(bpf_object__elf_init(obj), err, out); |
854 | goto out; | 920 | CHECK_ERR(bpf_object__check_endianness(obj), err, out); |
855 | if (bpf_object__check_endianness(obj)) | 921 | CHECK_ERR(bpf_object__elf_collect(obj), err, out); |
856 | goto out; | 922 | CHECK_ERR(bpf_object__collect_reloc(obj), err, out); |
857 | if (bpf_object__elf_collect(obj)) | 923 | CHECK_ERR(bpf_object__validate(obj), err, out); |
858 | goto out; | ||
859 | if (bpf_object__collect_reloc(obj)) | ||
860 | goto out; | ||
861 | if (bpf_object__validate(obj)) | ||
862 | goto out; | ||
863 | 924 | ||
864 | bpf_object__elf_finish(obj); | 925 | bpf_object__elf_finish(obj); |
865 | return obj; | 926 | return obj; |
866 | out: | 927 | out: |
867 | bpf_object__close(obj); | 928 | bpf_object__close(obj); |
868 | return NULL; | 929 | return ERR_PTR(err); |
869 | } | 930 | } |
870 | 931 | ||
871 | struct bpf_object *bpf_object__open(const char *path) | 932 | struct bpf_object *bpf_object__open(const char *path) |
@@ -922,6 +983,8 @@ int bpf_object__unload(struct bpf_object *obj) | |||
922 | 983 | ||
923 | int bpf_object__load(struct bpf_object *obj) | 984 | int bpf_object__load(struct bpf_object *obj) |
924 | { | 985 | { |
986 | int err; | ||
987 | |||
925 | if (!obj) | 988 | if (!obj) |
926 | return -EINVAL; | 989 | return -EINVAL; |
927 | 990 | ||
@@ -931,18 +994,16 @@ int bpf_object__load(struct bpf_object *obj) | |||
931 | } | 994 | } |
932 | 995 | ||
933 | obj->loaded = true; | 996 | obj->loaded = true; |
934 | if (bpf_object__create_maps(obj)) | 997 | |
935 | goto out; | 998 | CHECK_ERR(bpf_object__create_maps(obj), err, out); |
936 | if (bpf_object__relocate(obj)) | 999 | CHECK_ERR(bpf_object__relocate(obj), err, out); |
937 | goto out; | 1000 | CHECK_ERR(bpf_object__load_progs(obj), err, out); |
938 | if (bpf_object__load_progs(obj)) | ||
939 | goto out; | ||
940 | 1001 | ||
941 | return 0; | 1002 | return 0; |
942 | out: | 1003 | out: |
943 | bpf_object__unload(obj); | 1004 | bpf_object__unload(obj); |
944 | pr_warning("failed to load object '%s'\n", obj->path); | 1005 | pr_warning("failed to load object '%s'\n", obj->path); |
945 | return -EINVAL; | 1006 | return err; |
946 | } | 1007 | } |
947 | 1008 | ||
948 | void bpf_object__close(struct bpf_object *obj) | 1009 | void bpf_object__close(struct bpf_object *obj) |
@@ -990,7 +1051,7 @@ const char * | |||
990 | bpf_object__get_name(struct bpf_object *obj) | 1051 | bpf_object__get_name(struct bpf_object *obj) |
991 | { | 1052 | { |
992 | if (!obj) | 1053 | if (!obj) |
993 | return NULL; | 1054 | return ERR_PTR(-EINVAL); |
994 | return obj->path; | 1055 | return obj->path; |
995 | } | 1056 | } |
996 | 1057 | ||
@@ -1043,7 +1104,7 @@ const char *bpf_program__title(struct bpf_program *prog, bool needs_copy) | |||
1043 | title = strdup(title); | 1104 | title = strdup(title); |
1044 | if (!title) { | 1105 | if (!title) { |
1045 | pr_warning("failed to strdup program title\n"); | 1106 | pr_warning("failed to strdup program title\n"); |
1046 | return NULL; | 1107 | return ERR_PTR(-ENOMEM); |
1047 | } | 1108 | } |
1048 | } | 1109 | } |
1049 | 1110 | ||
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index bc80af03c6f4..30a40e9fa503 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h | |||
@@ -10,6 +10,26 @@ | |||
10 | 10 | ||
11 | #include <stdio.h> | 11 | #include <stdio.h> |
12 | #include <stdbool.h> | 12 | #include <stdbool.h> |
13 | #include <linux/err.h> | ||
14 | |||
15 | enum libbpf_errno { | ||
16 | __LIBBPF_ERRNO__START = 4000, | ||
17 | |||
18 | /* Something wrong in libelf */ | ||
19 | LIBBPF_ERRNO__LIBELF = __LIBBPF_ERRNO__START, | ||
20 | LIBBPF_ERRNO__FORMAT, /* BPF object format invalid */ | ||
21 | LIBBPF_ERRNO__KVERSION, /* Incorrect or no 'version' section */ | ||
22 | LIBBPF_ERRNO__ENDIAN, /* Endian missmatch */ | ||
23 | LIBBPF_ERRNO__INTERNAL, /* Internal error in libbpf */ | ||
24 | LIBBPF_ERRNO__RELOC, /* Relocation failed */ | ||
25 | LIBBPF_ERRNO__LOAD, /* Load program failure for unknown reason */ | ||
26 | LIBBPF_ERRNO__VERIFY, /* Kernel verifier blocks program loading */ | ||
27 | LIBBPF_ERRNO__PROG2BIG, /* Program too big */ | ||
28 | LIBBPF_ERRNO__KVER, /* Incorrect kernel version */ | ||
29 | __LIBBPF_ERRNO__END, | ||
30 | }; | ||
31 | |||
32 | int libbpf_strerror(int err, char *buf, size_t size); | ||
13 | 33 | ||
14 | /* | 34 | /* |
15 | * In include/linux/compiler-gcc.h, __printf is defined. However | 35 | * In include/linux/compiler-gcc.h, __printf is defined. However |