OSDN Git Service

libbpf: Add elf_resolve_pattern_offsets function
authorJiri Olsa <jolsa@kernel.org>
Wed, 9 Aug 2023 08:34:24 +0000 (10:34 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 21 Aug 2023 22:51:26 +0000 (15:51 -0700)
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: Jiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20230809083440.3209381-13-jolsa@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/lib/bpf/elf.c
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf_internal.h

index 8c51264..9d0296c 100644 (file)
@@ -377,3 +377,64 @@ out:
        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;
+}
index c05dd32..88a38e6 100644 (file)
@@ -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 */
index 92851c5..ead5513 100644 (file)
@@ -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 */