Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752313AbbD3K7Z (ORCPT ); Thu, 30 Apr 2015 06:59:25 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:14551 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751561AbbD3Kxg (ORCPT ); Thu, 30 Apr 2015 06:53:36 -0400 From: Wang Nan To: , , , , , , CC: , , , Subject: [RFC PATCH 17/22] perf bpf: relocation programs. Date: Thu, 30 Apr 2015 10:52:40 +0000 Message-ID: <1430391165-30267-18-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.554209AE.0053,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: 35d376e29ad030d4d827686f9f1b45c1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3755 Lines: 142 If an eBPF program access a map, LLVM generates a relocated load instruction. To enable the usage of that map, relocation must be done by replacing original instructions by map loading instructions. This patch do that work by utilizing previous stored relocation section information in 'struct bpf_obj'. Signed-off-by: Wang Nan --- tools/perf/util/bpf-loader.c | 97 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c index 34ccc10..fe623df 100644 --- a/tools/perf/util/bpf-loader.c +++ b/tools/perf/util/bpf-loader.c @@ -515,6 +515,17 @@ bpf_find_prog_by_name(struct bpf_obj *obj, const char *name) return NULL; } +static struct bpf_perf_prog * +bpf_find_prog_by_idx(struct bpf_obj *obj, int idx) +{ + struct bpf_perf_prog *prog; + + list_for_each_entry(prog, &obj->progs_list, list) + if (prog->idx == idx) + return prog; + return NULL; +} + /* * Use config_str to config program. If prog is NULL, find a * prog based on config_str. config_str should not be NULL. @@ -746,6 +757,90 @@ bpf_obj_create_maps(struct bpf_obj *obj) return 0; } +static int +bpf_perf_prog_relocate(struct bpf_obj *obj, + GElf_Shdr *shdr, + Elf_Data *data, + struct bpf_perf_prog *prog) +{ + int i, nrels; + + pr_debug("bpf: relocating: %s\n", prog->name); + nrels = shdr->sh_size / shdr->sh_entsize; + + for (i = 0; i < nrels; i++) { + GElf_Sym sym; + GElf_Rel rel; + unsigned int insn_idx; + struct bpf_insn *insns = prog->insns; + size_t map_idx; + + if (!gelf_getrel(data, i, &rel)) { + pr_err("bpf: relocation: failed to get %d reloc\n", i); + return -EINVAL; + } + + insn_idx = rel.r_offset / sizeof(struct bpf_insn); + pr_debug("bpf: relocation: insn_idx=%u\n", insn_idx); + + if (!gelf_getsym(obj->elf.symbols, + GELF_R_SYM(rel.r_info), + &sym)) { + pr_err("bpf: relocation: symbol %"PRIx64" not found\n", + GELF_R_SYM(rel.r_info)); + return -EINVAL; + } + + if (insns[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) { + pr_err("bpf: relocation: invalid relo for " + "insns[%d].code 0x%x\n", + insn_idx, insns[insn_idx].code); + return -EINVAL; + } + + map_idx = sym.st_value / sizeof(struct bpf_map_def); + if (map_idx >= obj->nr_maps) { + pr_err("bpf relocation: map_idx %d large than %d\n", + (int)map_idx, (int)obj->nr_maps - 1); + return -EINVAL; + } + + insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD; + insns[insn_idx].imm = obj->maps_fds[map_idx]; + } + return 0; +} + +static int +bpf_obj_relocate(struct bpf_obj *obj) +{ + int i, err; + + for (i = 0; i < obj->elf.nr_reloc; i++) { + GElf_Shdr *shdr = &obj->elf.reloc[i].shdr; + Elf_Data *data = obj->elf.reloc[i].data; + int idx = shdr->sh_info; + struct bpf_perf_prog *prog; + + if (shdr->sh_type != SHT_REL) { + pr_err("bpf: internal error\n"); + return -EINVAL; + } + + prog = bpf_find_prog_by_idx(obj, idx); + if (!prog) { + pr_err("bpf: relocation failed: no %d section\n", + idx); + return -ENOENT; + } + + err = bpf_perf_prog_relocate(obj, shdr, data, prog); + if (err) + return -EINVAL; + } + return 0; +} + int bpf__load(const char *path) { struct bpf_obj *obj; @@ -776,6 +871,8 @@ int bpf__load(const char *path) goto out; if ((err = bpf_obj_create_maps(obj))) goto out; + if ((err = bpf_obj_relocate(obj))) + goto out; list_add(&obj->list, &bpf_obj_list); return 0; -- 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/