X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=bfd%2Felfxx-aarch64.c;h=6c61ec63de824bb1172e5c8950c0d8af7e8a1052;hb=aebcde5eb475befba571ca9ae7b6c58126d41160;hp=35f3e229f54707ac47bac54fadb7da4b95b42559;hpb=e09ab7ac788fd5509adc40b86a3631a3028c1d33;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfxx-aarch64.c b/bfd/elfxx-aarch64.c index 35f3e229f5..6c61ec63de 100644 --- a/bfd/elfxx-aarch64.c +++ b/bfd/elfxx-aarch64.c @@ -1,5 +1,5 @@ /* AArch64-specific support for ELF. - Copyright (C) 2009-2015 Free Software Foundation, Inc. + Copyright (C) 2009-2017 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of BFD, the Binary File Descriptor library. @@ -25,46 +25,24 @@ #define MASK(n) ((1u << (n)) - 1) -/* Decode the 26-bit offset of unconditional branch. */ -static inline uint32_t -decode_branch_ofs_26 (uint32_t insn) -{ - return insn & MASK (26); -} +/* Sign-extend VALUE, which has the indicated number of BITS. */ -/* Decode the 19-bit offset of conditional branch and compare & branch. */ -static inline uint32_t -decode_cond_branch_ofs_19 (uint32_t insn) +bfd_signed_vma +_bfd_aarch64_sign_extend (bfd_vma value, int bits) { - return (insn >> 5) & MASK (19); -} + if (value & ((bfd_vma) 1 << (bits - 1))) + /* VALUE is negative. */ + value |= ((bfd_vma) - 1) << bits; -/* Decode the 19-bit offset of load literal. */ -static inline uint32_t -decode_ld_lit_ofs_19 (uint32_t insn) -{ - return (insn >> 5) & MASK (19); + return value; } -/* Decode the 14-bit offset of test & branch. */ -static inline uint32_t -decode_tst_branch_ofs_14 (uint32_t insn) -{ - return (insn >> 5) & MASK (14); -} +/* Decode the IMM field of ADRP. */ -/* Decode the 16-bit imm of move wide. */ -static inline uint32_t -decode_movw_imm (uint32_t insn) +uint32_t +_bfd_aarch64_decode_adrp_imm (uint32_t insn) { - return (insn >> 5) & MASK (16); -} - -/* Decode the 12-bit imm of add immediate. */ -static inline uint32_t -decode_add_imm (uint32_t insn) -{ - return (insn >> 10) & MASK (12); + return (((insn >> 5) & MASK (19)) << 2) | ((insn >> 29) & MASK (2)); } /* Reencode the imm field of add immediate. */ @@ -74,9 +52,10 @@ reencode_add_imm (uint32_t insn, uint32_t imm) return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10); } -/* Reencode the imm field of adr. */ -static inline uint32_t -reencode_adr_imm (uint32_t insn, uint32_t imm) +/* Reencode the IMM field of ADR. */ + +uint32_t +_bfd_aarch64_reencode_adr_imm (uint32_t insn, uint32_t imm) { return (insn & ~((MASK (2) << 29) | (MASK (19) << 5))) | ((imm & MASK (2)) << 29) | ((imm & (MASK (19) << 2)) << 3); @@ -228,8 +207,8 @@ _bfd_aarch64_elf_put_addend (bfd *abfd, switch (r_type) { - case BFD_RELOC_AARCH64_JUMP26: case BFD_RELOC_AARCH64_CALL26: + case BFD_RELOC_AARCH64_JUMP26: contents = reencode_branch_ofs_26 (contents, addend); break; @@ -241,9 +220,9 @@ _bfd_aarch64_elf_put_addend (bfd *abfd, contents = reencode_tst_branch_ofs_14 (contents, addend); break; - case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: - case BFD_RELOC_AARCH64_LD_LO19_PCREL: case BFD_RELOC_AARCH64_GOT_LD_PREL19: + case BFD_RELOC_AARCH64_LD_LO19_PCREL: + case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: if (old_addend & ((1 << howto->rightshift) - 1)) return bfd_reloc_overflow; @@ -253,24 +232,30 @@ _bfd_aarch64_elf_put_addend (bfd *abfd, case BFD_RELOC_AARCH64_TLSDESC_CALL: break; + case BFD_RELOC_AARCH64_ADR_GOT_PAGE: + case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL: + case BFD_RELOC_AARCH64_ADR_HI21_PCREL: + case BFD_RELOC_AARCH64_ADR_LO21_PCREL: + case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: - case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: - case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: - case BFD_RELOC_AARCH64_ADR_GOT_PAGE: - case BFD_RELOC_AARCH64_ADR_LO21_PCREL: - case BFD_RELOC_AARCH64_ADR_HI21_PCREL: - case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL: - contents = reencode_adr_imm (contents, addend); + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: + contents = _bfd_aarch64_reencode_adr_imm (contents, addend); break; + case BFD_RELOC_AARCH64_ADD_LO12: + case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12: case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: - case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12: + case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12: + case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12: case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC: - case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC: - case BFD_RELOC_AARCH64_ADD_LO12: /* Corresponds to: add rd, rn, #uimm12 to provide the low order 12 bits of the page offset following BFD_RELOC_AARCH64_ADR_HI21_PCREL which computes the @@ -278,17 +263,28 @@ _bfd_aarch64_elf_put_addend (bfd *abfd, contents = reencode_add_imm (contents, addend); break; - case BFD_RELOC_AARCH64_LDST8_LO12: + case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14: + case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: + case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: + case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: + case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: + case BFD_RELOC_AARCH64_LDST128_LO12: case BFD_RELOC_AARCH64_LDST16_LO12: case BFD_RELOC_AARCH64_LDST32_LO12: case BFD_RELOC_AARCH64_LDST64_LO12: - case BFD_RELOC_AARCH64_LDST128_LO12: - case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC: + case BFD_RELOC_AARCH64_LDST8_LO12: case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC: - case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12: case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC: - case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: - case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: + case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC: if (old_addend & ((1 << howto->rightshift) - 1)) return bfd_reloc_overflow; /* Used for ldr*|str* rt, [rn, #uimm12] to provide the low order @@ -302,12 +298,15 @@ _bfd_aarch64_elf_put_addend (bfd *abfd, instruction to MOVN or MOVZ depending on sign of calculated value. */ - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0: case BFD_RELOC_AARCH64_MOVW_G0_S: case BFD_RELOC_AARCH64_MOVW_G1_S: case BFD_RELOC_AARCH64_MOVW_G2_S: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2: + case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0: + case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1: + case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2: /* NOTE: We can only come here with movz or movn. */ if (addend < 0) { @@ -320,13 +319,11 @@ _bfd_aarch64_elf_put_addend (bfd *abfd, /* Force use of MOVZ. */ contents = reencode_movzn_to_movz (contents); } - /* fall through */ + /* Fall through. */ /* Group relocations to create a 16, 32, 48 or 64 bit unsigned data or abs address inline. */ - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC: case BFD_RELOC_AARCH64_MOVW_G0: case BFD_RELOC_AARCH64_MOVW_G0_NC: case BFD_RELOC_AARCH64_MOVW_G1: @@ -334,6 +331,18 @@ _bfd_aarch64_elf_put_addend (bfd *abfd, case BFD_RELOC_AARCH64_MOVW_G2: case BFD_RELOC_AARCH64_MOVW_G2_NC: case BFD_RELOC_AARCH64_MOVW_G3: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G1: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G1: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC: + case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC: contents = reencode_movw_imm (contents, addend); break; @@ -376,20 +385,21 @@ _bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type, { switch (r_type) { - case BFD_RELOC_AARCH64_TLSDESC_CALL: case BFD_RELOC_AARCH64_NONE: + case BFD_RELOC_AARCH64_TLSDESC_CALL: break; + case BFD_RELOC_AARCH64_16_PCREL: + case BFD_RELOC_AARCH64_32_PCREL: + case BFD_RELOC_AARCH64_64_PCREL: + case BFD_RELOC_AARCH64_ADR_LO21_PCREL: + case BFD_RELOC_AARCH64_BRANCH19: + case BFD_RELOC_AARCH64_LD_LO19_PCREL: case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: - case BFD_RELOC_AARCH64_ADR_LO21_PCREL: - case BFD_RELOC_AARCH64_BRANCH19: - case BFD_RELOC_AARCH64_LD_LO19_PCREL: - case BFD_RELOC_AARCH64_16_PCREL: - case BFD_RELOC_AARCH64_32_PCREL: - case BFD_RELOC_AARCH64_64_PCREL: + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: case BFD_RELOC_AARCH64_TSTBR14: if (weak_undef_p) value = place; @@ -403,21 +413,44 @@ _bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type, case BFD_RELOC_AARCH64_16: case BFD_RELOC_AARCH64_32: - case BFD_RELOC_AARCH64_MOVW_G0_S: - case BFD_RELOC_AARCH64_MOVW_G1_S: - case BFD_RELOC_AARCH64_MOVW_G2_S: + case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: case BFD_RELOC_AARCH64_MOVW_G0: case BFD_RELOC_AARCH64_MOVW_G0_NC: + case BFD_RELOC_AARCH64_MOVW_G0_S: case BFD_RELOC_AARCH64_MOVW_G1: case BFD_RELOC_AARCH64_MOVW_G1_NC: + case BFD_RELOC_AARCH64_MOVW_G1_S: case BFD_RELOC_AARCH64_MOVW_G2: case BFD_RELOC_AARCH64_MOVW_G2_NC: + case BFD_RELOC_AARCH64_MOVW_G2_S: case BFD_RELOC_AARCH64_MOVW_G3: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G1: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G1: + case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12: + case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12: + case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC: + case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2: value = value + addend; break; - case BFD_RELOC_AARCH64_ADR_HI21_PCREL: case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL: + case BFD_RELOC_AARCH64_ADR_HI21_PCREL: if (weak_undef_p) value = PG (place); value = PG (value + addend) - PG (place); @@ -431,30 +464,41 @@ _bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type, case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: value = PG (value + addend) - PG (place); break; + case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14: + case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: + /* Caller must make sure addend is the base address of .got section. */ + value = value - PG (addend); + break; + case BFD_RELOC_AARCH64_ADD_LO12: - case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: - case BFD_RELOC_AARCH64_LDST8_LO12: + case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: + case BFD_RELOC_AARCH64_LDST128_LO12: case BFD_RELOC_AARCH64_LDST16_LO12: case BFD_RELOC_AARCH64_LDST32_LO12: case BFD_RELOC_AARCH64_LDST64_LO12: - case BFD_RELOC_AARCH64_LDST128_LO12: - case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC: + case BFD_RELOC_AARCH64_LDST8_LO12: case BFD_RELOC_AARCH64_TLSDESC_ADD: - case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC: + case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12: case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC: + case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12: case BFD_RELOC_AARCH64_TLSDESC_LDR: case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: - case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC: - case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12: + case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC: value = PG_OFFSET (value + addend); break; + case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12: + value = value + addend; + break; + + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1: case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1: case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC: value = (value + addend) & (bfd_vma) 0xffff0000; @@ -465,6 +509,7 @@ _bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type, value = (value + addend) & ~(bfd_vma) 0xfff; break; + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0: case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC: value = (value + addend) & (bfd_vma) 0xffff; @@ -493,11 +538,10 @@ _bfd_aarch64_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, asection **secp ATTRIBUTE_UNUSED, bfd_vma *valp ATTRIBUTE_UNUSED) { - if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC - || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE) + if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC && (abfd->flags & DYNAMIC) == 0 && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour) - elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; return TRUE; }