Skip to content

Commit 7ace84c

Browse files
olsajiriAlexei Starovoitov
authored andcommitted
libbpf: Add elf_resolve_syms_offsets function
Adding elf_resolve_syms_offsets function that looks up offsets for symbols specified in syms array argument. Offsets are returned in allocated array with the 'cnt' size, that needs to be released by the caller. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Link: https://lore.kernel.org/r/20230809083440.3209381-12-jolsa@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 3774705 commit 7ace84c

2 files changed

Lines changed: 112 additions & 0 deletions

File tree

tools/lib/bpf/elf.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,113 @@ long elf_find_func_offset_from_file(const char *binary_path, const char *name)
267267
elf_close(&elf_fd);
268268
return ret;
269269
}
270+
271+
struct symbol {
272+
const char *name;
273+
int bind;
274+
int idx;
275+
};
276+
277+
static int symbol_cmp(const void *a, const void *b)
278+
{
279+
const struct symbol *sym_a = a;
280+
const struct symbol *sym_b = b;
281+
282+
return strcmp(sym_a->name, sym_b->name);
283+
}
284+
285+
/*
286+
* Return offsets in @poffsets for symbols specified in @syms array argument.
287+
* On success returns 0 and offsets are returned in allocated array with @cnt
288+
* size, that needs to be released by the caller.
289+
*/
290+
int elf_resolve_syms_offsets(const char *binary_path, int cnt,
291+
const char **syms, unsigned long **poffsets)
292+
{
293+
int sh_types[2] = { SHT_DYNSYM, SHT_SYMTAB };
294+
int err = 0, i, cnt_done = 0;
295+
unsigned long *offsets;
296+
struct symbol *symbols;
297+
struct elf_fd elf_fd;
298+
299+
err = elf_open(binary_path, &elf_fd);
300+
if (err)
301+
return err;
302+
303+
offsets = calloc(cnt, sizeof(*offsets));
304+
symbols = calloc(cnt, sizeof(*symbols));
305+
306+
if (!offsets || !symbols) {
307+
err = -ENOMEM;
308+
goto out;
309+
}
310+
311+
for (i = 0; i < cnt; i++) {
312+
symbols[i].name = syms[i];
313+
symbols[i].idx = i;
314+
}
315+
316+
qsort(symbols, cnt, sizeof(*symbols), symbol_cmp);
317+
318+
for (i = 0; i < ARRAY_SIZE(sh_types); i++) {
319+
struct elf_sym_iter iter;
320+
struct elf_sym *sym;
321+
322+
err = elf_sym_iter_new(&iter, elf_fd.elf, binary_path, sh_types[i], STT_FUNC);
323+
if (err == -ENOENT)
324+
continue;
325+
if (err)
326+
goto out;
327+
328+
while ((sym = elf_sym_iter_next(&iter))) {
329+
unsigned long sym_offset = elf_sym_offset(sym);
330+
int bind = GELF_ST_BIND(sym->sym.st_info);
331+
struct symbol *found, tmp = {
332+
.name = sym->name,
333+
};
334+
unsigned long *offset;
335+
336+
found = bsearch(&tmp, symbols, cnt, sizeof(*symbols), symbol_cmp);
337+
if (!found)
338+
continue;
339+
340+
offset = &offsets[found->idx];
341+
if (*offset > 0) {
342+
/* same offset, no problem */
343+
if (*offset == sym_offset)
344+
continue;
345+
/* handle multiple matches */
346+
if (found->bind != STB_WEAK && bind != STB_WEAK) {
347+
/* Only accept one non-weak bind. */
348+
pr_warn("elf: ambiguous match found '%s@%lu' in '%s' previous offset %lu\n",
349+
sym->name, sym_offset, binary_path, *offset);
350+
err = -ESRCH;
351+
goto out;
352+
} else if (bind == STB_WEAK) {
353+
/* already have a non-weak bind, and
354+
* this is a weak bind, so ignore.
355+
*/
356+
continue;
357+
}
358+
} else {
359+
cnt_done++;
360+
}
361+
*offset = sym_offset;
362+
found->bind = bind;
363+
}
364+
}
365+
366+
if (cnt != cnt_done) {
367+
err = -ENOENT;
368+
goto out;
369+
}
370+
371+
*poffsets = offsets;
372+
373+
out:
374+
free(symbols);
375+
if (err)
376+
free(offsets);
377+
elf_close(&elf_fd);
378+
return err;
379+
}

tools/lib/bpf/libbpf_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,4 +589,6 @@ struct elf_fd {
589589
int elf_open(const char *binary_path, struct elf_fd *elf_fd);
590590
void elf_close(struct elf_fd *elf_fd);
591591

592+
int elf_resolve_syms_offsets(const char *binary_path, int cnt,
593+
const char **syms, unsigned long **poffsets);
592594
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */

0 commit comments

Comments
 (0)