#define STRERR_BUFSIZE  128
 
+int elf_open(const char *binary_path, struct elf_fd *elf_fd)
+{
+       char errmsg[STRERR_BUFSIZE];
+       int fd, ret;
+       Elf *elf;
+
+       if (elf_version(EV_CURRENT) == EV_NONE) {
+               pr_warn("elf: failed to init libelf for %s\n", binary_path);
+               return -LIBBPF_ERRNO__LIBELF;
+       }
+       fd = open(binary_path, O_RDONLY | O_CLOEXEC);
+       if (fd < 0) {
+               ret = -errno;
+               pr_warn("elf: failed to open %s: %s\n", binary_path,
+                       libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
+               return ret;
+       }
+       elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+       if (!elf) {
+               pr_warn("elf: could not read elf from %s: %s\n", binary_path, elf_errmsg(-1));
+               close(fd);
+               return -LIBBPF_ERRNO__FORMAT;
+       }
+       elf_fd->fd = fd;
+       elf_fd->elf = elf;
+       return 0;
+}
+
+void elf_close(struct elf_fd *elf_fd)
+{
+       if (!elf_fd)
+               return;
+       elf_end(elf_fd->elf);
+       close(elf_fd->fd);
+}
+
 /* Return next ELF section of sh_type after scn, or first of that type if scn is NULL. */
 static Elf_Scn *elf_find_next_scn_by_type(Elf *elf, int sh_type, Elf_Scn *scn)
 {
  */
 long elf_find_func_offset_from_file(const char *binary_path, const char *name)
 {
-       char errmsg[STRERR_BUFSIZE];
+       struct elf_fd elf_fd;
        long ret = -ENOENT;
-       Elf *elf;
-       int fd;
 
-       fd = open(binary_path, O_RDONLY | O_CLOEXEC);
-       if (fd < 0) {
-               ret = -errno;
-               pr_warn("failed to open %s: %s\n", binary_path,
-                       libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
+       ret = elf_open(binary_path, &elf_fd);
+       if (ret)
                return ret;
-       }
-       elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
-       if (!elf) {
-               pr_warn("elf: could not read elf from %s: %s\n", binary_path, elf_errmsg(-1));
-               close(fd);
-               return -LIBBPF_ERRNO__FORMAT;
-       }
-
-       ret = elf_find_func_offset(elf, binary_path, name);
-       elf_end(elf);
-       close(fd);
+       ret = elf_find_func_offset(elf_fd.elf, binary_path, name);
+       elf_close(&elf_fd);
        return ret;
 }
-
 
 long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name);
 long elf_find_func_offset_from_file(const char *binary_path, const char *name);
 
+struct elf_fd {
+       Elf *elf;
+       int fd;
+};
+
+int elf_open(const char *binary_path, struct elf_fd *elf_fd);
+void elf_close(struct elf_fd *elf_fd);
+
 #endif /* __LIBBPF_LIBBPF_INTERNAL_H */
 
                                          const char *usdt_provider, const char *usdt_name,
                                          __u64 usdt_cookie)
 {
-       int i, fd, err, spec_map_fd, ip_map_fd;
+       int i, err, spec_map_fd, ip_map_fd;
        LIBBPF_OPTS(bpf_uprobe_opts, opts);
        struct hashmap *specs_hash = NULL;
        struct bpf_link_usdt *link = NULL;
        struct usdt_target *targets = NULL;
+       struct elf_fd elf_fd;
        size_t target_cnt;
-       Elf *elf;
 
        spec_map_fd = bpf_map__fd(man->specs_map);
        ip_map_fd = bpf_map__fd(man->ip_to_spec_id_map);
 
-       fd = open(path, O_RDONLY | O_CLOEXEC);
-       if (fd < 0) {
-               err = -errno;
-               pr_warn("usdt: failed to open ELF binary '%s': %d\n", path, err);
+       err = elf_open(path, &elf_fd);
+       if (err)
                return libbpf_err_ptr(err);
-       }
 
-       elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
-       if (!elf) {
-               err = -EBADF;
-               pr_warn("usdt: failed to parse ELF binary '%s': %s\n", path, elf_errmsg(-1));
-               goto err_out;
-       }
-
-       err = sanity_check_usdt_elf(elf, path);
+       err = sanity_check_usdt_elf(elf_fd.elf, path);
        if (err)
                goto err_out;
 
        /* discover USDT in given binary, optionally limiting
         * activations to a given PID, if pid > 0
         */
-       err = collect_usdt_targets(man, elf, path, pid, usdt_provider, usdt_name,
+       err = collect_usdt_targets(man, elf_fd.elf, path, pid, usdt_provider, usdt_name,
                                   usdt_cookie, &targets, &target_cnt);
        if (err <= 0) {
                err = (err == 0) ? -ENOENT : err;
 
        free(targets);
        hashmap__free(specs_hash);
-       elf_end(elf);
-       close(fd);
-
+       elf_close(&elf_fd);
        return &link->link;
 
 err_out:
                bpf_link__destroy(&link->link);
        free(targets);
        hashmap__free(specs_hash);
-       if (elf)
-               elf_end(elf);
-       close(fd);
+       elf_close(&elf_fd);
        return libbpf_err_ptr(err);
 }