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)) {
22 /* Hazard a guess where a function may be found in the PLT */
23 static GElf_Word pltLookupVal(ElfuElf *metarget, char *name)
30 relplt = elfu_mScnForall(metarget, subFindByName, ".rel.plt", NULL);
32 ELFU_WARN("dynsymLookupVal: Could not find .rel.plt section in destination ELF.\n");
36 plt = elfu_mScnForall(metarget, subFindByName, ".plt", NULL);
38 ELFU_WARN("dynsymLookupVal: Could not find .plt section in destination ELF.\n");
44 assert(relplt->linkptr);
46 CIRCLEQ_FOREACH(rel, &relplt->reltab.rels, elem) {
52 if (rel->type != R_386_JMP_SLOT) {
56 sym = CIRCLEQ_FIRST(&relplt->linkptr->symtab.syms);
57 for (i = 1; i < rel->sym; i++) {
58 sym = CIRCLEQ_NEXT(sym, elem);
65 if (!strcmp(sym->nameptr, name)) {
66 /* If this is the symbol we are looking for, then in an x86 binary
67 * the jump to the dynamic symbol is probably at offset (j * 16)
68 * from the start of the PLT, where j is the PLT entry and 16 is
69 * the number of bytes the machine code in a PLT entry take. */
70 GElf_Addr addr = plt->shdr.sh_addr + (16 * j);
71 ELFU_DEBUG("dynsymLookupVal: Guessing symbol '%s' is in destination memory at %jx (PLT entry #%d).\n", name, addr, j);
76 ELFU_WARN("dynsymLookupVal: Could not find symbol '%s' in destination ELF.\n", name);
82 static GElf_Word symtabLookupVal(ElfuElf *metarget, ElfuScn *msst, GElf_Word entry)
90 assert(!CIRCLEQ_EMPTY(&msst->symtab.syms));
92 sym = CIRCLEQ_FIRST(&msst->symtab.syms);
93 for (i = 1; i < entry; i++) {
94 sym = CIRCLEQ_NEXT(sym, elem);
102 assert(elfu_mScnByOldscn(metarget, sym->scnptr));
103 return elfu_mScnByOldscn(metarget, sym->scnptr)->shdr.sh_addr + sym->value;
104 } else if (sym->shndx == SHN_UNDEF) {
105 /* Look the symbol up in .dyn.plt. If it cannot be found there then
106 * .rel.dyn may need to be expanded with a COPY relocation so the
107 * dynamic linker fixes up the (TODO). */
108 return pltLookupVal(metarget, sym->nameptr);
109 } else if (sym->shndx == SHN_ABS) {
112 ELFU_WARN("symtabLookupVal: Symbol binding COMMON is not supported, using 0.\n");
118 assert(elfu_mScnByOldscn(metarget, sym->scnptr));
119 return elfu_mScnByOldscn(metarget, sym->scnptr)->shdr.sh_addr;
121 ELFU_WARN("symtabLookupVal: Symbol type FILE is not supported, using 0.\n");
124 ELFU_WARN("symtabLookupVal: Unknown symbol type %d for %s.\n", sym->type, sym->nameptr);
129 void elfu_mRelocate32(ElfuElf *metarget, ElfuScn *mstarget, ElfuScn *msrt)
136 ELFU_DEBUG("Relocating in section of type %d size %jx\n",
137 mstarget->shdr.sh_type,
138 mstarget->shdr.sh_size);
140 CIRCLEQ_FOREACH(rel, &msrt->reltab.rels, elem) {
141 Elf32_Word *dest = (Elf32_Word*)(((char*)(mstarget->data.d_buf)) + rel->offset);
142 Elf32_Word a = rel->addendUsed ? rel->addend : *dest;
143 Elf32_Addr p = mstarget->shdr.sh_addr + rel->offset;
144 Elf32_Addr s = symtabLookupVal(metarget, msrt->linkptr, rel->sym);
145 Elf32_Word newval = *dest;
149 ELFU_DEBUG("Skipping relocation: R_386_NONE");
152 ELFU_DEBUG("Relocation: R_386_32");
156 ELFU_DEBUG("Relocation: R_386_PC32");
161 ELFU_DEBUG("Skipping relocation: Unknown type %d", rel->type);
163 ELFU_DEBUG(", overwriting %x with %x.\n", *dest, newval);