Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752438AbbD3LAs (ORCPT ); Thu, 30 Apr 2015 07:00:48 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:14511 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751481AbbD3Kxe (ORCPT ); Thu, 30 Apr 2015 06:53:34 -0400 From: Wang Nan To: , , , , , , CC: , , , Subject: [RFC PATCH 12/22] perf bpf: collect bpf programs from object files. Date: Thu, 30 Apr 2015 10:52:35 +0000 Message-ID: <1430391165-30267-13-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1430391165-30267-1-git-send-email-wangnan0@huawei.com> References: <1430391165-30267-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.197.210] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020203.554209AD.00A3,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 8e66210551500a47db70606b37363b4e Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4423 Lines: 177 This patch collects all programs in an object file and links them into a list for further processing. 'struct bpf_perf_prog' is used 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_perf_prog' to prevent possible confusion. Signed-off-by: Wang Nan --- tools/perf/util/bpf-loader.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/bpf-loader.h | 14 +++++++ 2 files changed, 105 insertions(+) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index b9c701a..bbebaf1 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -59,11 +59,20 @@ static void bpf_obj_clear_elf(struct bpf_obj *obj) } } +static void bpf_perf_prog_free(struct bpf_perf_prog *prog); + static void bpf_obj_close(struct bpf_obj *obj) { + struct bpf_perf_prog *prog, *tmp; + if (!obj) return; + list_for_each_entry_safe(prog, tmp, &obj->progs_list, list) { + list_del(&prog->list); + bpf_perf_prog_free(prog); + } + bpf_obj_clear_elf(obj); if (obj->path) @@ -85,6 +94,7 @@ static struct bpf_obj *bpf_obj_alloc(const char *path) obj->needs_swap = false; obj->elf.fd = -1; + INIT_LIST_HEAD(&obj->progs_list); return obj; out: bpf_obj_close(obj); @@ -255,6 +265,70 @@ static int bpf_obj_config_init(struct bpf_obj *obj, void *data, return 0; } +static void +bpf_perf_prog_free(struct bpf_perf_prog *prog) +{ + if (!prog) + return; + + if (prog->name) + free(prog->name); + if (prog->insns) + free(prog->insns); + free(prog); +} + +static struct bpf_perf_prog * +bpf_perf_prog_alloc(struct bpf_obj *obj __maybe_unused, + void *data, size_t size, + char *name, int idx) +{ + struct bpf_perf_prog *prog; + + if (size < sizeof(struct bpf_insn)) { + pr_err("bpf: corrupted section %s\n", name); + return NULL; + } + + prog = calloc(1, sizeof(struct bpf_perf_prog)); + if (!prog) { + pr_err("bpf: failed to alloc prog\n"); + return NULL; + } + + /* + * Name of a program could be: + * "k(ret)probe/[a-zA-Z_][a-zA-Z_0-9]" + * + * or + * + * "[a-zA-Z_][a-zA-Z_0-9]" + * + * Will be parsed in other function. This function only saves + * the name. + */ + prog->name = strdup(name); + if (!prog->name) { + pr_err("bpf: failed to alloc name for prog %s\n", + name); + goto out; + } + + prog->insns = malloc(size); + if (!prog->insns) { + pr_err("bpf: failed to alloc insns for %s\n", name); + goto out; + } + prog->insns_cnt = size / sizeof(struct bpf_insn); + memcpy(prog->insns, data, + prog->insns_cnt * sizeof(struct bpf_insn)); + prog->idx = idx; + return prog; +out: + bpf_perf_prog_free(prog); + return NULL; +} + static int bpf_obj_elf_collect(struct bpf_obj *obj) { Elf *elf = obj->elf.elf; @@ -322,6 +396,23 @@ static int bpf_obj_elf_collect(struct bpf_obj *obj) err = -EEXIST; } else obj->elf.symbols = data; + } else if ((sh.sh_type == SHT_PROGBITS) && + (sh.sh_flags & SHF_EXECINSTR) && + (data->d_size > 0)) { + struct bpf_perf_prog *prog; + + prog = bpf_perf_prog_alloc(obj, data->d_buf, + data->d_size, name, + idx); + if (!prog) { + pr_err("bpf: failed to alloc " + "program %s (%s)", name, obj->path); + err = -ENOMEM; + } else { + pr_debug("bpf: found program %s\n", + prog->name); + list_add(&prog->list, &obj->progs_list); + } } if (err) goto out; diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h index f0b573c..f9cb46b 100644 --- a/tools/perf/util/bpf-loader.h +++ b/tools/perf/util/bpf-loader.h @@ -19,9 +19,23 @@ int bpf__load(const char *path); int bpf__run(void); +struct bpf_perf_prog { + struct list_head list; + + /* Index in elf obj file, for relocation use. */ + int idx; + char *name; + struct bpf_insn *insns; + size_t insns_cnt; +}; + struct bpf_obj { /* All bpf objs should be linked together. */ struct list_head list; + + /* All eBPF programs are linked at this list */ + struct list_head progs_list; + char *path; bool needs_swap; char license[64]; -- 1.8.3.4 -- 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/