Messages in this thread Patch in this message | | | From | Wang Nan <> | Subject | [RFC PATCH 12/22] perf bpf: collect bpf programs from object files. | Date | Thu, 30 Apr 2015 10:52:35 +0000 |
| |
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 <wangnan0@huawei.com> --- 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
| |