/** * @brief Search an entire open ELF object for a named symbol * * @param elf THe open ELF object * @param name The symbol name to find * * @returns The address to which the symbol points, 0 otherwise. */ static GElf_Addr elf_getsymaddr_byname(Elf *elf, const char * name) { uint32_t symtab_idx = 0; Elf_Scn *symtab; GElf_Addr addr = 0; symtab = elf_getsymtab(elf, &symtab_idx); while(symtab != NULL) { addr = elf_scn_getsymaddr_byname(elf, symtab, name); if (addr) { return addr; } symtab_idx++; symtab = elf_getsymtab(elf, &symtab_idx); } return 0; }
static void elf_reloc_apply(const char *p, const char *shstab, size_t shstabsz, ssize_t sidx, char *sdata, size_t ssz) { Elf_Ehdr *eh = (Elf_Ehdr *)p; Elf_Shdr *sh; Elf_Rel *rel = NULL; Elf_RelA *rela = NULL; const Elf_Sym *symtab, *sym; ssize_t symtabidx; size_t nsymb, rsym, rtyp, roff; size_t i, j; uint64_t value; int rsize; /* Find symbol table location and number of symbols. */ symtabidx = elf_getsymtab(p, shstab, shstabsz, &symtab, &nsymb); if (symtabidx == -1) { warnx("symbol table not found"); return; } /* Apply possible relocation. */ for (i = 0; i < eh->e_shnum; i++) { sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize); if (sh->sh_size == 0) continue; if ((sh->sh_info != sidx) || (sh->sh_link != symtabidx)) continue; switch (sh->sh_type) { case SHT_RELA: rela = (Elf_RelA *)(p + sh->sh_offset); for (j = 0; j < (sh->sh_size / sizeof(Elf_RelA)); j++) { rsym = ELF_R_SYM(rela[j].r_info); rtyp = ELF_R_TYPE(rela[j].r_info); roff = rela[j].r_offset; if (rsym >= nsymb) continue; sym = &symtab[rsym]; value = sym->st_value + rela[j].r_addend; rsize = elf_reloc_size(rtyp); if (rsize == -1 || roff + rsize >= ssz) continue; ELF_WRITE_RELOC(sdata + roff, value, rsize); } break; case SHT_REL: rel = (Elf_Rel *)(p + sh->sh_offset); for (j = 0; j < (sh->sh_size / sizeof(Elf_Rel)); j++) { rsym = ELF_R_SYM(rel[j].r_info); rtyp = ELF_R_TYPE(rel[j].r_info); roff = rel[j].r_offset; if (rsym >= nsymb) continue; sym = &symtab[rsym]; value = sym->st_value; rsize = elf_reloc_size(rtyp); if (rsize == -1 || roff + rsize >= ssz) continue; ELF_WRITE_RELOC(sdata + roff, value, rsize); } break; default: continue; } } }