[PATCH v11 12/39] 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_program__new() creates a new 'struct bpf_program' object. It first init a variable in stack using __bpf_program__new(), 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: Paul Mackerras Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3or...@163.com Link: http://lkml.kernel.org/r/1435716878-189507-13-git-send-email-wangn...@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/lib/bpf/libbpf.c | 117 + 1 file changed, 117 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 9b016c0..3b717de 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,84 @@ struct bpf_object { }; #define obj_elf_valid(o) ((o)->efile.elf) +static void bpf_program__clear(struct bpf_program *prog) +{ + if (!prog) + return; + + zfree(>section_name); + zfree(>insns); + prog->insns_cnt = 0; + prog->idx = -1; +} + +static int +__bpf_program__new(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__clear(prog); + return -ENOMEM; +} + +static struct bpf_program * +bpf_program__new(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__new(data, size, name, idx, ); + if (err) + return NULL; + + 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__clear(); + return NULL; + } + + obj->programs = progs; + obj->nr_programs = nr_progs + 1; + progs[nr_progs] = prog; + return [nr_progs]; +} + static struct bpf_object *bpf_object__new(const char *path, void *obj_buf, size_t obj_buf_sz) @@ -342,6 +435,21 @@ 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)) { + struct bpf_program *prog; + + prog = bpf_program__new(obj, data->d_buf, + data->d_size, name, + idx); +
[PATCH v11 12/39] 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_program__new() creates a new 'struct bpf_program' object. It first init a variable in stack using __bpf_program__new(), then if success, enlarges obj-programs array and copy the new object in. Signed-off-by: Wang Nan wangn...@huawei.com Acked-by: Alexei Starovoitov a...@plumgrid.com Cc: Brendan Gregg brendan.d.gr...@gmail.com Cc: Daniel Borkmann dan...@iogearbox.net Cc: David Ahern dsah...@gmail.com Cc: He Kuang heku...@huawei.com Cc: Jiri Olsa jo...@kernel.org Cc: Kaixu Xia xiaka...@huawei.com Cc: Masami Hiramatsu masami.hiramatsu...@hitachi.com Cc: Namhyung Kim namhy...@kernel.org Cc: Paul Mackerras pau...@samba.org Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Zefan Li lize...@huawei.com Cc: pi3or...@163.com Link: http://lkml.kernel.org/r/1435716878-189507-13-git-send-email-wangn...@huawei.com Signed-off-by: Arnaldo Carvalho de Melo a...@redhat.com --- tools/lib/bpf/libbpf.c | 117 + 1 file changed, 117 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 9b016c0..3b717de 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,84 @@ struct bpf_object { }; #define obj_elf_valid(o) ((o)-efile.elf) +static void bpf_program__clear(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__new(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__clear(prog); + return -ENOMEM; +} + +static struct bpf_program * +bpf_program__new(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__new(data, size, name, idx, prog); + if (err) + return NULL; + + 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__clear(prog); + return NULL; + } + + obj-programs = progs; + obj-nr_programs = nr_progs + 1; + progs[nr_progs] = prog; + return progs[nr_progs]; +} + static struct bpf_object *bpf_object__new(const char *path, void *obj_buf, size_t obj_buf_sz) @@ -342,6 +435,21 @@ 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) +