Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1174894
| From | Wang Nan <wangnan0@huawei.com> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [RFC PATCH v10 05/50] bpf tools: Open eBPF object file and do basic validation |
| Date | 2015-07-01 04:20 +0200 |
| Message-ID | <pHfN0-3Uy-33@gated-at.bofh.it> (permalink) |
| References | <pHfMZ-3Uy-3@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
This patch defines basic interface of libbpf. 'struct bpf_object' will
be the handler of each object file. Its internal structure is hide to
user. eBPF object files are compiled by LLVM as ELF format. In this
patch, libelf is used to open those files, read EHDR and do basic
validation according to e_type and e_machine.
All elf related staffs are grouped together and reside in efile field of
'struct bpf_object'. bpf_object__elf_finish() is introduced to clear it.
After all eBPF programs in an object file are loaded, related ELF
information is useless. Close the object file and free those memory.
zfree() and zclose() are introduced to ensure setting NULL pointers and
negative file descriptors after resources are released.
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Alexei Starovoitov <ast@plumgrid.com>
---
tools/lib/bpf/libbpf.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++
tools/lib/bpf/libbpf.h | 8 +++
2 files changed, 166 insertions(+)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 6f0c13a..9e44608 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -11,8 +11,12 @@
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
#include <asm/unistd.h>
#include <linux/bpf.h>
+#include <libelf.h>
+#include <gelf.h>
#include "libbpf.h"
@@ -52,3 +56,157 @@ void libbpf_set_print(libbpf_print_fn_t warn,
__pr_info = info;
__pr_debug = debug;
}
+
+/* Copied from tools/perf/util/util.h */
+#ifndef zfree
+# define zfree(ptr) ({ free(*ptr); *ptr = NULL; })
+#endif
+
+#ifndef zclose
+# define zclose(fd) ({ \
+ int ___err = 0; \
+ if ((fd) >= 0) \
+ ___err = close((fd)); \
+ fd = -1; \
+ ___err; })
+#endif
+
+#ifdef HAVE_LIBELF_MMAP_SUPPORT
+# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ_MMAP
+#else
+# define LIBBPF_ELF_C_READ_MMAP ELF_C_READ
+#endif
+
+struct bpf_object {
+ /*
+ * Information when doing elf related work. Only valid if fd
+ * is valid.
+ */
+ struct {
+ int fd;
+ Elf *elf;
+ GElf_Ehdr ehdr;
+ } efile;
+ char path[];
+};
+#define obj_elf_valid(o) ((o)->efile.elf)
+
+static struct bpf_object *bpf_object__new(const char *path)
+{
+ struct bpf_object *obj;
+
+ obj = calloc(1, sizeof(struct bpf_object) + strlen(path) + 1);
+ if (!obj) {
+ pr_warning("alloc memory failed for %s\n", path);
+ return NULL;
+ }
+
+ strcpy(obj->path, path);
+ obj->efile.fd = -1;
+ return obj;
+}
+
+static void bpf_object__elf_finish(struct bpf_object *obj)
+{
+ if (!obj_elf_valid(obj))
+ return;
+
+ if (obj->efile.elf) {
+ elf_end(obj->efile.elf);
+ obj->efile.elf = NULL;
+ }
+ zclose(obj->efile.fd);
+}
+
+static int bpf_object__elf_init(struct bpf_object *obj)
+{
+ int err = 0;
+ GElf_Ehdr *ep;
+
+ if (obj_elf_valid(obj)) {
+ pr_warning("elf init: internal error\n");
+ return -EEXIST;
+ }
+
+ obj->efile.fd = open(obj->path, O_RDONLY);
+ if (obj->efile.fd < 0) {
+ pr_warning("failed to open %s: %s\n", obj->path,
+ strerror(errno));
+ return -errno;
+ }
+
+ obj->efile.elf = elf_begin(obj->efile.fd,
+ LIBBPF_ELF_C_READ_MMAP,
+ NULL);
+ if (!obj->efile.elf) {
+ pr_warning("failed to open %s as ELF file\n",
+ obj->path);
+ err = -EINVAL;
+ goto errout;
+ }
+
+ if (!gelf_getehdr(obj->efile.elf, &obj->efile.ehdr)) {
+ pr_warning("failed to get EHDR from %s\n",
+ obj->path);
+ err = -EINVAL;
+ goto errout;
+ }
+ ep = &obj->efile.ehdr;
+
+ if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) {
+ pr_warning("%s is not an eBPF object file\n",
+ obj->path);
+ err = -EINVAL;
+ goto errout;
+ }
+
+ return 0;
+errout:
+ bpf_object__elf_finish(obj);
+ return err;
+}
+
+static struct bpf_object *
+__bpf_object__open(const char *path)
+{
+ struct bpf_object *obj;
+
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ pr_warning("failed to init libelf for %s\n", path);
+ return NULL;
+ }
+
+ obj = bpf_object__new(path);
+ if (!obj)
+ return NULL;
+
+ if (bpf_object__elf_init(obj))
+ goto out;
+
+ bpf_object__elf_finish(obj);
+ return obj;
+out:
+ bpf_object__close(obj);
+ return NULL;
+}
+
+struct bpf_object *bpf_object__open(const char *path)
+{
+ /* param validation */
+ if (!path)
+ return NULL;
+
+ pr_debug("loading %s\n", path);
+
+ return __bpf_object__open(path);
+}
+
+void bpf_object__close(struct bpf_object *obj)
+{
+ if (!obj)
+ return;
+
+ bpf_object__elf_finish(obj);
+
+ free(obj);
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 8d1eeba..ec3301c 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -8,6 +8,8 @@
#ifndef __BPF_LIBBPF_H
#define __BPF_LIBBPF_H
+#include <stdio.h>
+
/*
* In include/linux/compiler-gcc.h, __printf is defined. However
* it should be better if libbpf.h doesn't depend on Linux header file.
@@ -20,4 +22,10 @@ void libbpf_set_print(libbpf_print_fn_t warn,
libbpf_print_fn_t info,
libbpf_print_fn_t debug);
+/* Hide internal to user */
+struct bpf_object;
+
+struct bpf_object *bpf_object__open(const char *path);
+void bpf_object__close(struct bpf_object *object);
+
#endif
--
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/
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[RFC PATCH v10 00/50] perf tools: filtering events using eBPF programs Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 18/50] bpf tools: Introduce bpf_load_program() to bpf.c Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 07/50] bpf tools: Check endianness and make libbpf fail early Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 25/50] perf tools: Call clang to compile C source to object code Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 02/50] tracing, perf: Implement BPF programs attached to uprobes Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 05/50] bpf tools: Open eBPF object file and do basic validation Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 22/50] bpf tools: Link all bpf objects onto a list Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 27/50] perf tools: Auto detecting kernel build directory Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 06/50] bpf tools: Read eBPF object from buffer Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 13/50] bpf tools: Collect relocation sections from SHT_REL sections Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 01/50] bpf: Use correct #ifdef controller for trace_call_bpf() Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 16/50] bpf tools: Create eBPF maps defined in an object file Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 [RFC PATCH v10 17/50] bpf tools: Relocate eBPF programs Wang Nan <wangnan0@huawei.com> - 2015-07-01 04:20 +0200 Re: [RFC PATCH v10 23/50] perf tools: Make perf depend on libbpf Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-07-08 15:10 +0200 Re: [RFC PATCH v10 23/50] perf tools: Make perf depend on libbpf Arnaldo Carvalho de Melo <acme@kernel.org> - 2015-07-08 15:10 +0200
csiph-web