Commit f90eb70d authored by Jiri Olsa's avatar Jiri Olsa Committed by Alexei Starovoitov

libbpf: Add elf_open/elf_close functions

Adding elf_open/elf_close functions and using it in
elf_find_func_offset_from_file function. It will be
used in following changes to save some common code.
Acked-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20230809083440.3209381-10-jolsa@kernel.orgSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 5c742725
...@@ -10,6 +10,42 @@ ...@@ -10,6 +10,42 @@
#define STRERR_BUFSIZE 128 #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. */ /* 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) static Elf_Scn *elf_find_next_scn_by_type(Elf *elf, int sh_type, Elf_Scn *scn)
{ {
...@@ -170,28 +206,13 @@ long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name) ...@@ -170,28 +206,13 @@ 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) 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; long ret = -ENOENT;
Elf *elf;
int fd;
fd = open(binary_path, O_RDONLY | O_CLOEXEC); ret = elf_open(binary_path, &elf_fd);
if (fd < 0) { if (ret)
ret = -errno;
pr_warn("failed to open %s: %s\n", binary_path,
libbpf_strerror_r(ret, errmsg, sizeof(errmsg)));
return ret; return ret;
} ret = elf_find_func_offset(elf_fd.elf, binary_path, name);
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); elf_close(&elf_fd);
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);
return ret; return ret;
} }
...@@ -581,4 +581,12 @@ int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts); ...@@ -581,4 +581,12 @@ int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts);
long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name); 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); 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 */ #endif /* __LIBBPF_LIBBPF_INTERNAL_H */
...@@ -946,32 +946,22 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct ...@@ -946,32 +946,22 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
const char *usdt_provider, const char *usdt_name, const char *usdt_provider, const char *usdt_name,
__u64 usdt_cookie) __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); LIBBPF_OPTS(bpf_uprobe_opts, opts);
struct hashmap *specs_hash = NULL; struct hashmap *specs_hash = NULL;
struct bpf_link_usdt *link = NULL; struct bpf_link_usdt *link = NULL;
struct usdt_target *targets = NULL; struct usdt_target *targets = NULL;
struct elf_fd elf_fd;
size_t target_cnt; size_t target_cnt;
Elf *elf;
spec_map_fd = bpf_map__fd(man->specs_map); spec_map_fd = bpf_map__fd(man->specs_map);
ip_map_fd = bpf_map__fd(man->ip_to_spec_id_map); ip_map_fd = bpf_map__fd(man->ip_to_spec_id_map);
fd = open(path, O_RDONLY | O_CLOEXEC); err = elf_open(path, &elf_fd);
if (fd < 0) { if (err)
err = -errno;
pr_warn("usdt: failed to open ELF binary '%s': %d\n", path, err);
return libbpf_err_ptr(err); return libbpf_err_ptr(err);
}
elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); err = sanity_check_usdt_elf(elf_fd.elf, path);
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);
if (err) if (err)
goto err_out; goto err_out;
...@@ -984,7 +974,7 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct ...@@ -984,7 +974,7 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
/* discover USDT in given binary, optionally limiting /* discover USDT in given binary, optionally limiting
* activations to a given PID, if pid > 0 * 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); usdt_cookie, &targets, &target_cnt);
if (err <= 0) { if (err <= 0) {
err = (err == 0) ? -ENOENT : err; err = (err == 0) ? -ENOENT : err;
...@@ -1069,9 +1059,7 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct ...@@ -1069,9 +1059,7 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
free(targets); free(targets);
hashmap__free(specs_hash); hashmap__free(specs_hash);
elf_end(elf); elf_close(&elf_fd);
close(fd);
return &link->link; return &link->link;
err_out: err_out:
...@@ -1079,9 +1067,7 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct ...@@ -1079,9 +1067,7 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
bpf_link__destroy(&link->link); bpf_link__destroy(&link->link);
free(targets); free(targets);
hashmap__free(specs_hash); hashmap__free(specs_hash);
if (elf) elf_close(&elf_fd);
elf_end(elf);
close(fd);
return libbpf_err_ptr(err); return libbpf_err_ptr(err);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment