summaryrefslogtreecommitdiff
path: root/arch/x32
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2014-06-18 02:44:02 -0400
committerRich Felker <dalias@aerifal.cx>2014-06-18 02:44:02 -0400
commitadf94c19666e687a728bbf398f9a88ea4ea19996 (patch)
tree8393ad8b9c7db518d0351b36cccc4930614146f6 /arch/x32
parent94cf991bf4b18bb87a15a96e7b5e7d92fab787ba (diff)
downloadmusl-adf94c19666e687a728bbf398f9a88ea4ea19996.tar.gz
refactor to remove arch-specific relocation code from dynamic linker
this was one of the main instances of ugly code duplication: all archs use basically the same types of relocations, but roughly equivalent logic was duplicated for each arch to account for the different naming and numbering of relocation types and variation in whether REL or RELA records are used. as an added bonus, both REL and RELA are now supported on all archs, regardless of which is used by the standard toolchain.
Diffstat (limited to 'arch/x32')
-rw-r--r--arch/x32/reloc.h47
1 files changed, 20 insertions, 27 deletions
diff --git a/arch/x32/reloc.h b/arch/x32/reloc.h
index 1261fb5d..fcfbf99e 100644
--- a/arch/x32/reloc.h
+++ b/arch/x32/reloc.h
@@ -4,44 +4,37 @@
#define LDSO_ARCH "x32"
-#define IS_COPY(x) ((x)==R_X86_64_COPY)
-#define IS_PLT(x) ((x)==R_X86_64_JUMP_SLOT)
+/* FIXME: x32 is very strange in its use of 64-bit relocation types in
+ * a 32-bit environment. As long as the memory at reloc_addr is
+ * zero-filled prior to relocations, just treating 64-bit relocations
+ * as operating on 32-bit slots should be fine, but this should be
+ * checked. In particular, R_X86_64_64, R_X86_64_DTPOFF64, and
+ * R_X86_64_TPOFF64 may need checking. */
-static inline int do_single_reloc(
- struct dso *self, unsigned char *base_addr,
- size_t *reloc_addr, int type, size_t addend,
- Sym *sym, size_t sym_size,
- struct symdef def, size_t sym_val)
+static int remap_rel(int type)
{
switch(type) {
- case R_X86_64_GLOB_DAT:
- case R_X86_64_JUMP_SLOT:
case R_X86_64_64:
- *reloc_addr = sym_val + addend;
- break;
case R_X86_64_32:
- *(uint32_t *)reloc_addr = sym_val + addend;
- break;
+ return REL_SYMBOLIC;
case R_X86_64_PC32:
- *reloc_addr = sym_val + addend - (size_t)reloc_addr + (size_t)base_addr;
- break;
+ return REL_OFFSET;
+ case R_X86_64_GLOB_DAT:
+ return REL_GOT;
+ case R_X86_64_JUMP_SLOT:
+ return REL_PLT;
case R_X86_64_RELATIVE:
- *reloc_addr = (size_t)base_addr + addend;
- break;
+ return REL_RELATIVE;
case R_X86_64_COPY:
- memcpy(reloc_addr, (void *)sym_val, sym_size);
- break;
+ return REL_COPY;
case R_X86_64_DTPMOD64:
- *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
- break;
+ return REL_DTPMOD;
case R_X86_64_DTPOFF64:
- *reloc_addr = def.sym->st_value + addend;
- break;
+ case R_X86_64_DTPOFF32:
+ return REL_DTPOFF;
case R_X86_64_TPOFF64:
- *reloc_addr = (def.sym
- ? def.sym->st_value - def.dso->tls_offset
- : 0 - self->tls_offset) + addend;
- break;
+ case R_X86_64_TPOFF32:
+ return REL_TPOFF;
}
return 0;
}