Commit e613d1d0 authored by Jiri Olsa's avatar Jiri Olsa Committed by Alexei Starovoitov
Browse files

libbpf: Add elf_resolve_pattern_offsets function



Adding elf_resolve_pattern_offsets function that looks up
offsets for symbols specified by pattern argument.

The 'pattern' argument allows wildcards (*?' supported).

Offsets are returned in allocated array together with its
size and needs to be released by the caller.

Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20230809083440.3209381-13-jolsa@kernel.org


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 7ace84c6
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -377,3 +377,64 @@ int elf_resolve_syms_offsets(const char *binary_path, int cnt,
	elf_close(&elf_fd);
	return err;
}

/*
 * Return offsets in @poffsets for symbols specified by @pattern argument.
 * On success returns 0 and offsets are returned in allocated @poffsets
 * array with the @pctn size, that needs to be released by the caller.
 */
int elf_resolve_pattern_offsets(const char *binary_path, const char *pattern,
				unsigned long **poffsets, size_t *pcnt)
{
	int sh_types[2] = { SHT_SYMTAB, SHT_DYNSYM };
	unsigned long *offsets = NULL;
	size_t cap = 0, cnt = 0;
	struct elf_fd elf_fd;
	int err = 0, i;

	err = elf_open(binary_path, &elf_fd);
	if (err)
		return err;

	for (i = 0; i < ARRAY_SIZE(sh_types); i++) {
		struct elf_sym_iter iter;
		struct elf_sym *sym;

		err = elf_sym_iter_new(&iter, elf_fd.elf, binary_path, sh_types[i], STT_FUNC);
		if (err == -ENOENT)
			continue;
		if (err)
			goto out;

		while ((sym = elf_sym_iter_next(&iter))) {
			if (!glob_match(sym->name, pattern))
				continue;

			err = libbpf_ensure_mem((void **) &offsets, &cap, sizeof(*offsets),
						cnt + 1);
			if (err)
				goto out;

			offsets[cnt++] = elf_sym_offset(sym);
		}

		/* If we found anything in the first symbol section,
		 * do not search others to avoid duplicates.
		 */
		if (cnt)
			break;
	}

	if (cnt) {
		*poffsets = offsets;
		*pcnt = cnt;
	} else {
		err = -ENOENT;
	}

out:
	if (err)
		free(offsets);
	elf_close(&elf_fd);
	return err;
}
+1 −1
Original line number Diff line number Diff line
@@ -10569,7 +10569,7 @@ struct bpf_link *bpf_program__attach_ksyscall(const struct bpf_program *prog,
}

/* Adapted from perf/util/string.c */
static bool glob_match(const char *str, const char *pat)
bool glob_match(const char *str, const char *pat)
{
	while (*str && *pat && *pat != '*') {
		if (*pat == '?') {      /* Matches any single character */
+5 −0
Original line number Diff line number Diff line
@@ -578,6 +578,8 @@ static inline bool is_pow_of_2(size_t x)
#define PROG_LOAD_ATTEMPTS 5
int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts);

bool glob_match(const char *str, const char *pat);

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);

@@ -591,4 +593,7 @@ void elf_close(struct elf_fd *elf_fd);

int elf_resolve_syms_offsets(const char *binary_path, int cnt,
			     const char **syms, unsigned long **poffsets);
int elf_resolve_pattern_offsets(const char *binary_path, const char *pattern,
				 unsigned long **poffsets, size_t *pcnt);

#endif /* __LIBBPF_LIBBPF_INTERNAL_H */