/**
 * @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;
}
Exemple #2
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;
		}
	}
}