X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felfnn-aarch64.c;h=962a10edf9f376ee9cdca629e34cd467b4726e30;hb=753999c1ec8fa76bd5ed5509d1e5909d010e80ee;hp=4baa41b00c4263395ef60241012ea506fdb2e225;hpb=caa4096e844a000ff63c4fa9180d70ca2093fd2a;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 4baa41b00c..962a10edf9 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -1,5 +1,5 @@ /* AArch64-specific support for NN-bit ELF. - Copyright (C) 2009-2014 Free Software Foundation, Inc. + Copyright (C) 2009-2015 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of BFD, the Binary File Descriptor library. @@ -165,40 +165,60 @@ #endif #define IS_AARCH64_TLS_RELOC(R_TYPE) \ - ((R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21 \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1 \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC \ + ((R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PREL21 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19 \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2 \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1 \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLS_DTPMOD \ || (R_TYPE) == BFD_RELOC_AARCH64_TLS_DTPREL \ || (R_TYPE) == BFD_RELOC_AARCH64_TLS_TPREL \ || IS_AARCH64_TLSDESC_RELOC ((R_TYPE))) -#define IS_AARCH64_TLSDESC_RELOC(R_TYPE) \ - ((R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD_PREL19 \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21 \ +#define IS_AARCH64_TLS_RELAX_RELOC(R_TYPE) \ + ((R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PREL21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD_PREL19 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_CALL \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC) + +#define IS_AARCH64_TLSDESC_RELOC(R_TYPE) \ + ((R_TYPE) == BFD_RELOC_AARCH64_TLSDESC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_CALL \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G1 \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LDR \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_CALL \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC) + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD_PREL19 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G1) #define ELIMINATE_COPY_RELOCS 0 @@ -296,7 +316,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = #if ARCH_SIZE == 64 HOWTO (R_AARCH64_NULL, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -310,7 +330,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = #else HOWTO (R_AARCH64_NONE, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -847,6 +867,53 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0xffc, /* dst_mask */ FALSE), /* pcrel_offset */ + /* LD64: GOT offset for the symbol. */ + HOWTO64 (AARCH64_R (LD64_GOTOFF_LO15), /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (LD64_GOTOFF_LO15), /* name */ + FALSE, /* partial_inplace */ + 0x7ff8, /* src_mask */ + 0x7ff8, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* LD32: GOT offset to the page address of GOT table. + (G(S) - PAGE (_GLOBAL_OFFSET_TABLE_)) & 0x5ffc. */ + HOWTO32 (AARCH64_R (LD32_GOTPAGE_LO14), /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (LD32_GOTPAGE_LO14), /* name */ + FALSE, /* partial_inplace */ + 0x5ffc, /* src_mask */ + 0x5ffc, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* LD64: GOT offset to the page address of GOT table. + (G(S) - PAGE (_GLOBAL_OFFSET_TABLE_)) & 0x7ff8. */ + HOWTO64 (AARCH64_R (LD64_GOTPAGE_LO15), /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (LD64_GOTPAGE_LO15), /* name */ + FALSE, /* partial_inplace */ + 0x7ff8, /* src_mask */ + 0x7ff8, /* dst_mask */ + FALSE), /* pcrel_offset */ + /* Get to the page for the GOT entry for the symbol (G(S) - P) using an ADRP instruction. */ HOWTO (AARCH64_R (TLSGD_ADR_PAGE21), /* type */ @@ -863,6 +930,20 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0x1fffff, /* dst_mask */ TRUE), /* pcrel_offset */ + HOWTO (AARCH64_R (TLSGD_ADR_PREL21), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 21, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSGD_ADR_PREL21), /* name */ + FALSE, /* partial_inplace */ + 0x1fffff, /* src_mask */ + 0x1fffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + /* ADD: GOT offset G(S) & 0xff8 [no overflow check] */ HOWTO (AARCH64_R (TLSGD_ADD_LO12_NC), /* type */ 0, /* rightshift */ @@ -895,7 +976,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO64 (AARCH64_R (TLSIE_MOVW_GOTTPREL_G0_NC), /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -951,7 +1032,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO (AARCH64_R (TLSIE_LD_GOTTPREL_PREL19), /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 21, /* bitsize */ + 19, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -962,14 +1043,89 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0x1ffffc, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G2), /* type */ - 32, /* rightshift */ + /* Unsigned 12 bit byte offset to module TLS base address. */ + HOWTO (AARCH64_R (TLSLD_ADD_DTPREL_LO12), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_ADD_DTPREL_LO12), /* name */ + FALSE, /* partial_inplace */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* No overflow check version of BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12. */ + HOWTO (AARCH64_R (TLSLD_ADD_DTPREL_LO12_NC), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 12, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_ADD_DTPREL_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* ADD: GOT offset G(S) & 0xff8 [no overflow check] */ + HOWTO (AARCH64_R (TLSLD_ADD_LO12_NC), /* type */ + 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_ADD_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Get to the page for the GOT entry for the symbol + (G(S) - P) using an ADRP instruction. */ + HOWTO (AARCH64_R (TLSLD_ADR_PAGE21), /* type */ + 12, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 21, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_ADR_PAGE21), /* name */ + FALSE, /* partial_inplace */ + 0x1fffff, /* src_mask */ + 0x1fffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO (AARCH64_R (TLSLD_ADR_PREL21), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 21, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_ADR_PREL21), /* name */ + FALSE, /* partial_inplace */ + 0x1fffff, /* src_mask */ + 0x1fffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G2), /* type */ + 32, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ AARCH64_R_STR (TLSLE_MOVW_TPREL_G2), /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ @@ -979,7 +1135,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G1), /* type */ 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -993,7 +1149,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G1_NC), /* type */ 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -1007,7 +1163,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G0), /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -1021,7 +1177,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G0_NC), /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -1038,7 +1194,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 12, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ AARCH64_R_STR (TLSLE_ADD_TPREL_HI12), /* name */ FALSE, /* partial_inplace */ @@ -1052,7 +1208,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 12, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ AARCH64_R_STR (TLSLE_ADD_TPREL_LO12), /* name */ FALSE, /* partial_inplace */ @@ -1077,15 +1233,15 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO (AARCH64_R (TLSDESC_LD_PREL19), /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 21, /* bitsize */ + 19, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ AARCH64_R_STR (TLSDESC_LD_PREL19), /* name */ FALSE, /* partial_inplace */ - 0x1ffffc, /* src_mask */ - 0x1ffffc, /* dst_mask */ + 0x0ffffe0, /* src_mask */ + 0x0ffffe0, /* dst_mask */ TRUE), /* pcrel_offset */ HOWTO (AARCH64_R (TLSDESC_ADR_PREL21), /* type */ @@ -1222,7 +1378,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO (AARCH64_R (TLSDESC_CALL), /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ + 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ @@ -1377,7 +1533,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = static reloc_howto_type elfNN_aarch64_howto_none = HOWTO (R_AARCH64_NONE, /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ @@ -1431,6 +1587,14 @@ elfNN_aarch64_bfd_reloc_from_type (unsigned int r_type) if (r_type == R_AARCH64_NONE || r_type == R_AARCH64_NULL) return BFD_RELOC_AARCH64_NONE; + /* PR 17512: file: b371e70a. */ + if (r_type >= R_AARCH64_end) + { + _bfd_error_handler (_("Invalid AArch64 reloc number: %d"), r_type); + bfd_set_error (bfd_error_bad_value); + return BFD_RELOC_AARCH64_NONE; + } + return BFD_RELOC_AARCH64_RELOC_START + offsets[r_type]; } @@ -1611,6 +1775,18 @@ static const uint32_t aarch64_long_branch_stub[] = 0x00000000, }; +static const uint32_t aarch64_erratum_835769_stub[] = +{ + 0x00000000, /* Placeholder for multiply accumulate. */ + 0x14000000, /* b