Commit 434fdcea authored by Daniel Müller's avatar Daniel Müller Committed by Andrii Nakryiko
Browse files

libbpf: Introduce elf_find_func_offset_from_file() function



This change splits the elf_find_func_offset() function in two:
elf_find_func_offset(), which now accepts an already opened Elf object
instead of a path to a file that is to be opened, as well as
elf_find_func_offset_from_file(), which opens a binary based on a
path and then invokes elf_find_func_offset() on the Elf object. Having
this split in responsibilities will allow us to call
elf_find_func_offset() from other code paths on Elf objects that did not
necessarily come from a file on disk.

Signed-off-by: default avatarDaniel Müller <deso@posteo.net>
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20230301212308.1839139-3-deso@posteo.net
parent 1eebcb60
Loading
Loading
Loading
Loading
+36 −21
Original line number Diff line number Diff line
@@ -10530,32 +10530,19 @@ static Elf_Scn *elf_find_next_scn_by_type(Elf *elf, int sh_type, Elf_Scn *scn)
	return NULL;
}

/* Find offset of function name in object specified by path.  "name" matches
 * symbol name or name@@LIB for library functions.
/* Find offset of function name in the provided ELF object. "binary_path" is
 * the path to the ELF binary represented by "elf", and only used for error
 * reporting matters. "name" matches symbol name or name@@LIB for library
 * functions.
 */
static long elf_find_func_offset(const char *binary_path, const char *name)
static long elf_find_func_offset(Elf *elf, const char *binary_path, const char *name)
{
	int fd, i, sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB };
	int i, sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB };
	bool is_shared_lib, is_name_qualified;
	char errmsg[STRERR_BUFSIZE];
	long ret = -ENOENT;
	size_t name_len;
	GElf_Ehdr ehdr;
	Elf *elf;

	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)));
		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;
	}
	if (!gelf_getehdr(elf, &ehdr)) {
		pr_warn("elf: failed to get ehdr from %s: %s\n", binary_path, elf_errmsg(-1));
		ret = -LIBBPF_ERRNO__FORMAT;
@@ -10681,6 +10668,34 @@ static long elf_find_func_offset(const char *binary_path, const char *name)
		}
	}
out:
	return ret;
}

/* Find offset of function name in ELF object specified by path. "name" matches
 * symbol name or name@@LIB for library functions.
 */
static long elf_find_func_offset_from_file(const char *binary_path, const char *name)
{
	char errmsg[STRERR_BUFSIZE];
	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)));
		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);
	return ret;
@@ -10804,7 +10819,7 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid,
	if (func_name) {
		long sym_off;

		sym_off = elf_find_func_offset(binary_path, func_name);
		sym_off = elf_find_func_offset_from_file(binary_path, func_name);
		if (sym_off < 0)
			return libbpf_err_ptr(sym_off);
		func_offset += sym_off;