1 /* This file is part of centaur.
3 * centaur is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License 2 as
5 * published by the Free Software Foundation.
7 * centaur is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with centaur. If not, see <http://www.gnu.org/licenses/>.
19 #include <libelfu/libelfu.h>
22 /* Apply relocation information from section *msrt to data in
23 * section *mstarget (which is stored in *metarget). */
24 int elfu_mRelocate(ElfuElf *metarget, ElfuScn *mstarget, ElfuScn *msrt)
32 ELFU_DEBUG("Relocating in section of type %u size %x\n",
33 mstarget->shdr.sh_type,
34 (unsigned)mstarget->shdr.sh_size);
36 CIRCLEQ_FOREACH(rel, &msrt->reltab.rels, elem) {
37 Elf32_Word *dest32 = (Elf32_Word*)(mstarget->databuf + rel->offset);
38 Elf64_Word *dest64 = (Elf64_Word*)(mstarget->databuf + rel->offset);
42 sym = elfu_mSymtabIndexToSym(msrt->linkptr, rel->sym);
45 haveSymval = !elfu_mSymtabLookupSymToAddr(metarget,
50 if (sym->shndx == SHN_UNDEF) {
51 haveSymval = !elfu_mDynLookupPltAddrByName(metarget,
52 elfu_mSymtabSymToName(msrt->linkptr, sym),
55 haveSymval = !elfu_mDynLookupReldynAddrByName(metarget,
56 elfu_mSymtabSymToName(msrt->linkptr, sym),
62 if (metarget->elfclass == ELFCLASS32) {
63 Elf32_Word a32 = rel->addendUsed ? rel->addend : *dest32;
64 Elf32_Addr p32 = mstarget->shdr.sh_addr + rel->offset;
65 Elf32_Addr s32 = (Elf32_Addr)s;
67 switch(metarget->ehdr.e_machine) {
71 ELFU_DEBUG("Skipping relocation: R_386_NONE\n");
83 *dest32 = s32 + a32 - p32;
86 ELFU_DEBUG("elfu_mRelocate: Skipping unknown relocation type %d\n", rel->type);
90 ELFU_WARN("elfu_mRelocate: Unknown machine type. Aborting.\n");
92 } else if (metarget->elfclass == ELFCLASS64) {
93 Elf64_Word a64 = rel->addendUsed ? rel->addend : *dest64;
94 Elf64_Addr p64 = mstarget->shdr.sh_addr + rel->offset;
95 Elf64_Addr s64 = (Elf64_Addr)s;
97 switch(metarget->ehdr.e_machine) {
101 ELFU_DEBUG("Skipping relocation: R_386_NONE\n");
113 *dest32 = s64 + a64 - p64;
122 ELFU_DEBUG("elfu_mRelocate: Skipping unknown relocation type %d", rel->type);
126 ELFU_WARN("elfu_mRelocate: Unknown machine type. Aborting.\n");
134 ELFU_WARN("elfu_mRelocate: Could not resolve symbol %s. Aborting.\n",
135 elfu_mSymtabSymToName(msrt->linkptr, sym));