summaryrefslogtreecommitdiff
path: root/src/modelops/relocate.c
diff options
context:
space:
mode:
authornorly <ny-git@enpas.org>2013-06-15 21:42:53 +0100
committernorly <ny-git@enpas.org>2013-06-15 22:02:26 +0100
commit825613b8e4f141a82d2b8be22d7fba68fed5ef96 (patch)
tree8ade4e195c1a77a3814c44109c4f5cc9e1a5ced7 /src/modelops/relocate.c
parent5868bb32246367139f0d17a989650964f90a7958 (diff)
Basic x86-64 support, not very usable in practice
Turns out that x86-64 aligns LOAD segments to 0x200000 bytes. Given that the mapping starts at 0x400000, there is not much room to expand... so there will be a need to add additional LOAD headers.
Diffstat (limited to 'src/modelops/relocate.c')
-rw-r--r--src/modelops/relocate.c74
1 files changed, 50 insertions, 24 deletions
diff --git a/src/modelops/relocate.c b/src/modelops/relocate.c
index ea84937..2c9873c 100644
--- a/src/modelops/relocate.c
+++ b/src/modelops/relocate.c
@@ -57,7 +57,8 @@ static GElf_Word pltLookupVal(ElfuElf *metarget, char *name)
* Technically, these relocations write the functions' addresses
* to the GOT, not the PLT, after the dynamic linker has found
* them. */
- if (rel->type != R_386_JMP_SLOT) {
+ if ((metarget->elfclass == ELFCLASS32 && rel->type != R_386_JMP_SLOT)
+ || (metarget->elfclass == ELFCLASS64 && rel->type != R_X86_64_JUMP_SLOT)) {
continue;
}
@@ -148,29 +149,54 @@ void elfu_mRelocate32(ElfuElf *metarget, ElfuScn *mstarget, ElfuScn *msrt)
mstarget->shdr.sh_size);
CIRCLEQ_FOREACH(rel, &msrt->reltab.rels, elem) {
- Elf32_Word *dest = (Elf32_Word*)(((char*)(mstarget->data.d_buf)) + rel->offset);
- Elf32_Word a = rel->addendUsed ? rel->addend : *dest;
- Elf32_Addr p = mstarget->shdr.sh_addr + rel->offset;
- Elf32_Addr s = symtabLookupVal(metarget, msrt->linkptr, rel->sym);
- Elf32_Word newval = *dest;
-
- switch(rel->type) {
- case R_386_NONE:
- ELFU_DEBUG("Skipping relocation: R_386_NONE");
- break;
- case R_386_32:
- ELFU_DEBUG("Relocation: R_386_32");
- newval = s + a;
- break;
- case R_386_PC32:
- ELFU_DEBUG("Relocation: R_386_PC32");
- newval = s + a - p;
- break;
-
- default:
- ELFU_DEBUG("Skipping relocation: Unknown type %d", rel->type);
+ Elf32_Word *dest32 = (Elf32_Word*)(((char*)(mstarget->data.d_buf)) + rel->offset);
+ Elf64_Word *dest64 = (Elf64_Word*)(((char*)(mstarget->data.d_buf)) + rel->offset);
+
+
+ if (metarget->elfclass == ELFCLASS32) {
+ Elf32_Word a32 = rel->addendUsed ? rel->addend : *dest32;
+ Elf32_Addr p32 = mstarget->shdr.sh_addr + rel->offset;
+ Elf32_Addr s32 = symtabLookupVal(metarget, msrt->linkptr, rel->sym);
+ switch(rel->type) {
+ case R_386_NONE:
+ ELFU_DEBUG("Skipping relocation: R_386_NONE\n");
+ break;
+ case R_386_32:
+ *dest32 = s32 + a32;
+ break;
+ case R_386_PC32:
+ *dest32 = s32 + a32 - p32;
+ break;
+
+ default:
+ ELFU_DEBUG("Skipping relocation: Unknown type %d\n", rel->type);
+ }
+ } else if (metarget->elfclass == ELFCLASS64) {
+ /* x86-64 only uses RELA with explicit addend. */
+ assert(rel->addendUsed);
+ Elf64_Word a64 = rel->addend;
+ Elf64_Addr p64 = mstarget->shdr.sh_addr + rel->offset;
+ Elf64_Addr s64 = symtabLookupVal(metarget, msrt->linkptr, rel->sym);
+
+ switch(rel->type) {
+ case R_X86_64_NONE:
+ ELFU_DEBUG("Skipping relocation: R_386_NONE\n");
+ break;
+ case R_X86_64_64:
+ *dest64 = s64 + a64;
+ break;
+ case R_X86_64_PC32:
+ *dest32 = s64 + a64 - p64;
+ break;
+ case R_X86_64_32:
+ *dest32 = s64 + a64;
+ break;
+
+ default:
+ ELFU_DEBUG("Skipping relocation: Unknown type %d", rel->type);
+ }
}
- ELFU_DEBUG(", overwriting %x with %x.\n", *dest, newval);
- *dest = newval;
+
+
}
}