X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felfnn-aarch64.c;h=8f3f75cf24228f570e4580168895682ee1488edc;hb=1aa66fb1527c3c81fef2a39a3a3ec9d36f1cfdec;hp=22f95d368f0a3bb4209ac831e3868c4c0efd8045;hpb=e234935207c21a212b5a35928f50b578c65b9649;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 22f95d368f..8f3f75cf24 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -1,5 +1,5 @@ /* AArch64-specific support for NN-bit ELF. - Copyright 2009-2013 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,78 @@ #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_TLSGD_MOVW_G1 \ || (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_HI12 \ + || (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_TLSLD_LDST16_DTPREL_LO12 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2 \ || (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_TLSDESC_ADD_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_LD_PREL19 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC \ + || (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_TLSLD_ADD_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21) + +#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 +334,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 +348,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 +885,83 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0xffc, /* dst_mask */ FALSE), /* pcrel_offset */ + /* Lower 16 bits of GOT offset for the symbol. */ + HOWTO64 (AARCH64_R (MOVW_GOTOFF_G0_NC), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (MOVW_GOTOFF_G0_NC), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Higher 16 bits of GOT offset for the symbol. */ + HOWTO64 (AARCH64_R (MOVW_GOTOFF_G1), /* type */ + 16, /* 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 (MOVW_GOTOFF_G1), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* 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 +978,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 */ @@ -878,6 +1007,21 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0xfff, /* dst_mask */ FALSE), /* pcrel_offset */ + /* Higher 16 bits of GOT offset to tls_index. */ + HOWTO64 (AARCH64_R (TLSGD_MOVW_G1), /* type */ + 16, /* 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 (TLSGD_MOVW_G1), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO64 (AARCH64_R (TLSIE_MOVW_GOTTPREL_G1), /* type */ 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -895,7 +1039,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 +1095,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,91 +1106,38 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0x1ffffc, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G2), /* type */ - 32, /* 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 (TLSLE_MOVW_TPREL_G2), /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G1), /* type */ - 16, /* 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 (TLSLE_MOVW_TPREL_G1), /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G1_NC), /* type */ - 16, /* 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 (TLSLE_MOVW_TPREL_G1_NC), /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G0), /* type */ - 0, /* rightshift */ + /* ADD: bit[23:12] of byte offset to module TLS base address. */ + HOWTO (AARCH64_R (TLSLD_ADD_DTPREL_HI12), /* type */ + 12, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 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_MOVW_TPREL_G0), /* name */ + AARCH64_R_STR (TLSLD_ADD_DTPREL_HI12), /* name */ FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G0_NC), /* type */ + /* 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_dont, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSLE_MOVW_TPREL_G0_NC), /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - HOWTO (AARCH64_R (TLSLE_ADD_TPREL_HI12), /* type */ - 12, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 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 */ + AARCH64_R_STR (TLSLD_ADD_DTPREL_LO12), /* name */ FALSE, /* partial_inplace */ 0xfff, /* src_mask */ 0xfff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLSLE_ADD_TPREL_LO12), /* type */ + /* 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 */ @@ -1054,13 +1145,14 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSLE_ADD_TPREL_LO12), /* name */ + AARCH64_R_STR (TLSLD_ADD_DTPREL_LO12_NC), /* name */ FALSE, /* partial_inplace */ 0xfff, /* src_mask */ 0xfff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLSLE_ADD_TPREL_LO12_NC), /* type */ + /* 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 */ @@ -1068,1577 +1160,2684 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSLE_ADD_TPREL_LO12_NC), /* name */ + AARCH64_R_STR (TLSLD_ADD_LO12_NC), /* name */ FALSE, /* partial_inplace */ 0xfff, /* src_mask */ 0xfff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLSDESC_LD_PREL19), /* type */ - 2, /* rightshift */ + /* 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_dont, /* complain_on_overflow */ + complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_LD_PREL19), /* name */ + AARCH64_R_STR (TLSLD_ADR_PAGE21), /* name */ FALSE, /* partial_inplace */ - 0x1ffffc, /* src_mask */ - 0x1ffffc, /* dst_mask */ + 0x1fffff, /* src_mask */ + 0x1fffff, /* dst_mask */ TRUE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLSDESC_ADR_PREL21), /* type */ + 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_dont, /* complain_on_overflow */ + complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_ADR_PREL21), /* name */ + AARCH64_R_STR (TLSLD_ADR_PREL21), /* name */ FALSE, /* partial_inplace */ 0x1fffff, /* src_mask */ 0x1fffff, /* dst_mask */ TRUE), /* pcrel_offset */ - /* Get to the page for the GOT entry for the symbol - (G(S) - P) using an ADRP instruction. */ - HOWTO (AARCH64_R (TLSDESC_ADR_PAGE21), /* type */ - 12, /* rightshift */ + /* LD/ST16: bit[11:1] of byte offset to module TLS base address. */ + HOWTO64 (AARCH64_R (TLSLD_LDST16_DTPREL_LO12), /* type */ + 1, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 21, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ + 11, /* bitsize */ + FALSE, /* pc_relative */ + 10, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_ADR_PAGE21), /* name */ + AARCH64_R_STR (TLSLD_LDST16_DTPREL_LO12), /* name */ FALSE, /* partial_inplace */ - 0x1fffff, /* src_mask */ - 0x1fffff, /* dst_mask */ - TRUE), /* pcrel_offset */ + 0x1ffc00, /* src_mask */ + 0x1ffc00, /* dst_mask */ + FALSE), /* pcrel_offset */ - /* LD64: GOT offset G(S) & 0xff8. */ - HOWTO64 (AARCH64_R (TLSDESC_LD64_LO12_NC), /* type */ - 3, /* rightshift */ + /* Same as BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12, but no overflow check. */ + HOWTO64 (AARCH64_R (TLSLD_LDST16_DTPREL_LO12_NC), /* type */ + 1, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ + 11, /* bitsize */ FALSE, /* pc_relative */ - 0, /* bitpos */ + 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_LD64_LO12_NC), /* name */ + AARCH64_R_STR (TLSLD_LDST16_DTPREL_LO12_NC), /* name */ FALSE, /* partial_inplace */ - 0xff8, /* src_mask */ - 0xff8, /* dst_mask */ + 0x1ffc00, /* src_mask */ + 0x1ffc00, /* dst_mask */ FALSE), /* pcrel_offset */ - /* LD32: GOT offset G(S) & 0xffc. */ - HOWTO32 (AARCH64_R (TLSDESC_LD32_LO12_NC), /* type */ + /* LD/ST32: bit[11:2] of byte offset to module TLS base address. */ + HOWTO64 (AARCH64_R (TLSLD_LDST32_DTPREL_LO12), /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ + 10, /* bitsize */ FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ + 10, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_LD32_LO12_NC), /* name */ + AARCH64_R_STR (TLSLD_LDST32_DTPREL_LO12), /* name */ FALSE, /* partial_inplace */ - 0xffc, /* src_mask */ - 0xffc, /* dst_mask */ + 0x3ffc00, /* src_mask */ + 0x3ffc00, /* dst_mask */ FALSE), /* pcrel_offset */ - /* ADD: GOT offset G(S) & 0xfff. */ - HOWTO (AARCH64_R (TLSDESC_ADD_LO12_NC), /* type */ - 0, /* rightshift */ + /* Same as BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12, but no overflow check. */ + HOWTO64 (AARCH64_R (TLSLD_LDST32_DTPREL_LO12_NC), /* type */ + 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ + 10, /* bitsize */ FALSE, /* pc_relative */ - 0, /* bitpos */ + 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_ADD_LO12_NC), /* name */ + AARCH64_R_STR (TLSLD_LDST32_DTPREL_LO12_NC), /* name */ FALSE, /* partial_inplace */ - 0xfff, /* src_mask */ - 0xfff, /* dst_mask */ + 0xffc00, /* src_mask */ + 0xffc00, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO64 (AARCH64_R (TLSDESC_OFF_G1), /* type */ - 16, /* rightshift */ + /* LD/ST64: bit[11:3] of byte offset to module TLS base address. */ + HOWTO64 (AARCH64_R (TLSLD_LDST64_DTPREL_LO12), /* type */ + 3, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 12, /* bitsize */ + 9, /* bitsize */ FALSE, /* pc_relative */ - 0, /* bitpos */ + 10, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_LDST64_DTPREL_LO12), /* name */ + FALSE, /* partial_inplace */ + 0x3ffc00, /* src_mask */ + 0x3ffc00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Same as BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12, but no overflow check. */ + HOWTO64 (AARCH64_R (TLSLD_LDST64_DTPREL_LO12_NC), /* type */ + 3, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 9, /* bitsize */ + FALSE, /* pc_relative */ + 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_OFF_G1), /* name */ + AARCH64_R_STR (TLSLD_LDST64_DTPREL_LO12_NC), /* name */ FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ + 0x7fc00, /* src_mask */ + 0x7fc00, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO64 (AARCH64_R (TLSDESC_OFF_G0_NC), /* type */ + /* LD/ST8: bit[11:0] of byte offset to module TLS base address. */ + HOWTO64 (AARCH64_R (TLSLD_LDST8_DTPREL_LO12), /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ + 10, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_OFF_G0_NC), /* name */ + AARCH64_R_STR (TLSLD_LDST8_DTPREL_LO12), /* name */ FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ + 0x3ffc00, /* src_mask */ + 0x3ffc00, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO64 (AARCH64_R (TLSDESC_LDR), /* type */ + /* Same as BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12, but no overflow check. */ + HOWTO64 (AARCH64_R (TLSLD_LDST8_DTPREL_LO12_NC), /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 12, /* bitsize */ FALSE, /* pc_relative */ - 0, /* bitpos */ + 10, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_LDR), /* name */ + AARCH64_R_STR (TLSLD_LDST8_DTPREL_LO12_NC), /* name */ FALSE, /* partial_inplace */ - 0x0, /* src_mask */ - 0x0, /* dst_mask */ + 0x3ffc00, /* src_mask */ + 0x3ffc00, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO64 (AARCH64_R (TLSDESC_ADD), /* type */ + /* MOVZ: bit[15:0] of byte offset to module TLS base address. */ + HOWTO (AARCH64_R (TLSLD_MOVW_DTPREL_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 */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_ADD), /* name */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G0), /* name */ FALSE, /* partial_inplace */ - 0x0, /* src_mask */ - 0x0, /* dst_mask */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLSDESC_CALL), /* type */ + /* No overflow check version of BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0. */ + HOWTO (AARCH64_R (TLSLD_MOVW_DTPREL_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 */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC_CALL), /* name */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G0_NC), /* name */ FALSE, /* partial_inplace */ - 0x0, /* src_mask */ - 0x0, /* dst_mask */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (COPY), /* type */ - 0, /* rightshift */ + /* MOVZ: bit[31:16] of byte offset to module TLS base address. */ + HOWTO (AARCH64_R (TLSLD_MOVW_DTPREL_G1), /* type */ + 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (COPY), /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G1), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (GLOB_DAT), /* type */ - 0, /* rightshift */ + /* No overflow check version of BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1. */ + HOWTO64 (AARCH64_R (TLSLD_MOVW_DTPREL_G1_NC), /* type */ + 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ + complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (GLOB_DAT), /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G1_NC), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (JUMP_SLOT), /* type */ - 0, /* rightshift */ + /* MOVZ: bit[47:32] of byte offset to module TLS base address. */ + HOWTO64 (AARCH64_R (TLSLD_MOVW_DTPREL_G2), /* type */ + 32, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (JUMP_SLOT), /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G2), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (RELATIVE), /* type */ - 0, /* rightshift */ + HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G2), /* type */ + 32, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (RELATIVE), /* name */ - TRUE, /* partial_inplace */ - ALL_ONES, /* src_mask */ - ALL_ONES, /* dst_mask */ + AARCH64_R_STR (TLSLE_MOVW_TPREL_G2), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLS_DTPMOD), /* type */ - 0, /* rightshift */ + HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G1), /* type */ + 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ -#if ARCH_SIZE == 64 - AARCH64_R_STR (TLS_DTPMOD64), /* name */ -#else - AARCH64_R_STR (TLS_DTPMOD), /* name */ -#endif + AARCH64_R_STR (TLSLE_MOVW_TPREL_G1), /* name */ FALSE, /* partial_inplace */ - 0, /* src_mask */ - ALL_ONES, /* dst_mask */ - FALSE), /* pc_reloffset */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLS_DTPREL), /* type */ - 0, /* rightshift */ + HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G1_NC), /* type */ + 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ -#if ARCH_SIZE == 64 - AARCH64_R_STR (TLS_DTPREL64), /* name */ -#else - AARCH64_R_STR (TLS_DTPREL), /* name */ -#endif + AARCH64_R_STR (TLSLE_MOVW_TPREL_G1_NC), /* name */ FALSE, /* partial_inplace */ - 0, /* src_mask */ - ALL_ONES, /* dst_mask */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLS_TPREL), /* type */ + HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G0), /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ -#if ARCH_SIZE == 64 - AARCH64_R_STR (TLS_TPREL64), /* name */ -#else - AARCH64_R_STR (TLS_TPREL), /* name */ -#endif + AARCH64_R_STR (TLSLE_MOVW_TPREL_G0), /* name */ FALSE, /* partial_inplace */ - 0, /* src_mask */ - ALL_ONES, /* dst_mask */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (TLSDESC), /* type */ + HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G0_NC), /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ + 16, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSDESC), /* name */ + AARCH64_R_STR (TLSLE_MOVW_TPREL_G0_NC), /* name */ FALSE, /* partial_inplace */ - 0, /* src_mask */ - ALL_ONES, /* dst_mask */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO (AARCH64_R (IRELATIVE), /* type */ - 0, /* rightshift */ + HOWTO (AARCH64_R (TLSLE_ADD_TPREL_HI12), /* type */ + 12, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ + 12, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (IRELATIVE), /* name */ + AARCH64_R_STR (TLSLE_ADD_TPREL_HI12), /* name */ FALSE, /* partial_inplace */ - 0, /* src_mask */ - ALL_ONES, /* dst_mask */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ FALSE), /* pcrel_offset */ - EMPTY_HOWTO (0), -}; - -static reloc_howto_type elfNN_aarch64_howto_none = - HOWTO (R_AARCH64_NONE, /* type */ + HOWTO (AARCH64_R (TLSLE_ADD_TPREL_LO12), /* type */ 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 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 */ - "R_AARCH64_NONE", /* name */ + AARCH64_R_STR (TLSLE_ADD_TPREL_LO12), /* name */ FALSE, /* partial_inplace */ - 0, /* src_mask */ - 0, /* dst_mask */ - FALSE); /* pcrel_offset */ - -/* Given HOWTO, return the bfd internal relocation enumerator. */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ -static bfd_reloc_code_real_type -elfNN_aarch64_bfd_reloc_from_howto (reloc_howto_type *howto) -{ - const int size - = (int) ARRAY_SIZE (elfNN_aarch64_howto_table); - const ptrdiff_t offset - = howto - elfNN_aarch64_howto_table; + HOWTO (AARCH64_R (TLSLE_ADD_TPREL_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 (TLSLE_ADD_TPREL_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ - if (offset > 0 && offset < size - 1) - return BFD_RELOC_AARCH64_RELOC_START + offset; + HOWTO (AARCH64_R (TLSDESC_LD_PREL19), /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 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 */ + 0x0ffffe0, /* src_mask */ + 0x0ffffe0, /* dst_mask */ + TRUE), /* pcrel_offset */ - if (howto == &elfNN_aarch64_howto_none) - return BFD_RELOC_AARCH64_NONE; + HOWTO (AARCH64_R (TLSDESC_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 (TLSDESC_ADR_PREL21), /* name */ + FALSE, /* partial_inplace */ + 0x1fffff, /* src_mask */ + 0x1fffff, /* dst_mask */ + TRUE), /* pcrel_offset */ - return BFD_RELOC_AARCH64_RELOC_START; + /* Get to the page for the GOT entry for the symbol + (G(S) - P) using an ADRP instruction. */ + HOWTO (AARCH64_R (TLSDESC_ADR_PAGE21), /* type */ + 12, /* 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 (TLSDESC_ADR_PAGE21), /* name */ + FALSE, /* partial_inplace */ + 0x1fffff, /* src_mask */ + 0x1fffff, /* dst_mask */ + TRUE), /* pcrel_offset */ + + /* LD64: GOT offset G(S) & 0xff8. */ + HOWTO64 (AARCH64_R (TLSDESC_LD64_LO12_NC), /* type */ + 3, /* 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 (TLSDESC_LD64_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0xff8, /* src_mask */ + 0xff8, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* LD32: GOT offset G(S) & 0xffc. */ + HOWTO32 (AARCH64_R (TLSDESC_LD32_LO12_NC), /* type */ + 2, /* 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 (TLSDESC_LD32_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0xffc, /* src_mask */ + 0xffc, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* ADD: GOT offset G(S) & 0xfff. */ + HOWTO (AARCH64_R (TLSDESC_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 (TLSDESC_ADD_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO64 (AARCH64_R (TLSDESC_OFF_G1), /* type */ + 16, /* 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 (TLSDESC_OFF_G1), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO64 (AARCH64_R (TLSDESC_OFF_G0_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 (TLSDESC_OFF_G0_NC), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO64 (AARCH64_R (TLSDESC_LDR), /* 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 (TLSDESC_LDR), /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO64 (AARCH64_R (TLSDESC_ADD), /* 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 (TLSDESC_ADD), /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (AARCH64_R (TLSDESC_CALL), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSDESC_CALL), /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (AARCH64_R (COPY), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (COPY), /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (AARCH64_R (GLOB_DAT), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (GLOB_DAT), /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (AARCH64_R (JUMP_SLOT), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (JUMP_SLOT), /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (AARCH64_R (RELATIVE), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (RELATIVE), /* name */ + TRUE, /* partial_inplace */ + ALL_ONES, /* src_mask */ + ALL_ONES, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (AARCH64_R (TLS_DTPMOD), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ +#if ARCH_SIZE == 64 + AARCH64_R_STR (TLS_DTPMOD64), /* name */ +#else + AARCH64_R_STR (TLS_DTPMOD), /* name */ +#endif + FALSE, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + FALSE), /* pc_reloffset */ + + HOWTO (AARCH64_R (TLS_DTPREL), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ +#if ARCH_SIZE == 64 + AARCH64_R_STR (TLS_DTPREL64), /* name */ +#else + AARCH64_R_STR (TLS_DTPREL), /* name */ +#endif + FALSE, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (AARCH64_R (TLS_TPREL), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ +#if ARCH_SIZE == 64 + AARCH64_R_STR (TLS_TPREL64), /* name */ +#else + AARCH64_R_STR (TLS_TPREL), /* name */ +#endif + FALSE, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (AARCH64_R (TLSDESC), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSDESC), /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (AARCH64_R (IRELATIVE), /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 64, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (IRELATIVE), /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + ALL_ONES, /* dst_mask */ + FALSE), /* pcrel_offset */ + + EMPTY_HOWTO (0), +}; + +static reloc_howto_type elfNN_aarch64_howto_none = + HOWTO (R_AARCH64_NONE, /* type */ + 0, /* rightshift */ + 3, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_AARCH64_NONE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE); /* pcrel_offset */ + +/* Given HOWTO, return the bfd internal relocation enumerator. */ + +static bfd_reloc_code_real_type +elfNN_aarch64_bfd_reloc_from_howto (reloc_howto_type *howto) +{ + const int size + = (int) ARRAY_SIZE (elfNN_aarch64_howto_table); + const ptrdiff_t offset + = howto - elfNN_aarch64_howto_table; + + if (offset > 0 && offset < size - 1) + return BFD_RELOC_AARCH64_RELOC_START + offset; + + if (howto == &elfNN_aarch64_howto_none) + return BFD_RELOC_AARCH64_NONE; + + return BFD_RELOC_AARCH64_RELOC_START; +} + +/* Given R_TYPE, return the bfd internal relocation enumerator. */ + +static bfd_reloc_code_real_type +elfNN_aarch64_bfd_reloc_from_type (unsigned int r_type) +{ + static bfd_boolean initialized_p = FALSE; + /* Indexed by R_TYPE, values are offsets in the howto_table. */ + static unsigned int offsets[R_AARCH64_end]; + + if (initialized_p == FALSE) + { + unsigned int i; + + for (i = 1; i < ARRAY_SIZE (elfNN_aarch64_howto_table) - 1; ++i) + if (elfNN_aarch64_howto_table[i].type != 0) + offsets[elfNN_aarch64_howto_table[i].type] = i; + + initialized_p = TRUE; + } + + 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]; +} + +struct elf_aarch64_reloc_map +{ + bfd_reloc_code_real_type from; + bfd_reloc_code_real_type to; +}; + +/* Map bfd generic reloc to AArch64-specific reloc. */ +static const struct elf_aarch64_reloc_map elf_aarch64_reloc_map[] = +{ + {BFD_RELOC_NONE, BFD_RELOC_AARCH64_NONE}, + + /* Basic data relocations. */ + {BFD_RELOC_CTOR, BFD_RELOC_AARCH64_NN}, + {BFD_RELOC_64, BFD_RELOC_AARCH64_64}, + {BFD_RELOC_32, BFD_RELOC_AARCH64_32}, + {BFD_RELOC_16, BFD_RELOC_AARCH64_16}, + {BFD_RELOC_64_PCREL, BFD_RELOC_AARCH64_64_PCREL}, + {BFD_RELOC_32_PCREL, BFD_RELOC_AARCH64_32_PCREL}, + {BFD_RELOC_16_PCREL, BFD_RELOC_AARCH64_16_PCREL}, +}; + +/* Given the bfd internal relocation enumerator in CODE, return the + corresponding howto entry. */ + +static reloc_howto_type * +elfNN_aarch64_howto_from_bfd_reloc (bfd_reloc_code_real_type code) +{ + unsigned int i; + + /* Convert bfd generic reloc to AArch64-specific reloc. */ + if (code < BFD_RELOC_AARCH64_RELOC_START + || code > BFD_RELOC_AARCH64_RELOC_END) + for (i = 0; i < ARRAY_SIZE (elf_aarch64_reloc_map); i++) + if (elf_aarch64_reloc_map[i].from == code) + { + code = elf_aarch64_reloc_map[i].to; + break; + } + + if (code > BFD_RELOC_AARCH64_RELOC_START + && code < BFD_RELOC_AARCH64_RELOC_END) + if (elfNN_aarch64_howto_table[code - BFD_RELOC_AARCH64_RELOC_START].type) + return &elfNN_aarch64_howto_table[code - BFD_RELOC_AARCH64_RELOC_START]; + + if (code == BFD_RELOC_AARCH64_NONE) + return &elfNN_aarch64_howto_none; + + return NULL; +} + +static reloc_howto_type * +elfNN_aarch64_howto_from_type (unsigned int r_type) +{ + bfd_reloc_code_real_type val; + reloc_howto_type *howto; + +#if ARCH_SIZE == 32 + if (r_type > 256) + { + bfd_set_error (bfd_error_bad_value); + return NULL; + } +#endif + + if (r_type == R_AARCH64_NONE) + return &elfNN_aarch64_howto_none; + + val = elfNN_aarch64_bfd_reloc_from_type (r_type); + howto = elfNN_aarch64_howto_from_bfd_reloc (val); + + if (howto != NULL) + return howto; + + bfd_set_error (bfd_error_bad_value); + return NULL; +} + +static void +elfNN_aarch64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc, + Elf_Internal_Rela *elf_reloc) +{ + unsigned int r_type; + + r_type = ELFNN_R_TYPE (elf_reloc->r_info); + bfd_reloc->howto = elfNN_aarch64_howto_from_type (r_type); +} + +static reloc_howto_type * +elfNN_aarch64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + bfd_reloc_code_real_type code) +{ + reloc_howto_type *howto = elfNN_aarch64_howto_from_bfd_reloc (code); + + if (howto != NULL) + return howto; + + bfd_set_error (bfd_error_bad_value); + return NULL; +} + +static reloc_howto_type * +elfNN_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 1; i < ARRAY_SIZE (elfNN_aarch64_howto_table) - 1; ++i) + if (elfNN_aarch64_howto_table[i].name != NULL + && strcasecmp (elfNN_aarch64_howto_table[i].name, r_name) == 0) + return &elfNN_aarch64_howto_table[i]; + + return NULL; +} + +#define TARGET_LITTLE_SYM aarch64_elfNN_le_vec +#define TARGET_LITTLE_NAME "elfNN-littleaarch64" +#define TARGET_BIG_SYM aarch64_elfNN_be_vec +#define TARGET_BIG_NAME "elfNN-bigaarch64" + +/* The linker script knows the section names for placement. + The entry_names are used to do simple name mangling on the stubs. + Given a function name, and its type, the stub can be found. The + name can be changed. The only requirement is the %s be present. */ +#define STUB_ENTRY_NAME "__%s_veneer" + +/* The name of the dynamic interpreter. This is put in the .interp + section. */ +#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1" + +#define AARCH64_MAX_FWD_BRANCH_OFFSET \ + (((1 << 25) - 1) << 2) +#define AARCH64_MAX_BWD_BRANCH_OFFSET \ + (-((1 << 25) << 2)) + +#define AARCH64_MAX_ADRP_IMM ((1 << 20) - 1) +#define AARCH64_MIN_ADRP_IMM (-(1 << 20)) + +static int +aarch64_valid_for_adrp_p (bfd_vma value, bfd_vma place) +{ + bfd_signed_vma offset = (bfd_signed_vma) (PG (value) - PG (place)) >> 12; + return offset <= AARCH64_MAX_ADRP_IMM && offset >= AARCH64_MIN_ADRP_IMM; +} + +static int +aarch64_valid_branch_p (bfd_vma value, bfd_vma place) +{ + bfd_signed_vma offset = (bfd_signed_vma) (value - place); + return (offset <= AARCH64_MAX_FWD_BRANCH_OFFSET + && offset >= AARCH64_MAX_BWD_BRANCH_OFFSET); +} + +static const uint32_t aarch64_adrp_branch_stub [] = +{ + 0x90000010, /* adrp ip0, X */ + /* R_AARCH64_ADR_HI21_PCREL(X) */ + 0x91000210, /* add ip0, ip0, :lo12:X */ + /* R_AARCH64_ADD_ABS_LO12_NC(X) */ + 0xd61f0200, /* br ip0 */ +}; + +static const uint32_t aarch64_long_branch_stub[] = +{ +#if ARCH_SIZE == 64 + 0x58000090, /* ldr ip0, 1f */ +#else + 0x18000090, /* ldr wip0, 1f */ +#endif + 0x10000011, /* adr ip1, #0 */ + 0x8b110210, /* add ip0, ip0, ip1 */ + 0xd61f0200, /* br ip0 */ + 0x00000000, /* 1: .xword or .word + R_AARCH64_PRELNN(X) + 12 + */ + 0x00000000, +}; + +static const uint32_t aarch64_erratum_835769_stub[] = +{ + 0x00000000, /* Placeholder for multiply accumulate. */ + 0x14000000, /* b