4 #include <libelfu/libelfu.h>
7 static void* subFindByName(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2)
9 char *name = (char*)aux1;
12 if (elfu_mScnName(me, ms)) {
13 if (!strcmp(elfu_mScnName(me, ms), name)) {
23 /* Hazard a guess where a function may be found in the PLT */
24 int elfu_mDynLookupPltAddrByName(ElfuElf *me, char *name, GElf_Addr *result)
31 relplt = elfu_mScnForall(me, subFindByName, ".rel.plt", NULL);
33 /* x86-64 uses .rela.plt instead */
34 relplt = elfu_mScnForall(me, subFindByName, ".rela.plt", NULL);
37 ELFU_WARN("elfu_mDynLookupPltAddr: Could not find .rel.plt section in destination ELF.\n");
41 plt = elfu_mScnForall(me, subFindByName, ".plt", NULL);
43 ELFU_WARN("elfu_mDynLookupPltAddr: Could not find .plt section in destination ELF.\n");
48 /* Look up name. If the j-th entry in .rel.plt has the name we are
49 * looking for, we assume that the (j+1)-th entry in .plt is machine
50 * code to jump to the function.
51 * Your mileage may vary, but it works on my GNU binaries. */
52 assert(relplt->linkptr);
54 CIRCLEQ_FOREACH(rel, &relplt->reltab.rels, elem) {
61 /* We only consider runtime relocations for functions.
62 * Technically, these relocations write the functions' addresses
63 * to the GOT, not the PLT, after the dynamic linker has found
65 if ((me->elfclass == ELFCLASS32 && rel->type != R_386_JMP_SLOT)
66 || (me->elfclass == ELFCLASS64 && rel->type != R_X86_64_JUMP_SLOT)) {
70 /* Get the (rel->sym)-th symbol from the symbol table that
71 * .rel.plt points to. */
72 sym = CIRCLEQ_FIRST(&relplt->linkptr->symtab.syms);
73 for (i = 1; i < rel->sym; i++) {
74 sym = CIRCLEQ_NEXT(sym, elem);
77 symname = ELFU_SYMSTR(relplt->linkptr, sym->name);
78 if (!strcmp(symname, name)) {
79 /* If this is the symbol we are looking for, then in an x86 binary
80 * the jump to the dynamic symbol is probably at offset (j * 16)
81 * from the start of the PLT, where j is the PLT entry and 16 is
82 * the number of bytes the machine code in a PLT entry take. */
83 GElf_Addr addr = plt->shdr.sh_addr + (16 * j);
84 ELFU_DEBUG("elfu_mDynLookupPltAddr: Guessing symbol '%s' is in destination memory at %x (PLT entry #%u).\n", name, (unsigned)addr, j);
90 ELFU_WARN("elfu_mDynLookupPltAddr: Could not find symbol '%s' in destination ELF.\n", name);