diff options
author | Wang Nan | 2015-07-01 02:14:07 +0000 |
---|---|---|
committer | Arnaldo Carvalho de Melo | 2015-08-07 10:16:59 -0300 |
commit | 55cffde2e1a41109cb49f8e94de954c8240242b5 (patch) | |
tree | 327432a2959dcf1e3d4161c62b7589e2896da8c5 /tools/lib | |
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')
-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 { int map_idx; } *reloc_desc; int nr_reloc; + + int fd; }; struct bpf_object { @@ -135,11 +137,20 @@ struct bpf_object { }; #define obj_elf_valid(o) ((o)->efile.elf) +static void bpf_program__unload(struct bpf_program *prog) +{ + if (!prog) + return; + + zclose(prog->fd); +} + static void bpf_program__exit(struct bpf_program *prog) { if (!prog) return; + bpf_program__unload(prog); zfree(&prog->section_name); zfree(&prog->insns); zfree(&prog->reloc_desc); @@ -176,6 +187,7 @@ bpf_program__init(void *data, size_t size, char *name, int idx, memcpy(prog->insns, data, prog->insns_cnt * sizeof(struct bpf_insn)); prog->idx = idx; + prog->fd = -1; return 0; errout: @@ -718,6 +730,79 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) return 0; } +static int +load_program(struct bpf_insn *insns, int insns_cnt, + char *license, u32 kern_version, int *pfd) +{ + int ret; + char *log_buf; + + if (!insns || !insns_cnt) + return -EINVAL; + + log_buf = malloc(BPF_LOG_BUF_SIZE); + if (!log_buf) + pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); + + ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, + insns_cnt, license, kern_version, + log_buf, BPF_LOG_BUF_SIZE); + + if (ret >= 0) { + *pfd = ret; + ret = 0; + goto out; + } + + ret = -EINVAL; + pr_warning("load bpf program failed: %s\n", strerror(errno)); + + if (log_buf) { + pr_warning("-- BEGIN DUMP LOG ---\n"); + pr_warning("\n%s\n", log_buf); + pr_warning("-- END LOG --\n"); + } + +out: + free(log_buf); + return ret; +} + +static int +bpf_program__load(struct bpf_program *prog, + char *license, u32 kern_version) +{ + int err, fd; + + err = load_program(prog->insns, prog->insns_cnt, + license, kern_version, &fd); + if (!err) + prog->fd = fd; + + if (err) + pr_warning("failed to load program '%s'\n", + prog->section_name); + zfree(&prog->insns); + prog->insns_cnt = 0; + return err; +} + +static int +bpf_object__load_progs(struct bpf_object *obj) +{ + size_t i; + int err; + + for (i = 0; i < obj->nr_programs; i++) { + err = bpf_program__load(&obj->programs[i], + obj->license, + obj->kern_version); + if (err) + return err; + } + return 0; +} + static int bpf_object__validate(struct bpf_object *obj) { if (obj->kern_version == 0) { @@ -795,6 +880,9 @@ int bpf_object__unload(struct bpf_object *obj) zfree(&obj->map_fds); obj->nr_map_fds = 0; + for (i = 0; i < obj->nr_programs; i++) + bpf_program__unload(&obj->programs[i]); + return 0; } @@ -813,6 +901,8 @@ int bpf_object__load(struct bpf_object *obj) goto out; if (bpf_object__relocate(obj)) goto out; + if (bpf_object__load_progs(obj)) + goto out; return 0; out: |