summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rts/linker/ELFRelocs/AArch64.def201
-rw-r--r--rts/linker/ELFRelocs/ARM.def138
-rw-r--r--rts/linker/ELFRelocs/LICENSE-LLVM.TXT68
-rw-r--r--rts/linker/ELFRelocs/i386.def47
-rw-r--r--rts/linker/ELFRelocs/x86_64.def45
-rw-r--r--rts/linker/Elf.c177
-rw-r--r--rts/linker/elf_compat.h35
-rw-r--r--rts/linker/elf_util.c24
-rw-r--r--rts/linker/elf_util.h18
-rw-r--r--rts/linker/util.h30
10 files changed, 671 insertions, 112 deletions
diff --git a/rts/linker/ELFRelocs/AArch64.def b/rts/linker/ELFRelocs/AArch64.def
new file mode 100644
index 0000000000..c21df07d2d
--- /dev/null
+++ b/rts/linker/ELFRelocs/AArch64.def
@@ -0,0 +1,201 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// Based on ABI release 1.1-beta, dated 6 November 2013. NB: The cover page of
+// this document, IHI0056C_beta_aaelf64.pdf, on infocenter.arm.com, still
+// labels this as release 1.0.
+ELF_RELOC(R_AARCH64_NONE, 0)
+ELF_RELOC(R_AARCH64_ABS64, 0x101)
+ELF_RELOC(R_AARCH64_ABS32, 0x102)
+ELF_RELOC(R_AARCH64_ABS16, 0x103)
+ELF_RELOC(R_AARCH64_PREL64, 0x104)
+ELF_RELOC(R_AARCH64_PREL32, 0x105)
+ELF_RELOC(R_AARCH64_PREL16, 0x106)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G0, 0x107)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G0_NC, 0x108)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G1, 0x109)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G1_NC, 0x10a)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G2, 0x10b)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G2_NC, 0x10c)
+ELF_RELOC(R_AARCH64_MOVW_UABS_G3, 0x10d)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G0, 0x10e)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G1, 0x10f)
+ELF_RELOC(R_AARCH64_MOVW_SABS_G2, 0x110)
+ELF_RELOC(R_AARCH64_LD_PREL_LO19, 0x111)
+ELF_RELOC(R_AARCH64_ADR_PREL_LO21, 0x112)
+ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21, 0x113)
+ELF_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC, 0x114)
+ELF_RELOC(R_AARCH64_ADD_ABS_LO12_NC, 0x115)
+ELF_RELOC(R_AARCH64_LDST8_ABS_LO12_NC, 0x116)
+ELF_RELOC(R_AARCH64_TSTBR14, 0x117)
+ELF_RELOC(R_AARCH64_CONDBR19, 0x118)
+ELF_RELOC(R_AARCH64_JUMP26, 0x11a)
+ELF_RELOC(R_AARCH64_CALL26, 0x11b)
+ELF_RELOC(R_AARCH64_LDST16_ABS_LO12_NC, 0x11c)
+ELF_RELOC(R_AARCH64_LDST32_ABS_LO12_NC, 0x11d)
+ELF_RELOC(R_AARCH64_LDST64_ABS_LO12_NC, 0x11e)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G0, 0x11f)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G0_NC, 0x120)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G1, 0x121)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G1_NC, 0x122)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G2, 0x123)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G2_NC, 0x124)
+ELF_RELOC(R_AARCH64_MOVW_PREL_G3, 0x125)
+ELF_RELOC(R_AARCH64_LDST128_ABS_LO12_NC, 0x12b)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0, 0x12c)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC, 0x12d)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1, 0x12e)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC, 0x12f)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2, 0x130)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC, 0x131)
+ELF_RELOC(R_AARCH64_MOVW_GOTOFF_G3, 0x132)
+ELF_RELOC(R_AARCH64_GOTREL64, 0x133)
+ELF_RELOC(R_AARCH64_GOTREL32, 0x134)
+ELF_RELOC(R_AARCH64_GOT_LD_PREL19, 0x135)
+ELF_RELOC(R_AARCH64_LD64_GOTOFF_LO15, 0x136)
+ELF_RELOC(R_AARCH64_ADR_GOT_PAGE, 0x137)
+ELF_RELOC(R_AARCH64_LD64_GOT_LO12_NC, 0x138)
+ELF_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 0x139)
+ELF_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 0x200)
+ELF_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 0x201)
+ELF_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC, 0x202)
+ELF_RELOC(R_AARCH64_TLSGD_MOVW_G1, 0x203)
+ELF_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC, 0x204)
+ELF_RELOC(R_AARCH64_TLSLD_ADR_PREL21, 0x205)
+ELF_RELOC(R_AARCH64_TLSLD_ADR_PAGE21, 0x206)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC, 0x207)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_G1, 0x208)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC, 0x209)
+ELF_RELOC(R_AARCH64_TLSLD_LD_PREL19, 0x20a)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2, 0x20b)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1, 0x20c)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, 0x20d)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0, 0x20e)
+ELF_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, 0x20f)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12, 0x210)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12, 0x211)
+ELF_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, 0x212)
+ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, 0x213)
+ELF_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, 0x214)
+ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, 0x215)
+ELF_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, 0x216)
+ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, 0x217)
+ELF_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, 0x218)
+ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, 0x219)
+ELF_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, 0x21a)
+ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 0x21b)
+ELF_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 0x21c)
+ELF_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 0x21d)
+ELF_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 0x21e)
+ELF_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 0x21f)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2, 0x220)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1, 0x221)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 0x222)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0, 0x223)
+ELF_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 0x224)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12, 0x225)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12, 0x226)
+ELF_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 0x227)
+ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12, 0x228)
+ELF_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, 0x229)
+ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12, 0x22a)
+ELF_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, 0x22b)
+ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12, 0x22c)
+ELF_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, 0x22d)
+ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12, 0x22e)
+ELF_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, 0x22f)
+ELF_RELOC(R_AARCH64_TLSDESC_LD_PREL19, 0x230)
+ELF_RELOC(R_AARCH64_TLSDESC_ADR_PREL21, 0x231)
+ELF_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21, 0x232)
+ELF_RELOC(R_AARCH64_TLSDESC_LD64_LO12_NC, 0x233)
+ELF_RELOC(R_AARCH64_TLSDESC_ADD_LO12_NC, 0x234)
+ELF_RELOC(R_AARCH64_TLSDESC_OFF_G1, 0x235)
+ELF_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC, 0x236)
+ELF_RELOC(R_AARCH64_TLSDESC_LDR, 0x237)
+ELF_RELOC(R_AARCH64_TLSDESC_ADD, 0x238)
+ELF_RELOC(R_AARCH64_TLSDESC_CALL, 0x239)
+ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12, 0x23a)
+ELF_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, 0x23b)
+ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, 0x23c)
+ELF_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 0x23d)
+ELF_RELOC(R_AARCH64_COPY, 0x400)
+ELF_RELOC(R_AARCH64_GLOB_DAT, 0x401)
+ELF_RELOC(R_AARCH64_JUMP_SLOT, 0x402)
+ELF_RELOC(R_AARCH64_RELATIVE, 0x403)
+ELF_RELOC(R_AARCH64_TLS_DTPREL64, 0x404)
+ELF_RELOC(R_AARCH64_TLS_DTPMOD64, 0x405)
+ELF_RELOC(R_AARCH64_TLS_TPREL64, 0x406)
+ELF_RELOC(R_AARCH64_TLSDESC, 0x407)
+ELF_RELOC(R_AARCH64_IRELATIVE, 0x408)
+
+// ELF_RELOC(R_AARCH64_P32_NONE, 0)
+ELF_RELOC(R_AARCH64_P32_ABS32, 0x001)
+ELF_RELOC(R_AARCH64_P32_ABS16, 0x002)
+ELF_RELOC(R_AARCH64_P32_PREL32, 0x003)
+ELF_RELOC(R_AARCH64_P32_PREL16, 0x004)
+ELF_RELOC(R_AARCH64_P32_MOVW_UABS_G0, 0x005)
+ELF_RELOC(R_AARCH64_P32_MOVW_UABS_G0_NC, 0x006)
+ELF_RELOC(R_AARCH64_P32_MOVW_UABS_G1, 0x007)
+ELF_RELOC(R_AARCH64_P32_MOVW_SABS_G0, 0x008)
+ELF_RELOC(R_AARCH64_P32_LD_PREL_LO19, 0x009)
+ELF_RELOC(R_AARCH64_P32_ADR_PREL_LO21, 0x00a)
+ELF_RELOC(R_AARCH64_P32_ADR_PREL_PG_HI21, 0x00b)
+ELF_RELOC(R_AARCH64_P32_ADD_ABS_LO12_NC, 0x00c)
+ELF_RELOC(R_AARCH64_P32_LDST8_ABS_LO12_NC, 0x00d)
+ELF_RELOC(R_AARCH64_P32_TSTBR14, 0x012)
+ELF_RELOC(R_AARCH64_P32_CONDBR19, 0x013)
+ELF_RELOC(R_AARCH64_P32_JUMP26, 0x014)
+ELF_RELOC(R_AARCH64_P32_CALL26, 0x015)
+ELF_RELOC(R_AARCH64_P32_LDST16_ABS_LO12_NC, 0x00e)
+ELF_RELOC(R_AARCH64_P32_LDST32_ABS_LO12_NC, 0x00f)
+ELF_RELOC(R_AARCH64_P32_LDST64_ABS_LO12_NC, 0x010)
+ELF_RELOC(R_AARCH64_P32_MOVW_PREL_G0, 0x016)
+ELF_RELOC(R_AARCH64_P32_MOVW_PREL_G0_NC, 0x017)
+ELF_RELOC(R_AARCH64_P32_MOVW_PREL_G1, 0x018)
+ELF_RELOC(R_AARCH64_P32_LDST128_ABS_LO12_NC, 0x011)
+ELF_RELOC(R_AARCH64_P32_GOT_LD_PREL19, 0x019)
+ELF_RELOC(R_AARCH64_P32_ADR_GOT_PAGE, 0x01a)
+ELF_RELOC(R_AARCH64_P32_LD64_GOT_LO12_NC, 0x01b)
+ELF_RELOC(R_AARCH64_P32_LD32_GOTPAGE_LO14, 0x01c)
+ELF_RELOC(R_AARCH64_P32_TLSLD_MOVW_DTPREL_G1, 0x057)
+ELF_RELOC(R_AARCH64_P32_TLSLD_MOVW_DTPREL_G0, 0x058)
+ELF_RELOC(R_AARCH64_P32_TLSLD_MOVW_DTPREL_G0_NC, 0x059)
+ELF_RELOC(R_AARCH64_P32_TLSLD_ADD_DTPREL_HI12, 0x05a)
+ELF_RELOC(R_AARCH64_P32_TLSLD_ADD_DTPREL_LO12, 0x05b)
+ELF_RELOC(R_AARCH64_P32_TLSLD_ADD_DTPREL_LO12_NC, 0x05c)
+ELF_RELOC(R_AARCH64_P32_TLSLD_LDST8_DTPREL_LO12, 0x05d)
+ELF_RELOC(R_AARCH64_P32_TLSLD_LDST8_DTPREL_LO12_NC, 0x05e)
+ELF_RELOC(R_AARCH64_P32_TLSLD_LDST16_DTPREL_LO12, 0x05f)
+ELF_RELOC(R_AARCH64_P32_TLSLD_LDST16_DTPREL_LO12_NC, 0x060)
+ELF_RELOC(R_AARCH64_P32_TLSLD_LDST32_DTPREL_LO12, 0x061)
+ELF_RELOC(R_AARCH64_P32_TLSLD_LDST32_DTPREL_LO12_NC, 0x062)
+ELF_RELOC(R_AARCH64_P32_TLSLD_LDST64_DTPREL_LO12, 0x063)
+ELF_RELOC(R_AARCH64_P32_TLSLD_LDST64_DTPREL_LO12_NC, 0x064)
+ELF_RELOC(R_AARCH64_P32_TLSIE_ADR_GOTTPREL_PAGE21, 0x067)
+ELF_RELOC(R_AARCH64_P32_TLSIE_LD32_GOTTPREL_LO12_NC, 0x068)
+ELF_RELOC(R_AARCH64_P32_TLSIE_LD_GOTTPREL_PREL19, 0x069)
+ELF_RELOC(R_AARCH64_P32_TLSLE_MOVW_TPREL_G1, 0x06a)
+ELF_RELOC(R_AARCH64_P32_TLSLE_MOVW_TPREL_G0, 0x06b)
+ELF_RELOC(R_AARCH64_P32_TLSLE_MOVW_TPREL_G0_NC, 0x06c)
+ELF_RELOC(R_AARCH64_P32_TLSLE_ADD_TPREL_HI12, 0x06d)
+ELF_RELOC(R_AARCH64_P32_TLSLE_ADD_TPREL_LO12, 0x06e)
+ELF_RELOC(R_AARCH64_P32_TLSLE_ADD_TPREL_LO12_NC, 0x06f)
+ELF_RELOC(R_AARCH64_P32_TLSLE_LDST8_TPREL_LO12, 0x070)
+ELF_RELOC(R_AARCH64_P32_TLSLE_LDST8_TPREL_LO12_NC, 0x071)
+ELF_RELOC(R_AARCH64_P32_TLSLE_LDST16_TPREL_LO12, 0x072)
+ELF_RELOC(R_AARCH64_P32_TLSLE_LDST16_TPREL_LO12_NC, 0x073)
+ELF_RELOC(R_AARCH64_P32_TLSLE_LDST32_TPREL_LO12, 0x074)
+ELF_RELOC(R_AARCH64_P32_TLSLE_LDST32_TPREL_LO12_NC, 0x075)
+ELF_RELOC(R_AARCH64_P32_TLSLE_LDST64_TPREL_LO12, 0x076)
+ELF_RELOC(R_AARCH64_P32_TLSLE_LDST64_TPREL_LO12_NC, 0x077)
+ELF_RELOC(R_AARCH64_P32_TLSDESC_ADR_PAGE21, 0x051)
+ELF_RELOC(R_AARCH64_P32_TLSDESC_LD32_LO12_NC, 0x07d)
+ELF_RELOC(R_AARCH64_P32_TLSDESC_ADD_LO12_NC, 0x034)
+ELF_RELOC(R_AARCH64_P32_TLSDESC_CALL, 0x07f)
+ELF_RELOC(R_AARCH64_P32_COPY, 0x0b4)
+ELF_RELOC(R_AARCH64_P32_GLOB_DAT, 0x0b5)
+ELF_RELOC(R_AARCH64_P32_JUMP_SLOT, 0x0b6)
+ELF_RELOC(R_AARCH64_P32_RELATIVE, 0x0b7)
+ELF_RELOC(R_AARCH64_P32_IRELATIVE, 0x0bc)
diff --git a/rts/linker/ELFRelocs/ARM.def b/rts/linker/ELFRelocs/ARM.def
new file mode 100644
index 0000000000..730fc5b883
--- /dev/null
+++ b/rts/linker/ELFRelocs/ARM.def
@@ -0,0 +1,138 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// Meets 2.09 ABI Specs.
+ELF_RELOC(R_ARM_NONE, 0x00)
+ELF_RELOC(R_ARM_PC24, 0x01)
+ELF_RELOC(R_ARM_ABS32, 0x02)
+ELF_RELOC(R_ARM_REL32, 0x03)
+ELF_RELOC(R_ARM_LDR_PC_G0, 0x04)
+ELF_RELOC(R_ARM_ABS16, 0x05)
+ELF_RELOC(R_ARM_ABS12, 0x06)
+ELF_RELOC(R_ARM_THM_ABS5, 0x07)
+ELF_RELOC(R_ARM_ABS8, 0x08)
+ELF_RELOC(R_ARM_SBREL32, 0x09)
+ELF_RELOC(R_ARM_THM_CALL, 0x0a)
+ELF_RELOC(R_ARM_THM_PC8, 0x0b)
+ELF_RELOC(R_ARM_BREL_ADJ, 0x0c)
+ELF_RELOC(R_ARM_TLS_DESC, 0x0d)
+ELF_RELOC(R_ARM_THM_SWI8, 0x0e)
+ELF_RELOC(R_ARM_XPC25, 0x0f)
+ELF_RELOC(R_ARM_THM_XPC22, 0x10)
+ELF_RELOC(R_ARM_TLS_DTPMOD32, 0x11)
+ELF_RELOC(R_ARM_TLS_DTPOFF32, 0x12)
+ELF_RELOC(R_ARM_TLS_TPOFF32, 0x13)
+ELF_RELOC(R_ARM_COPY, 0x14)
+ELF_RELOC(R_ARM_GLOB_DAT, 0x15)
+ELF_RELOC(R_ARM_JUMP_SLOT, 0x16)
+ELF_RELOC(R_ARM_RELATIVE, 0x17)
+ELF_RELOC(R_ARM_GOTOFF32, 0x18)
+ELF_RELOC(R_ARM_BASE_PREL, 0x19)
+ELF_RELOC(R_ARM_GOT_BREL, 0x1a)
+ELF_RELOC(R_ARM_PLT32, 0x1b)
+ELF_RELOC(R_ARM_CALL, 0x1c)
+ELF_RELOC(R_ARM_JUMP24, 0x1d)
+ELF_RELOC(R_ARM_THM_JUMP24, 0x1e)
+ELF_RELOC(R_ARM_BASE_ABS, 0x1f)
+ELF_RELOC(R_ARM_ALU_PCREL_7_0, 0x20)
+ELF_RELOC(R_ARM_ALU_PCREL_15_8, 0x21)
+ELF_RELOC(R_ARM_ALU_PCREL_23_15, 0x22)
+ELF_RELOC(R_ARM_LDR_SBREL_11_0_NC, 0x23)
+ELF_RELOC(R_ARM_ALU_SBREL_19_12_NC, 0x24)
+ELF_RELOC(R_ARM_ALU_SBREL_27_20_CK, 0x25)
+ELF_RELOC(R_ARM_TARGET1, 0x26)
+ELF_RELOC(R_ARM_SBREL31, 0x27)
+ELF_RELOC(R_ARM_V4BX, 0x28)
+ELF_RELOC(R_ARM_TARGET2, 0x29)
+ELF_RELOC(R_ARM_PREL31, 0x2a)
+ELF_RELOC(R_ARM_MOVW_ABS_NC, 0x2b)
+ELF_RELOC(R_ARM_MOVT_ABS, 0x2c)
+ELF_RELOC(R_ARM_MOVW_PREL_NC, 0x2d)
+ELF_RELOC(R_ARM_MOVT_PREL, 0x2e)
+ELF_RELOC(R_ARM_THM_MOVW_ABS_NC, 0x2f)
+ELF_RELOC(R_ARM_THM_MOVT_ABS, 0x30)
+ELF_RELOC(R_ARM_THM_MOVW_PREL_NC, 0x31)
+ELF_RELOC(R_ARM_THM_MOVT_PREL, 0x32)
+ELF_RELOC(R_ARM_THM_JUMP19, 0x33)
+ELF_RELOC(R_ARM_THM_JUMP6, 0x34)
+ELF_RELOC(R_ARM_THM_ALU_PREL_11_0, 0x35)
+ELF_RELOC(R_ARM_THM_PC12, 0x36)
+ELF_RELOC(R_ARM_ABS32_NOI, 0x37)
+ELF_RELOC(R_ARM_REL32_NOI, 0x38)
+ELF_RELOC(R_ARM_ALU_PC_G0_NC, 0x39)
+ELF_RELOC(R_ARM_ALU_PC_G0, 0x3a)
+ELF_RELOC(R_ARM_ALU_PC_G1_NC, 0x3b)
+ELF_RELOC(R_ARM_ALU_PC_G1, 0x3c)
+ELF_RELOC(R_ARM_ALU_PC_G2, 0x3d)
+ELF_RELOC(R_ARM_LDR_PC_G1, 0x3e)
+ELF_RELOC(R_ARM_LDR_PC_G2, 0x3f)
+ELF_RELOC(R_ARM_LDRS_PC_G0, 0x40)
+ELF_RELOC(R_ARM_LDRS_PC_G1, 0x41)
+ELF_RELOC(R_ARM_LDRS_PC_G2, 0x42)
+ELF_RELOC(R_ARM_LDC_PC_G0, 0x43)
+ELF_RELOC(R_ARM_LDC_PC_G1, 0x44)
+ELF_RELOC(R_ARM_LDC_PC_G2, 0x45)
+ELF_RELOC(R_ARM_ALU_SB_G0_NC, 0x46)
+ELF_RELOC(R_ARM_ALU_SB_G0, 0x47)
+ELF_RELOC(R_ARM_ALU_SB_G1_NC, 0x48)
+ELF_RELOC(R_ARM_ALU_SB_G1, 0x49)
+ELF_RELOC(R_ARM_ALU_SB_G2, 0x4a)
+ELF_RELOC(R_ARM_LDR_SB_G0, 0x4b)
+ELF_RELOC(R_ARM_LDR_SB_G1, 0x4c)
+ELF_RELOC(R_ARM_LDR_SB_G2, 0x4d)
+ELF_RELOC(R_ARM_LDRS_SB_G0, 0x4e)
+ELF_RELOC(R_ARM_LDRS_SB_G1, 0x4f)
+ELF_RELOC(R_ARM_LDRS_SB_G2, 0x50)
+ELF_RELOC(R_ARM_LDC_SB_G0, 0x51)
+ELF_RELOC(R_ARM_LDC_SB_G1, 0x52)
+ELF_RELOC(R_ARM_LDC_SB_G2, 0x53)
+ELF_RELOC(R_ARM_MOVW_BREL_NC, 0x54)
+ELF_RELOC(R_ARM_MOVT_BREL, 0x55)
+ELF_RELOC(R_ARM_MOVW_BREL, 0x56)
+ELF_RELOC(R_ARM_THM_MOVW_BREL_NC, 0x57)
+ELF_RELOC(R_ARM_THM_MOVT_BREL, 0x58)
+ELF_RELOC(R_ARM_THM_MOVW_BREL, 0x59)
+ELF_RELOC(R_ARM_TLS_GOTDESC, 0x5a)
+ELF_RELOC(R_ARM_TLS_CALL, 0x5b)
+ELF_RELOC(R_ARM_TLS_DESCSEQ, 0x5c)
+ELF_RELOC(R_ARM_THM_TLS_CALL, 0x5d)
+ELF_RELOC(R_ARM_PLT32_ABS, 0x5e)
+ELF_RELOC(R_ARM_GOT_ABS, 0x5f)
+ELF_RELOC(R_ARM_GOT_PREL, 0x60)
+ELF_RELOC(R_ARM_GOT_BREL12, 0x61)
+ELF_RELOC(R_ARM_GOTOFF12, 0x62)
+ELF_RELOC(R_ARM_GOTRELAX, 0x63)
+ELF_RELOC(R_ARM_GNU_VTENTRY, 0x64)
+ELF_RELOC(R_ARM_GNU_VTINHERIT, 0x65)
+ELF_RELOC(R_ARM_THM_JUMP11, 0x66)
+ELF_RELOC(R_ARM_THM_JUMP8, 0x67)
+ELF_RELOC(R_ARM_TLS_GD32, 0x68)
+ELF_RELOC(R_ARM_TLS_LDM32, 0x69)
+ELF_RELOC(R_ARM_TLS_LDO32, 0x6a)
+ELF_RELOC(R_ARM_TLS_IE32, 0x6b)
+ELF_RELOC(R_ARM_TLS_LE32, 0x6c)
+ELF_RELOC(R_ARM_TLS_LDO12, 0x6d)
+ELF_RELOC(R_ARM_TLS_LE12, 0x6e)
+ELF_RELOC(R_ARM_TLS_IE12GP, 0x6f)
+ELF_RELOC(R_ARM_PRIVATE_0, 0x70)
+ELF_RELOC(R_ARM_PRIVATE_1, 0x71)
+ELF_RELOC(R_ARM_PRIVATE_2, 0x72)
+ELF_RELOC(R_ARM_PRIVATE_3, 0x73)
+ELF_RELOC(R_ARM_PRIVATE_4, 0x74)
+ELF_RELOC(R_ARM_PRIVATE_5, 0x75)
+ELF_RELOC(R_ARM_PRIVATE_6, 0x76)
+ELF_RELOC(R_ARM_PRIVATE_7, 0x77)
+ELF_RELOC(R_ARM_PRIVATE_8, 0x78)
+ELF_RELOC(R_ARM_PRIVATE_9, 0x79)
+ELF_RELOC(R_ARM_PRIVATE_10, 0x7a)
+ELF_RELOC(R_ARM_PRIVATE_11, 0x7b)
+ELF_RELOC(R_ARM_PRIVATE_12, 0x7c)
+ELF_RELOC(R_ARM_PRIVATE_13, 0x7d)
+ELF_RELOC(R_ARM_PRIVATE_14, 0x7e)
+ELF_RELOC(R_ARM_PRIVATE_15, 0x7f)
+ELF_RELOC(R_ARM_ME_TOO, 0x80)
+ELF_RELOC(R_ARM_THM_TLS_DESCSEQ16, 0x81)
+ELF_RELOC(R_ARM_THM_TLS_DESCSEQ32, 0x82)
+ELF_RELOC(R_ARM_IRELATIVE, 0xa0)
diff --git a/rts/linker/ELFRelocs/LICENSE-LLVM.TXT b/rts/linker/ELFRelocs/LICENSE-LLVM.TXT
new file mode 100644
index 0000000000..ff63f2b6aa
--- /dev/null
+++ b/rts/linker/ELFRelocs/LICENSE-LLVM.TXT
@@ -0,0 +1,68 @@
+==============================================================================
+LLVM Release License
+==============================================================================
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2003-2017 University of Illinois at Urbana-Champaign.
+All rights reserved.
+
+Developed by:
+
+ LLVM Team
+
+ University of Illinois at Urbana-Champaign
+
+ http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
+SOFTWARE.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The LLVM software contains code written by third parties. Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
+The following pieces of software have additional or alternate copyrights,
+licenses, and/or restrictions:
+
+Program Directory
+------- ---------
+Google Test llvm/utils/unittest/googletest
+OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}
+pyyaml tests llvm/test/YAMLParser/{*.data, LICENSE.TXT}
+ARM contributions llvm/lib/Target/ARM/LICENSE.TXT
+md5 contributions llvm/lib/Support/MD5.cpp llvm/include/llvm/Support/MD5.h
diff --git a/rts/linker/ELFRelocs/i386.def b/rts/linker/ELFRelocs/i386.def
new file mode 100644
index 0000000000..1d28cf595c
--- /dev/null
+++ b/rts/linker/ELFRelocs/i386.def
@@ -0,0 +1,47 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+// TODO: this is just a subset
+ELF_RELOC(R_386_NONE, 0)
+ELF_RELOC(R_386_32, 1)
+ELF_RELOC(R_386_PC32, 2)
+ELF_RELOC(R_386_GOT32, 3)
+ELF_RELOC(R_386_PLT32, 4)
+ELF_RELOC(R_386_COPY, 5)
+ELF_RELOC(R_386_GLOB_DAT, 6)
+ELF_RELOC(R_386_JUMP_SLOT, 7)
+ELF_RELOC(R_386_RELATIVE, 8)
+ELF_RELOC(R_386_GOTOFF, 9)
+ELF_RELOC(R_386_GOTPC, 10)
+ELF_RELOC(R_386_32PLT, 11)
+ELF_RELOC(R_386_TLS_TPOFF, 14)
+ELF_RELOC(R_386_TLS_IE, 15)
+ELF_RELOC(R_386_TLS_GOTIE, 16)
+ELF_RELOC(R_386_TLS_LE, 17)
+ELF_RELOC(R_386_TLS_GD, 18)
+ELF_RELOC(R_386_TLS_LDM, 19)
+ELF_RELOC(R_386_16, 20)
+ELF_RELOC(R_386_PC16, 21)
+ELF_RELOC(R_386_8, 22)
+ELF_RELOC(R_386_PC8, 23)
+ELF_RELOC(R_386_TLS_GD_32, 24)
+ELF_RELOC(R_386_TLS_GD_PUSH, 25)
+ELF_RELOC(R_386_TLS_GD_CALL, 26)
+ELF_RELOC(R_386_TLS_GD_POP, 27)
+ELF_RELOC(R_386_TLS_LDM_32, 28)
+ELF_RELOC(R_386_TLS_LDM_PUSH, 29)
+ELF_RELOC(R_386_TLS_LDM_CALL, 30)
+ELF_RELOC(R_386_TLS_LDM_POP, 31)
+ELF_RELOC(R_386_TLS_LDO_32, 32)
+ELF_RELOC(R_386_TLS_IE_32, 33)
+ELF_RELOC(R_386_TLS_LE_32, 34)
+ELF_RELOC(R_386_TLS_DTPMOD32, 35)
+ELF_RELOC(R_386_TLS_DTPOFF32, 36)
+ELF_RELOC(R_386_TLS_TPOFF32, 37)
+ELF_RELOC(R_386_TLS_GOTDESC, 39)
+ELF_RELOC(R_386_TLS_DESC_CALL, 40)
+ELF_RELOC(R_386_TLS_DESC, 41)
+ELF_RELOC(R_386_IRELATIVE, 42)
+ELF_RELOC(R_386_GOT32X, 43)
diff --git a/rts/linker/ELFRelocs/x86_64.def b/rts/linker/ELFRelocs/x86_64.def
new file mode 100644
index 0000000000..18fdcf9472
--- /dev/null
+++ b/rts/linker/ELFRelocs/x86_64.def
@@ -0,0 +1,45 @@
+
+#ifndef ELF_RELOC
+#error "ELF_RELOC must be defined"
+#endif
+
+ELF_RELOC(R_X86_64_NONE, 0)
+ELF_RELOC(R_X86_64_64, 1)
+ELF_RELOC(R_X86_64_PC32, 2)
+ELF_RELOC(R_X86_64_GOT32, 3)
+ELF_RELOC(R_X86_64_PLT32, 4)
+ELF_RELOC(R_X86_64_COPY, 5)
+ELF_RELOC(R_X86_64_GLOB_DAT, 6)
+ELF_RELOC(R_X86_64_JUMP_SLOT, 7)
+ELF_RELOC(R_X86_64_RELATIVE, 8)
+ELF_RELOC(R_X86_64_GOTPCREL, 9)
+ELF_RELOC(R_X86_64_32, 10)
+ELF_RELOC(R_X86_64_32S, 11)
+ELF_RELOC(R_X86_64_16, 12)
+ELF_RELOC(R_X86_64_PC16, 13)
+ELF_RELOC(R_X86_64_8, 14)
+ELF_RELOC(R_X86_64_PC8, 15)
+ELF_RELOC(R_X86_64_DTPMOD64, 16)
+ELF_RELOC(R_X86_64_DTPOFF64, 17)
+ELF_RELOC(R_X86_64_TPOFF64, 18)
+ELF_RELOC(R_X86_64_TLSGD, 19)
+ELF_RELOC(R_X86_64_TLSLD, 20)
+ELF_RELOC(R_X86_64_DTPOFF32, 21)
+ELF_RELOC(R_X86_64_GOTTPOFF, 22)
+ELF_RELOC(R_X86_64_TPOFF32, 23)
+ELF_RELOC(R_X86_64_PC64, 24)
+ELF_RELOC(R_X86_64_GOTOFF64, 25)
+ELF_RELOC(R_X86_64_GOTPC32, 26)
+ELF_RELOC(R_X86_64_GOT64, 27)
+ELF_RELOC(R_X86_64_GOTPCREL64, 28)
+ELF_RELOC(R_X86_64_GOTPC64, 29)
+ELF_RELOC(R_X86_64_GOTPLT64, 30)
+ELF_RELOC(R_X86_64_PLTOFF64, 31)
+ELF_RELOC(R_X86_64_SIZE32, 32)
+ELF_RELOC(R_X86_64_SIZE64, 33)
+ELF_RELOC(R_X86_64_GOTPC32_TLSDESC, 34)
+ELF_RELOC(R_X86_64_TLSDESC_CALL, 35)
+ELF_RELOC(R_X86_64_TLSDESC, 36)
+ELF_RELOC(R_X86_64_IRELATIVE, 37)
+ELF_RELOC(R_X86_64_GOTPCRELX, 41)
+ELF_RELOC(R_X86_64_REX_GOTPCRELX, 42)
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index 5b67548a1b..9d60b393a0 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -6,6 +6,13 @@
|| defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) \
|| defined(openbsd_HOST_OS) || defined(gnu_HOST_OS)
+// It is essential that this is included before any <elf.h> is included. <elf.h>
+// defines R_XXX relocations, which would interfere with the COMPAT_R_XXX
+// relocations we generate. E.g. COMPAT_ ## R_ARM_ARM32 would end up as
+// const unsigned COMPAT_3 = 0x03; instead of
+// const unsigned COMPAT_R_ARM_ARM32 = 0x03;
+#include "elf_compat.h"
+
#include "RtsUtils.h"
#include "RtsSymbolInfo.h"
#include "linker/Elf.h"
@@ -14,6 +21,8 @@
#include "linker/SymbolExtras.h"
#include "sm/OSMem.h"
#include "GetEnv.h"
+#include "linker/util.h"
+#include "linker/elf_util.h"
#include <stdlib.h>
#include <string.h>
@@ -81,56 +90,8 @@
#else
/* openbsd elf has things in different places, with diff names */
# include <elf_abi.h>
-# include <machine/reloc.h>
-# define R_386_32 RELOC_32
-# define R_386_PC32 RELOC_PC32
#endif
-/* If elf.h doesn't define it */
-# ifndef R_X86_64_PC64
-# define R_X86_64_PC64 24
-# endif
-
-/*
- * Workaround for libc implementations (e.g. eglibc) with incomplete
- * relocation lists
- */
-#ifndef R_ARM_THM_CALL
-# define R_ARM_THM_CALL 10
-#endif
-#ifndef R_ARM_CALL
-# define R_ARM_CALL 28
-#endif
-#ifndef R_ARM_JUMP24
-# define R_ARM_JUMP24 29
-#endif
-#ifndef R_ARM_THM_JUMP24
-# define R_ARM_THM_JUMP24 30
-#endif
-#ifndef R_ARM_TARGET1
-# define R_ARM_TARGET1 38
-#endif
-#ifndef R_ARM_MOVW_ABS_NC
-# define R_ARM_MOVW_ABS_NC 43
-#endif
-#ifndef R_ARM_MOVT_ABS
-# define R_ARM_MOVT_ABS 44
-#endif
-#ifndef R_ARM_THM_MOVW_ABS_NC
-# define R_ARM_THM_MOVW_ABS_NC 47
-#endif
-#ifndef R_ARM_THM_MOVT_ABS
-# define R_ARM_THM_MOVT_ABS 48
-#endif
-#ifndef R_ARM_THM_JUMP11
-# define R_ARM_THM_JUMP11 102
-#endif
-#ifndef R_ARM_THM_JUMP8
-# define R_ARM_THM_JUMP8 103
-#endif
-
-
-
/*
Note [Many ELF Sections]
@@ -164,9 +125,9 @@ static Elf_Word elf_shnum(Elf_Ehdr* ehdr)
static Elf_Word elf_shstrndx(Elf_Ehdr* ehdr)
{
- Elf_Shdr* shdr = (Elf_Shdr*) ((char*)ehdr + ehdr->e_shoff);
Elf_Half shstrndx = ehdr->e_shstrndx;
#if defined(SHN_XINDEX)
+ Elf_Shdr* shdr = (Elf_Shdr*) ((char*)ehdr + ehdr->e_shoff);
return shstrndx != SHN_XINDEX ? shstrndx : shdr[0].sh_link;
#else
// some OSes do not support SHN_XINDEX yet, let's revert to
@@ -742,21 +703,6 @@ end:
return result;
}
-#if defined(arm_HOST_ARCH)
-// TODO: These likely belong in a library somewhere
-
-// Signed extend a number to a 32-bit int.
-static inline StgInt32 sign_extend32(uint32_t bits, StgWord32 x) {
- return ((StgInt32) (x << (32 - bits))) >> (32 - bits);
-}
-
-// Does the given signed integer fit into the given bit width?
-static inline StgBool is_int(uint32_t bits, StgInt32 x) {
- return bits > 32 || (-(1 << (bits-1)) <= x
- && x < (1 << (bits-1)));
-}
-#endif
-
/* Do ELF relocations which lack an explicit addend. All x86-linux
and arm-linux relocations appear to be of this form. */
static int
@@ -886,25 +832,26 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
switch (reloc_type) {
# ifdef i386_HOST_ARCH
- case R_386_32: *pP = value; break;
- case R_386_PC32: *pP = value - P; break;
+ case COMPAT_R_386_32: *pP = value; break;
+ case COMPAT_R_386_PC32: *pP = value - P; break;
# endif
# ifdef arm_HOST_ARCH
- case R_ARM_ABS32:
- case R_ARM_TARGET1: // Specified by Linux ARM ABI to be equivalent to ABS32
+ case COMPAT_R_ARM_ABS32:
+ // Specified by Linux ARM ABI to be equivalent to ABS32
+ case COMPAT_R_ARM_TARGET1:
*(Elf32_Word *)P += S;
*(Elf32_Word *)P |= T;
break;
- case R_ARM_REL32:
+ case COMPAT_R_ARM_REL32:
*(Elf32_Word *)P += S;
*(Elf32_Word *)P |= T;
*(Elf32_Word *)P -= P;
break;
- case R_ARM_CALL:
- case R_ARM_JUMP24:
+ case COMPAT_R_ARM_CALL:
+ case COMPAT_R_ARM_JUMP24:
{
// N.B. LLVM's LLD linker's relocation implement is a fantastic
// resource
@@ -923,30 +870,36 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
StgWord32 result = ((S + imm) | T) - P;
const StgBool overflow = !is_int(26, (StgInt32) result);
-
// Handle overflow and Thumb interworking
- const StgBool needs_veneer = (is_target_thm && ELF_R_TYPE(info) == R_ARM_JUMP24) || overflow;
+ const StgBool needs_veneer =
+ (is_target_thm && ELF_R_TYPE(info) == COMPAT_R_ARM_JUMP24)
+ || overflow;
+
if (needs_veneer) {
// Generate veneer
- // The +8 below is to undo the PC-bias compensation done by the object producer
- SymbolExtra *extra = makeArmSymbolExtra(oc, ELF_R_SYM(info), S+imm+8, 0, is_target_thm);
+ // The +8 below is to undo the PC-bias compensation done by the
+ // object producer
+ SymbolExtra *extra = makeArmSymbolExtra(oc, ELF_R_SYM(info),
+ S+imm+8, 0,
+ is_target_thm);
// The -8 below is to compensate for PC bias
result = (StgWord32) ((StgInt32) extra->jumpIsland - P - 8);
result &= ~1; // Clear thumb indicator bit
if (!is_int(26, (StgInt32) result)) {
- errorBelch("Unable to fixup overflow'd R_ARM_CALL: jump island=%p, reloc=%p\n",
+ errorBelch("Unable to fixup overflow'd R_ARM_CALL: "
+ "jump island=%p, reloc=%p\n",
(void*) extra->jumpIsland, (void*) P);
return 0;
}
}
-
// Update the branch target
const StgWord32 imm24 = (result & 0x03fffffc) >> 2;
*word = (*word & ~0x00ffffff)
| (imm24 & 0x00ffffff);
// Change the relocated branch into a BLX if necessary
- const StgBool switch_mode = is_target_thm && (reloc_type == R_ARM_CALL);
+ const StgBool switch_mode =
+ is_target_thm && (reloc_type == COMPAT_R_ARM_CALL);
if (!needs_veneer && switch_mode) {
const StgWord32 hBit = (result & 0x2) >> 1;
// Change instruction to BLX
@@ -956,8 +909,8 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
break;
}
- case R_ARM_MOVT_ABS:
- case R_ARM_MOVW_ABS_NC:
+ case COMPAT_R_ARM_MOVT_ABS:
+ case COMPAT_R_ARM_MOVW_ABS_NC:
{
StgWord32 *word = (StgWord32 *)P;
StgWord32 imm12 = *word & 0xfff;
@@ -965,7 +918,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
StgInt32 offset = imm4 << 12 | imm12;
StgWord32 result = (S + offset) | T;
- if (reloc_type == R_ARM_MOVT_ABS)
+ if (reloc_type == COMPAT_R_ARM_MOVT_ABS)
result = (result & 0xffff0000) >> 16;
StgWord32 result12 = result & 0xfff;
@@ -974,8 +927,8 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
break;
}
- case R_ARM_THM_CALL:
- case R_ARM_THM_JUMP24:
+ case COMPAT_R_ARM_THM_CALL:
+ case COMPAT_R_ARM_THM_JUMP24:
{
StgWord16 *upper = (StgWord16 *)P;
StgWord16 *lower = (StgWord16 *)(P + 2);
@@ -999,15 +952,20 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
imm -= 0x02000000;
offset = ((imm + S) | T) - P;
- overflow = offset <= (StgWord32)0xff000000 || offset >= (StgWord32)0x01000000;
+ overflow = offset <= (StgWord32)0xff000000
+ || offset >= (StgWord32)0x01000000;
- if ((!is_target_thm && ELF_R_TYPE(info) == R_ARM_THM_JUMP24) || overflow) {
+ if ((!is_target_thm && ELF_R_TYPE(info) == COMPAT_R_ARM_THM_JUMP24)
+ || overflow) {
// Generate veneer
- SymbolExtra *extra = makeArmSymbolExtra(oc, ELF_R_SYM(info), S+imm+4, 1, is_target_thm);
+ SymbolExtra *extra = makeArmSymbolExtra(oc, ELF_R_SYM(info),
+ S+imm+4, 1,
+ is_target_thm);
offset = (StgWord32) &extra->jumpIsland - P - 4;
sign = offset >> 31;
to_thm = 1;
- } else if (!is_target_thm && ELF_R_TYPE(info) == R_ARM_THM_CALL) {
+ } else if (!is_target_thm
+ && ELF_R_TYPE(info) == COMPAT_R_ARM_THM_CALL) {
offset &= ~0x3;
to_thm = 0;
}
@@ -1026,8 +984,8 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
break;
}
- case R_ARM_THM_MOVT_ABS:
- case R_ARM_THM_MOVW_ABS_NC:
+ case COMPAT_R_ARM_THM_MOVT_ABS:
+ case COMPAT_R_ARM_THM_MOVW_ABS_NC:
{
StgWord16 *upper = (StgWord16 *)P;
StgWord16 *lower = (StgWord16 *)(P + 2);
@@ -1038,9 +996,9 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
offset = (offset ^ 0x8000) - 0x8000; // Sign extend
offset += S;
- if (ELF_R_TYPE(info) == R_ARM_THM_MOVW_ABS_NC)
+ if (ELF_R_TYPE(info) == COMPAT_R_ARM_THM_MOVW_ABS_NC)
offset |= T;
- else if (ELF_R_TYPE(info) == R_ARM_THM_MOVT_ABS)
+ else if (ELF_R_TYPE(info) == COMPAT_R_ARM_THM_MOVT_ABS)
offset >>= 16;
*upper = ( (*upper & 0xfbf0)
@@ -1052,13 +1010,14 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
break;
}
- case R_ARM_THM_JUMP8:
+ case COMPAT_R_ARM_THM_JUMP8:
{
StgWord16 *word = (StgWord16 *)P;
StgWord offset = *word & 0x01fe;
offset += S - P;
if (!is_target_thm) {
- errorBelch("%s: Thumb to ARM transition with JUMP8 relocation not supported\n",
+ errorBelch("%s: Thumb to ARM transition with JUMP8 relocation "
+ "not supported\n",
oc->fileName);
return 0;
}
@@ -1068,13 +1027,14 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
break;
}
- case R_ARM_THM_JUMP11:
+ case COMPAT_R_ARM_THM_JUMP11:
{
StgWord16 *word = (StgWord16 *)P;
StgWord offset = *word & 0x0ffe;
offset += S - P;
if (!is_target_thm) {
- errorBelch("%s: Thumb to ARM transition with JUMP11 relocation not supported\n",
+ errorBelch("%s: Thumb to ARM transition with JUMP11 relocation "
+ "not supported\n",
oc->fileName);
return 0;
}
@@ -1303,11 +1263,11 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
# endif
#if defined(x86_64_HOST_ARCH)
- case R_X86_64_64:
+ case COMPAT_R_X86_64_64:
*(Elf64_Xword *)P = value;
break;
- case R_X86_64_PC32:
+ case COMPAT_R_X86_64_PC32:
{
#if defined(ALWAYS_PIC)
barf("R_X86_64_PC32 relocation, but ALWAYS_PIC.");
@@ -1331,14 +1291,14 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
break;
}
- case R_X86_64_PC64:
+ case COMPAT_R_X86_64_PC64:
{
StgInt64 off = value - P;
*(Elf64_Word *)P = (Elf64_Word)off;
break;
}
- case R_X86_64_32:
+ case COMPAT_R_X86_64_32:
#if defined(ALWAYS_PIC)
barf("R_X86_64_32 relocation, but ALWAYS_PIC.");
#else
@@ -1359,7 +1319,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
#endif
break;
- case R_X86_64_32S:
+ case COMPAT_R_X86_64_32S:
#if defined(ALWAYS_PIC)
barf("R_X86_64_32S relocation, but ALWAYS_PIC.");
#else
@@ -1379,14 +1339,9 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
*(Elf64_Sword *)P = (Elf64_Sword)value;
#endif
break;
-/* These two relocations were introduced in glibc 2.23 and binutils 2.26.
- But in order to use them the system which compiles the bindist for GHC needs
- to have glibc >= 2.23. So only use them if they're defined. */
-#if defined(R_X86_64_REX_GOTPCRELX) && defined(R_X86_64_GOTPCRELX)
- case R_X86_64_REX_GOTPCRELX:
- case R_X86_64_GOTPCRELX:
-#endif
- case R_X86_64_GOTPCREL:
+ case COMPAT_R_X86_64_REX_GOTPCRELX:
+ case COMPAT_R_X86_64_GOTPCRELX:
+ case COMPAT_R_X86_64_GOTPCREL:
{
StgInt64 gotAddress = (StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S)->addr;
StgInt64 off = gotAddress + A - P;
@@ -1394,7 +1349,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
break;
}
#if defined(dragonfly_HOST_OS)
- case R_X86_64_GOTTPOFF:
+ case COMPAT_R_X86_64_GOTTPOFF:
{
#if defined(ALWAYS_PIC)
barf("R_X86_64_GOTTPOFF relocation, but ALWAYS_PIC.");
@@ -1413,9 +1368,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
}
#endif
-
-
- case R_X86_64_PLT32:
+ case COMPAT_R_X86_64_PLT32:
{
#if defined(ALWAYS_PIC)
barf("R_X86_64_PLT32 relocation, but ALWAYS_PIC.");
diff --git a/rts/linker/elf_compat.h b/rts/linker/elf_compat.h
new file mode 100644
index 0000000000..c42f1f8949
--- /dev/null
+++ b/rts/linker/elf_compat.h
@@ -0,0 +1,35 @@
+// This file contains relocations, for various
+// architectures for the ELF format. We include
+// to not have to depend on the (limited set of)
+// relocations provided by the system header.
+//
+// The files in ELFRelocs/ have been taken from
+// the LLVM project. See ELFRelocs/LICENSE-LLVM.TXT
+// for the University of Illinois Open Source License
+// under which it is distrubuted.
+//
+
+#ifndef RTS_ELF_COMPAT_H
+#define RTS_ELF_COMPAT_H
+
+#define PASTE(x,y) x ## y
+#define EVAL(x,y) PASTE(x,y)
+
+// generate COMPAT_R_<ARCH>_<REL> relocations to
+// prevent clashes with definitions in <elf.h>.
+#define ELF_RELOC(name, value) PASTE(COMPAT_,name) = value,
+
+enum RelocAarch64 {
+#include "ELFRelocs/AArch64.def"
+};
+enum RelocARM {
+#include "ELFRelocs/ARM.def"
+};
+enum Reloci386 {
+#include "ELFRelocs/i386.def"
+};
+enum RelocX86_64 {
+#include "ELFRelocs/x86_64.def"
+};
+
+#endif //RTS_ELF_COMPAT_H
diff --git a/rts/linker/elf_util.c b/rts/linker/elf_util.c
new file mode 100644
index 0000000000..bdfab22ace
--- /dev/null
+++ b/rts/linker/elf_util.c
@@ -0,0 +1,24 @@
+#include "linker/elf_util.h"
+#include "ElfTypes.h"
+
+#if defined(OBJFORMAT_ELF)
+
+ElfSymbolTable *
+find_symbol_table(ObjectCode * oc, unsigned symolTableIndex) {
+ for(ElfSymbolTable * t=oc->info->symbolTables; t != NULL; t = t->next)
+ if(t->index == symolTableIndex)
+ return t;
+ return NULL;
+}
+
+ElfSymbol *
+find_symbol(ObjectCode * oc, unsigned symbolTableIndex, unsigned long
+symbolIndex) {
+ ElfSymbolTable * t = find_symbol_table(oc, symbolTableIndex);
+ if(NULL != t && symbolIndex < t->n_symbols) {
+ return &t->symbols[symbolIndex];
+ }
+ return NULL;
+}
+
+#endif
diff --git a/rts/linker/elf_util.h b/rts/linker/elf_util.h
new file mode 100644
index 0000000000..cae84a906a
--- /dev/null
+++ b/rts/linker/elf_util.h
@@ -0,0 +1,18 @@
+#ifndef RTS_LINKER_ELF_UTIL_H
+#define RTS_LINKER_ELF_UTIL_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "LinkerInternals.h"
+
+#if defined(OBJFORMAT_ELF)
+
+ElfSymbolTable * find_symbol_table(ObjectCode * oc,
+ unsigned symbolTableIndex);
+
+ElfSymbol * find_symbol(ObjectCode * oc,
+ unsigned symbolTableIndex,
+ unsigned long symbolIndex);
+
+#endif
+#endif //RTS_LINKER_ELF_UTIL_H
diff --git a/rts/linker/util.h b/rts/linker/util.h
new file mode 100644
index 0000000000..650e7f443a
--- /dev/null
+++ b/rts/linker/util.h
@@ -0,0 +1,30 @@
+#ifndef RTS_LINKER_UTIL_H
+#define RTS_LINKER_UTIL_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "LinkerInternals.h"
+
+// Signed extend a number to a 32-bit int.
+// Does the given signed integer fit into the given bit width?
+static inline int32_t
+sign_extend32(uint32_t bits, uint32_t x)
+{
+ return ((int32_t) (x << (32 - bits))) >> (32 - bits);
+}
+
+// Does the given signed integer fit into the given bit width?
+static inline bool
+is_int(uint32_t bits, int32_t x)
+{
+ return bits > 32 || (-(1 << (bits-1)) <= x
+ && x < (1 << (bits-1)));
+}
+
+static inline bool
+is_int64(uint32_t bits, int64_t x) {
+ return bits > 64 || (-((int64_t)1 << (bits-1)) <= x
+ && x < ((int64_t)1 << (bits-1)));
+}
+
+#endif //RTS_LINKER_UTIL_H