Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932774AbbHHINY (ORCPT ); Sat, 8 Aug 2015 04:13:24 -0400 Received: from terminus.zytor.com ([198.137.202.10]:53734 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754281AbbHHINQ (ORCPT ); Sat, 8 Aug 2015 04:13:16 -0400 Date: Sat, 8 Aug 2015 01:12:35 -0700 From: tip-bot for Wang Nan Message-ID: Cc: mingo@kernel.org, a.p.zijlstra@chello.nl, wangnan0@huawei.com, linux-kernel@vger.kernel.org, brendan.d.gregg@gmail.com, lizefan@huawei.com, jolsa@kernel.org, masami.hiramatsu.pt@hitachi.com, hekuang@huawei.com, xiakaixu@huawei.com, tglx@linutronix.de, ast@plumgrid.com, daniel@iogearbox.net, hpa@zytor.com, dsahern@gmail.com, acme@redhat.com, namhyung@kernel.org Reply-To: mingo@kernel.org, a.p.zijlstra@chello.nl, wangnan0@huawei.com, jolsa@kernel.org, masami.hiramatsu.pt@hitachi.com, linux-kernel@vger.kernel.org, brendan.d.gregg@gmail.com, lizefan@huawei.com, xiakaixu@huawei.com, hekuang@huawei.com, daniel@iogearbox.net, acme@redhat.com, namhyung@kernel.org, dsahern@gmail.com, hpa@zytor.com, tglx@linutronix.de, ast@plumgrid.com In-Reply-To: <1435716878-189507-13-git-send-email-wangnan0@huawei.com> References: <1435716878-189507-13-git-send-email-wangnan0@huawei.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:perf/core] bpf tools: Collect eBPF programs from their own sections Git-Commit-ID: a5b8bd47dcc574cd3a71357b3a0f586969e4b887 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5718 Lines: 201 Commit-ID: a5b8bd47dcc574cd3a71357b3a0f586969e4b887 Gitweb: http://git.kernel.org/tip/a5b8bd47dcc574cd3a71357b3a0f586969e4b887 Author: Wang Nan AuthorDate: Wed, 1 Jul 2015 02:14:00 +0000 Committer: Arnaldo Carvalho de Melo CommitDate: Fri, 7 Aug 2015 10:16:57 -0300 bpf tools: Collect eBPF programs from their own sections This patch collects all programs in an object file into an array of 'struct bpf_program' for further processing. That structure is for representing each eBPF program. 'bpf_prog' should be a better name, but it has been used by linux/filter.h. Although it is a kernel space name, I still prefer to call it 'bpf_program' to prevent possible confusion. bpf_object__add_program() creates a new 'struct bpf_program' object. It first init a variable in stack using bpf_program__init(), then if success, enlarges obj->programs array and copy the new object in. Signed-off-by: Wang Nan Acked-by: Alexei Starovoitov Cc: Brendan Gregg Cc: Daniel Borkmann Cc: David Ahern Cc: He Kuang Cc: Jiri Olsa Cc: Kaixu Xia Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1435716878-189507-13-git-send-email-wangnan0@huawei.com [ Made bpf_object__add_program() propagate the error (-EINVAL or -ENOMEM) ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/bpf/libbpf.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 9b016c0..102156f 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -78,12 +78,27 @@ void libbpf_set_print(libbpf_print_fn_t warn, # define LIBBPF_ELF_C_READ_MMAP ELF_C_READ #endif +/* + * bpf_prog should be a better name but it has been used in + * linux/filter.h. + */ +struct bpf_program { + /* Index in elf obj file, for relocation use. */ + int idx; + char *section_name; + struct bpf_insn *insns; + size_t insns_cnt; +}; + struct bpf_object { char license[64]; u32 kern_version; void *maps_buf; size_t maps_buf_sz; + struct bpf_program *programs; + size_t nr_programs; + /* * Information when doing elf related work. Only valid if fd * is valid. @@ -100,6 +115,85 @@ struct bpf_object { }; #define obj_elf_valid(o) ((o)->efile.elf) +static void bpf_program__exit(struct bpf_program *prog) +{ + if (!prog) + return; + + zfree(&prog->section_name); + zfree(&prog->insns); + prog->insns_cnt = 0; + prog->idx = -1; +} + +static int +bpf_program__init(void *data, size_t size, char *name, int idx, + struct bpf_program *prog) +{ + if (size < sizeof(struct bpf_insn)) { + pr_warning("corrupted section '%s'\n", name); + return -EINVAL; + } + + bzero(prog, sizeof(*prog)); + + prog->section_name = strdup(name); + if (!prog->section_name) { + pr_warning("failed to alloc name for prog %s\n", + name); + goto errout; + } + + prog->insns = malloc(size); + if (!prog->insns) { + pr_warning("failed to alloc insns for %s\n", name); + goto errout; + } + prog->insns_cnt = size / sizeof(struct bpf_insn); + memcpy(prog->insns, data, + prog->insns_cnt * sizeof(struct bpf_insn)); + prog->idx = idx; + + return 0; +errout: + bpf_program__exit(prog); + return -ENOMEM; +} + +static int +bpf_object__add_program(struct bpf_object *obj, void *data, size_t size, + char *name, int idx) +{ + struct bpf_program prog, *progs; + int nr_progs, err; + + err = bpf_program__init(data, size, name, idx, &prog); + if (err) + return err; + + progs = obj->programs; + nr_progs = obj->nr_programs; + + progs = realloc(progs, sizeof(progs[0]) * (nr_progs + 1)); + if (!progs) { + /* + * In this case the original obj->programs + * is still valid, so don't need special treat for + * bpf_close_object(). + */ + pr_warning("failed to alloc a new program '%s'\n", + name); + bpf_program__exit(&prog); + return -ENOMEM; + } + + pr_debug("found program %s\n", prog.section_name); + obj->programs = progs; + obj->nr_programs = nr_progs + 1; + progs[nr_progs] = prog; + return 0; +} + static struct bpf_object *bpf_object__new(const char *path, void *obj_buf, size_t obj_buf_sz) @@ -342,6 +436,17 @@ static int bpf_object__elf_collect(struct bpf_object *obj) err = -EEXIST; } else obj->efile.symbols = data; + } else if ((sh.sh_type == SHT_PROGBITS) && + (sh.sh_flags & SHF_EXECINSTR) && + (data->d_size > 0)) { + err = bpf_object__add_program(obj, data->d_buf, + data->d_size, name, idx); + if (err) { + char errmsg[128]; + strerror_r(-err, errmsg, sizeof(errmsg)); + pr_warning("failed to alloc program %s (%s): %s", + name, obj->path, errmsg); + } } if (err) goto out; @@ -415,11 +520,20 @@ struct bpf_object *bpf_object__open_buffer(void *obj_buf, void bpf_object__close(struct bpf_object *obj) { + size_t i; + if (!obj) return; bpf_object__elf_finish(obj); zfree(&obj->maps_buf); + + if (obj->programs && obj->nr_programs) { + for (i = 0; i < obj->nr_programs; i++) + bpf_program__exit(&obj->programs[i]); + } + zfree(&obj->programs); + free(obj); } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/