diff options
-rw-r--r-- | rts/linker/ELFRelocs/AArch64.def | 201 | ||||
-rw-r--r-- | rts/linker/ELFRelocs/ARM.def | 138 | ||||
-rw-r--r-- | rts/linker/ELFRelocs/LICENSE-LLVM.TXT | 68 | ||||
-rw-r--r-- | rts/linker/ELFRelocs/i386.def | 47 | ||||
-rw-r--r-- | rts/linker/ELFRelocs/x86_64.def | 45 | ||||
-rw-r--r-- | rts/linker/Elf.c | 177 | ||||
-rw-r--r-- | rts/linker/elf_compat.h | 35 | ||||
-rw-r--r-- | rts/linker/elf_util.c | 24 | ||||
-rw-r--r-- | rts/linker/elf_util.h | 18 | ||||
-rw-r--r-- | rts/linker/util.h | 30 |
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 |