in helpers/uprobe_helpers.c [224:289]
off_t get_elf_func_offset(const char *path, const char *func)
{
off_t ret = -1;
int i, fd = -1;
Elf *e;
Elf_Scn *scn;
Elf_Data *data;
GElf_Ehdr ehdr;
GElf_Shdr shdr[1];
GElf_Phdr phdr;
GElf_Sym sym[1];
size_t shstrndx, nhdrs;
char *n;
e = open_elf(path, &fd);
if (!gelf_getehdr(e, &ehdr))
goto out;
if (elf_getshdrstrndx(e, &shstrndx) != 0)
goto out;
scn = NULL;
while ((scn = elf_nextscn(e, scn))) {
if (!gelf_getshdr(scn, shdr))
continue;
if (!(shdr->sh_type == SHT_SYMTAB || shdr->sh_type == SHT_DYNSYM))
continue;
data = NULL;
while ((data = elf_getdata(scn, data))) {
for (i = 0; gelf_getsym(data, i, sym); i++) {
n = elf_strptr(e, shdr->sh_link, sym->st_name);
if (!n)
continue;
if (GELF_ST_TYPE(sym->st_info) != STT_FUNC)
continue;
if (!strcmp(n, func)) {
ret = sym->st_value;
goto check;
}
}
}
}
check:
if (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_DYN) {
if (elf_getphdrnum(e, &nhdrs) != 0) {
ret = -1;
goto out;
}
for (i = 0; i < (int)nhdrs; i++) {
if (!gelf_getphdr(e, i, &phdr))
continue;
if (phdr.p_type != PT_LOAD || !(phdr.p_flags & PF_X))
continue;
if (phdr.p_vaddr <= ret && ret < (phdr.p_vaddr + phdr.p_memsz)) {
ret = ret - phdr.p_vaddr + phdr.p_offset;
goto out;
}
}
ret = -1;
}
out:
close_elf(e, fd);
return ret;
}