|
@@ -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);
|
|
|
+}
|