X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=src%2Flibelfu%2Fmodelops%2Fdynlookup.c;h=e20adfea0446714c2a8b67253df421cd1bed10b7;hb=1ca19c5484ee0f18a3701b3f98ac8ca43df8b505;hp=a2cd3ae7a84eaedbe3aa7f79184bb1d3cee8ae59;hpb=bac3bc42ef0133a7dda0870c4e1f37e5651feb99;p=centaur.git diff --git a/src/libelfu/modelops/dynlookup.c b/src/libelfu/modelops/dynlookup.c index a2cd3ae..e20adfe 100644 --- a/src/libelfu/modelops/dynlookup.c +++ b/src/libelfu/modelops/dynlookup.c @@ -91,3 +91,60 @@ int elfu_mDynLookupPltAddrByName(ElfuElf *me, char *name, GElf_Addr *result) return -1; } + + + +/* Hazard a guess where a global variable may be found in .bss, + * based on dynamic linking information in .rel.dyn */ +int elfu_mDynLookupReldynAddrByName(ElfuElf *me, char *name, GElf_Addr *result) +{ + ElfuScn *reldyn; + ElfuRel *rel; + GElf_Word j; + + reldyn = elfu_mScnForall(me, subFindByName, ".rel.dyn", NULL); + if (!reldyn) { + /* x86-64 uses .rela.dyn instead */ + reldyn = elfu_mScnForall(me, subFindByName, ".rela.dyn", NULL); + } + if (!reldyn) { + ELFU_WARN("elfu_mDynLookupReldynAddrByName: Could not find .rel.dyn section in destination ELF.\n"); + return -1; + } + + + assert(reldyn->linkptr); + j = 0; + CIRCLEQ_FOREACH(rel, &reldyn->reltab.rels, elem) { + ElfuSym *sym; + char *symname; + + j++; + + /* We only consider COPY relocations for global variables here. + * Technically, these relocations write the variables' contents + * to .bss. */ + if ((me->elfclass == ELFCLASS32 && rel->type != R_386_COPY) + || (me->elfclass == ELFCLASS64 && rel->type != R_X86_64_COPY)) { + continue; + } + + /* Get the (rel->sym)-th symbol from the symbol table that + * .rel.dyn points to. */ + sym = elfu_mSymtabIndexToSym(reldyn->linkptr, rel->sym); + assert(sym); + + symname = elfu_mSymtabSymToName(reldyn->linkptr, sym); + if (!strcmp(symname, name)) { + GElf_Addr addr = rel->offset; + ELFU_DEBUG("elfu_mDynLookupReldynAddrByName: Guessing symbol '%s' is in destination memory at %x (PLT entry #%u).\n", name, (unsigned)addr, j); + *result = addr; + return 0; + } + } + + ELFU_WARN("elfu_mDynLookupReldynAddrByName: Could not find or use symbol '%s' in destination ELF.\n", name); + ELFU_WARN(" NOTE: Only R_*_COPY relocations are resolved to global variables.\n"); + + return -1; +}