diff options
author | Wang Nan <wangnan0@huawei.com> | 2015-06-30 22:14:07 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-08-07 09:16:59 -0400 |
commit | 55cffde2e1a41109cb49f8e94de954c8240242b5 (patch) | |
tree | 327432a2959dcf1e3d4161c62b7589e2896da8c5 /tools/lib/bpf/libbpf.c | |
parent | 7bf98369a73a9a84c56b3f2b247ea8f0eaf8668b (diff) |
bpf tools: Load eBPF programs in object files into kernel
This patch utilizes previous introduced bpf_load_program to load
programs in the ELF file into kernel. Result is stored in 'fd' field in
'struct bpf_program'.
During loading, it allocs a log buffer and free it before return. Note
that that buffer is not passed to bpf_load_program() if the first
loading try is successful. Doesn't use a statically allocated log buffer
to avoid potention multi-thread problem.
Instructions collected during opening is cleared after loading.
load_program() is created for loading a 'struct bpf_insn' array into
kernel, bpf_program__load() calls it. By this design we have a function
loads instructions into kernel. It will be used by further patches,
which creates different instances from a program and load them into
kernel.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1435716878-189507-20-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r-- | tools/lib/bpf/libbpf.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 94f966008887..38447b7d6e73 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -96,6 +96,8 @@ struct bpf_program { | |||
96 | int map_idx; | 96 | int map_idx; |
97 | } *reloc_desc; | 97 | } *reloc_desc; |
98 | int nr_reloc; | 98 | int nr_reloc; |
99 | |||
100 | int fd; | ||
99 | }; | 101 | }; |
100 | 102 | ||
101 | struct bpf_object { | 103 | struct bpf_object { |
@@ -135,11 +137,20 @@ struct bpf_object { | |||
135 | }; | 137 | }; |
136 | #define obj_elf_valid(o) ((o)->efile.elf) | 138 | #define obj_elf_valid(o) ((o)->efile.elf) |
137 | 139 | ||
140 | static void bpf_program__unload(struct bpf_program *prog) | ||
141 | { | ||
142 | if (!prog) | ||
143 | return; | ||
144 | |||
145 | zclose(prog->fd); | ||
146 | } | ||
147 | |||
138 | static void bpf_program__exit(struct bpf_program *prog) | 148 | static void bpf_program__exit(struct bpf_program *prog) |
139 | { | 149 | { |
140 | if (!prog) | 150 | if (!prog) |
141 | return; | 151 | return; |
142 | 152 | ||
153 | bpf_program__unload(prog); | ||
143 | zfree(&prog->section_name); | 154 | zfree(&prog->section_name); |
144 | zfree(&prog->insns); | 155 | zfree(&prog->insns); |
145 | zfree(&prog->reloc_desc); | 156 | zfree(&prog->reloc_desc); |
@@ -176,6 +187,7 @@ bpf_program__init(void *data, size_t size, char *name, int idx, | |||
176 | memcpy(prog->insns, data, | 187 | memcpy(prog->insns, data, |
177 | prog->insns_cnt * sizeof(struct bpf_insn)); | 188 | prog->insns_cnt * sizeof(struct bpf_insn)); |
178 | prog->idx = idx; | 189 | prog->idx = idx; |
190 | prog->fd = -1; | ||
179 | 191 | ||
180 | return 0; | 192 | return 0; |
181 | errout: | 193 | errout: |
@@ -718,6 +730,79 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) | |||
718 | return 0; | 730 | return 0; |
719 | } | 731 | } |
720 | 732 | ||
733 | static int | ||
734 | load_program(struct bpf_insn *insns, int insns_cnt, | ||
735 | char *license, u32 kern_version, int *pfd) | ||
736 | { | ||
737 | int ret; | ||
738 | char *log_buf; | ||
739 | |||
740 | if (!insns || !insns_cnt) | ||
741 | return -EINVAL; | ||
742 | |||
743 | log_buf = malloc(BPF_LOG_BUF_SIZE); | ||
744 | if (!log_buf) | ||
745 | pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); | ||
746 | |||
747 | ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, | ||
748 | insns_cnt, license, kern_version, | ||
749 | log_buf, BPF_LOG_BUF_SIZE); | ||
750 | |||
751 | if (ret >= 0) { | ||
752 | *pfd = ret; | ||
753 | ret = 0; | ||
754 | goto out; | ||
755 | } | ||
756 | |||
757 | ret = -EINVAL; | ||
758 | pr_warning("load bpf program failed: %s\n", strerror(errno)); | ||
759 | |||
760 | if (log_buf) { | ||
761 | pr_warning("-- BEGIN DUMP LOG ---\n"); | ||
762 | pr_warning("\n%s\n", log_buf); | ||
763 | pr_warning("-- END LOG --\n"); | ||
764 | } | ||
765 | |||
766 | out: | ||
767 | free(log_buf); | ||
768 | return ret; | ||
769 | } | ||
770 | |||
771 | static int | ||
772 | bpf_program__load(struct bpf_program *prog, | ||
773 | char *license, u32 kern_version) | ||
774 | { | ||
775 | int err, fd; | ||
776 | |||
777 | err = load_program(prog->insns, prog->insns_cnt, | ||
778 | license, kern_version, &fd); | ||
779 | if (!err) | ||
780 | prog->fd = fd; | ||
781 | |||
782 | if (err) | ||
783 | pr_warning("failed to load program '%s'\n", | ||
784 | prog->section_name); | ||
785 | zfree(&prog->insns); | ||
786 | prog->insns_cnt = 0; | ||
787 | return err; | ||
788 | } | ||
789 | |||
790 | static int | ||
791 | bpf_object__load_progs(struct bpf_object *obj) | ||
792 | { | ||
793 | size_t i; | ||
794 | int err; | ||
795 | |||
796 | for (i = 0; i < obj->nr_programs; i++) { | ||
797 | err = bpf_program__load(&obj->programs[i], | ||
798 | obj->license, | ||
799 | obj->kern_version); | ||
800 | if (err) | ||
801 | return err; | ||
802 | } | ||
803 | return 0; | ||
804 | } | ||
805 | |||
721 | static int bpf_object__validate(struct bpf_object *obj) | 806 | static int bpf_object__validate(struct bpf_object *obj) |
722 | { | 807 | { |
723 | if (obj->kern_version == 0) { | 808 | if (obj->kern_version == 0) { |
@@ -795,6 +880,9 @@ int bpf_object__unload(struct bpf_object *obj) | |||
795 | zfree(&obj->map_fds); | 880 | zfree(&obj->map_fds); |
796 | obj->nr_map_fds = 0; | 881 | obj->nr_map_fds = 0; |
797 | 882 | ||
883 | for (i = 0; i < obj->nr_programs; i++) | ||
884 | bpf_program__unload(&obj->programs[i]); | ||
885 | |||
798 | return 0; | 886 | return 0; |
799 | } | 887 | } |
800 | 888 | ||
@@ -813,6 +901,8 @@ int bpf_object__load(struct bpf_object *obj) | |||
813 | goto out; | 901 | goto out; |
814 | if (bpf_object__relocate(obj)) | 902 | if (bpf_object__relocate(obj)) |
815 | goto out; | 903 | goto out; |
904 | if (bpf_object__load_progs(obj)) | ||
905 | goto out; | ||
816 | 906 | ||
817 | return 0; | 907 | return 0; |
818 | out: | 908 | out: |