[PATCH v11 12/39] bpf tools: Collect eBPF programs from their own sections

2015-07-08 Thread Wang Nan
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

2015-07-08 Thread Wang Nan
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) 
+