X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=bfd%2Felfnn-aarch64.c;h=b329273a99047e93a10e2d53ab5dc4584cc44a2e;hb=50e03d47b77d5730f96f6b6bb66187654e66c797;hp=1d896d4ea327390d5233e303160fe97985275617;hpb=80de0c6d618be3656fa5a82bf445e0cd1b4b16d3;p=binutils-gdb.git diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 1d896d4ea32..b329273a990 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-2015 Free Software Foundation, Inc. + Copyright (C) 2009-2016 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of BFD, the Binary File Descriptor library. @@ -165,41 +165,86 @@ #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_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_MOVW_GOTTPREL_G1 \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC \ + || (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 \ +#define IS_AARCH64_TLS_RELAX_RELOC(R_TYPE) \ + ((R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD \ + || (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_ADD_LO12_NC \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G1 \ + || (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_TLSDESC_LDR \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G1 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LDR \ + || (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_TLSGD_MOVW_G0_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_MOVW_G1 \ + || (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_ADR_PAGE21 \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21 \ || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_CALL \ - || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC) + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC \ + || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LDR \ + || (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 @@ -294,8 +339,8 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = /* Basic data relocations. */ -#if ARCH_SIZE == 64 - HOWTO (R_AARCH64_NULL, /* type */ + /* Deprecated, but retained for backwards compatibility. */ + HOWTO64 (R_AARCH64_NULL, /* type */ 0, /* rightshift */ 3, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ @@ -308,7 +353,6 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ -#else HOWTO (R_AARCH64_NONE, /* type */ 0, /* rightshift */ 3, /* size (0 = byte, 1 = short, 2 = long) */ @@ -322,7 +366,6 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0, /* src_mask */ 0, /* dst_mask */ FALSE), /* pcrel_offset */ -#endif /* .xword: (S+A) */ HOWTO64 (AARCH64_R (ABS64), /* type */ @@ -530,7 +573,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO (AARCH64_R (MOVW_SABS_G0), /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ + 17, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ @@ -545,7 +588,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO64 (AARCH64_R (MOVW_SABS_G1), /* type */ 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ + 17, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ @@ -560,7 +603,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = HOWTO64 (AARCH64_R (MOVW_SABS_G2), /* type */ 32, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ + 17, /* bitsize */ FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ @@ -848,6 +891,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 */ @@ -893,29 +1013,31 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0xfff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO64 (AARCH64_R (TLSIE_MOVW_GOTTPREL_G1), /* type */ - 16, /* rightshift */ + /* Lower 16 bits of GOT offset to tls_index. */ + HOWTO64 (AARCH64_R (TLSGD_MOVW_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 (TLSIE_MOVW_GOTTPREL_G1), /* name */ + AARCH64_R_STR (TLSGD_MOVW_G0_NC), /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ FALSE), /* pcrel_offset */ - HOWTO64 (AARCH64_R (TLSIE_MOVW_GOTTPREL_G0_NC), /* type */ - 0, /* rightshift */ + /* 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_dont, /* complain_on_overflow */ + complain_overflow_unsigned, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - AARCH64_R_STR (TLSIE_MOVW_GOTTPREL_G0_NC), /* name */ + AARCH64_R_STR (TLSGD_MOVW_G1), /* name */ FALSE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ @@ -977,6 +1099,319 @@ static reloc_howto_type elfNN_aarch64_howto_table[] = 0x1ffffc, /* dst_mask */ FALSE), /* pcrel_offset */ + HOWTO64 (AARCH64_R (TLSIE_MOVW_GOTTPREL_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 (TLSIE_MOVW_GOTTPREL_G0_NC), /* 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) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSIE_MOVW_GOTTPREL_G1), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_ADD_DTPREL_HI12), /* name */ + FALSE, /* partial_inplace */ + 0xfff, /* src_mask */ + 0xfff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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 */ + + /* 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) */ + 11, /* bitsize */ + FALSE, /* pc_relative */ + 10, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_LDST16_DTPREL_LO12), /* name */ + FALSE, /* partial_inplace */ + 0x1ffc00, /* src_mask */ + 0x1ffc00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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) */ + 11, /* bitsize */ + FALSE, /* pc_relative */ + 10, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_LDST16_DTPREL_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0x1ffc00, /* src_mask */ + 0x1ffc00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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) */ + 10, /* bitsize */ + FALSE, /* pc_relative */ + 10, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_LDST32_DTPREL_LO12), /* name */ + FALSE, /* partial_inplace */ + 0x3ffc00, /* src_mask */ + 0x3ffc00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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) */ + 10, /* bitsize */ + FALSE, /* pc_relative */ + 10, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_LDST32_DTPREL_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0xffc00, /* src_mask */ + 0xffc00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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) */ + 9, /* bitsize */ + FALSE, /* pc_relative */ + 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 (TLSLD_LDST64_DTPREL_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0x7fc00, /* src_mask */ + 0x7fc00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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 */ + 10, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_LDST8_DTPREL_LO12), /* name */ + FALSE, /* partial_inplace */ + 0x3ffc00, /* src_mask */ + 0x3ffc00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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 */ + 10, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_LDST8_DTPREL_LO12_NC), /* name */ + FALSE, /* partial_inplace */ + 0x3ffc00, /* src_mask */ + 0x3ffc00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G0), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G0_NC), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G1), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G1_NC), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 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) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_unsigned, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + AARCH64_R_STR (TLSLD_MOVW_DTPREL_G2), /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G2), /* type */ 32, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ @@ -1067,7 +1502,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 */ @@ -1184,7 +1619,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 (TLSDESC_OFF_G1), /* name */ FALSE, /* partial_inplace */ @@ -1852,6 +2287,9 @@ struct elf_aarch64_link_hash_table /* Enable ADRP->ADR rewrite for erratum 843419 workaround. */ int fix_erratum_843419_adr; + /* Don't apply link-time values for dynamic relocations. */ + int no_apply_dynamic_relocs; + /* The number of bytes in the initial entry in the PLT. */ bfd_size_type plt_header_size; @@ -1895,7 +2333,7 @@ struct elf_aarch64_link_hash_table /* Assorted information used by elfNN_aarch64_size_stubs. */ unsigned int bfd_count; - int top_index; + unsigned int top_index; asection **input_list; /* The offset into splt of the PLT entry for the TLS descriptor @@ -2202,28 +2640,19 @@ aarch64_select_branch_stub (bfd_vma value, bfd_vma place) /* Determine the type of stub needed, if any, for a call. */ static enum elf_aarch64_stub_type -aarch64_type_of_stub (struct bfd_link_info *info, - asection *input_sec, +aarch64_type_of_stub (asection *input_sec, const Elf_Internal_Rela *rel, + asection *sym_sec, unsigned char st_type, - struct elf_aarch64_link_hash_entry *hash, bfd_vma destination) { bfd_vma location; bfd_signed_vma branch_offset; unsigned int r_type; - struct elf_aarch64_link_hash_table *globals; enum elf_aarch64_stub_type stub_type = aarch64_stub_none; - bfd_boolean via_plt_p; - - if (st_type != STT_FUNC) - return stub_type; - - globals = elf_aarch64_hash_table (info); - via_plt_p = (globals->root.splt != NULL && hash != NULL - && hash->root.plt.offset != (bfd_vma) - 1); - if (via_plt_p) + if (st_type != STT_FUNC + && (sym_sec == input_sec)) return stub_type; /* Determine where the call point is. */ @@ -2404,8 +2833,8 @@ _bfd_aarch64_add_stub_entry_in_group (const char *stub_name, TRUE, FALSE); if (stub_entry == NULL) { - (*_bfd_error_handler) (_("%s: cannot create stub entry %s"), - section->owner, stub_name); + _bfd_error_handler (_("%s: cannot create stub entry %s"), + section->owner, stub_name); return NULL; } @@ -2432,7 +2861,7 @@ _bfd_aarch64_add_stub_entry_after (const char *stub_name, TRUE, FALSE); if (stub_entry == NULL) { - (*_bfd_error_handler) (_("cannot create stub entry %s"), stub_name); + _bfd_error_handler (_("cannot create stub entry %s"), stub_name); return NULL; } @@ -2616,7 +3045,7 @@ elfNN_aarch64_setup_section_lists (bfd *output_bfd, { bfd *input_bfd; unsigned int bfd_count; - int top_id, top_index; + unsigned int top_id, top_index; asection *section; asection **input_list, **list; bfd_size_type amt; @@ -3701,8 +4130,8 @@ elfNN_aarch64_size_stubs (bfd *output_bfd, } /* Determine what (if any) linker stub is needed. */ - stub_type = aarch64_type_of_stub - (info, section, irela, st_type, hash, destination); + stub_type = aarch64_type_of_stub (section, irela, sym_sec, + st_type, destination); if (stub_type == aarch64_stub_none) continue; @@ -3733,7 +4162,7 @@ elfNN_aarch64_size_stubs (bfd *output_bfd, goto error_ret_free_internal; } - stub_entry->target_value = sym_value; + stub_entry->target_value = sym_value + irela->r_addend; stub_entry->target_section = sym_sec; stub_entry->stub_type = stub_type; stub_entry->h = hash; @@ -3906,7 +4335,8 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd, int no_enum_warn, int no_wchar_warn, int pic_veneer, int fix_erratum_835769, - int fix_erratum_843419) + int fix_erratum_843419, + int no_apply_dynamic_relocs) { struct elf_aarch64_link_hash_table *globals; @@ -3915,6 +4345,7 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd, globals->fix_erratum_835769 = fix_erratum_835769; globals->fix_erratum_843419 = fix_erratum_843419; globals->fix_erratum_843419_adr = TRUE; + globals->no_apply_dynamic_relocs = no_apply_dynamic_relocs; BFD_ASSERT (is_aarch64_elf (output_bfd)); elf_aarch64_tdata (output_bfd)->no_enum_size_warning = no_enum_warn; @@ -3937,8 +4368,8 @@ aarch64_calculate_got_entry_vma (struct elf_link_hash_entry *h, BFD_ASSERT (basegot != NULL); off = h->got.offset; BFD_ASSERT (off != (bfd_vma) - 1); - if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) - || (info->shared + if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) + || (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) || (ELF_ST_VISIBILITY (h->other) && h->root.type == bfd_link_hash_undefweak)) @@ -3980,8 +4411,8 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type, switch (r_type) { - case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: return (is_local ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1 : BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21); @@ -3996,8 +4427,23 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type, ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1 : BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19); - case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSDESC_LDR: + return (is_local + ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC + : BFD_RELOC_AARCH64_NONE); + + case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC: + return (is_local + ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC + : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC); + + case BFD_RELOC_AARCH64_TLSDESC_OFF_G1: + return (is_local + ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2 + : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1); + case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC: + case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: return (is_local ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC : BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC); @@ -4016,11 +4462,29 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type, ? BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12 : BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19); + case BFD_RELOC_AARCH64_TLSDESC_ADD: case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_CALL: /* Instructions with these relocations will become NOPs. */ return BFD_RELOC_AARCH64_NONE; + case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: + return is_local ? BFD_RELOC_AARCH64_NONE : r_type; + +#if ARCH_SIZE == 64 + case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC: + return is_local + ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC + : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC; + + case BFD_RELOC_AARCH64_TLSGD_MOVW_G1: + return is_local + ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2 + : BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1; +#endif + default: break; } @@ -4033,42 +4497,48 @@ aarch64_reloc_got_type (bfd_reloc_code_real_type r_type) { switch (r_type) { - case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: - case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: case BFD_RELOC_AARCH64_ADR_GOT_PAGE: case BFD_RELOC_AARCH64_GOT_LD_PREL19: + 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_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: return GOT_NORMAL; + case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: - case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G1: + case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: return GOT_TLS_GD; + case BFD_RELOC_AARCH64_TLSDESC_ADD: case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: case BFD_RELOC_AARCH64_TLSDESC_CALL: - case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC: + case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: + case BFD_RELOC_AARCH64_TLSDESC_LDR: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G1: return GOT_TLSDESC_GD; case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: - case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1: return GOT_TLS_IE; - 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_TLSLE_MOVW_TPREL_G0: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2: - return GOT_UNKNOWN; - default: break; } @@ -4085,7 +4555,7 @@ aarch64_can_relax_tls (bfd *input_bfd, unsigned int symbol_got_type; unsigned int reloc_got_type; - if (! IS_AARCH64_TLS_RELOC (r_type)) + if (! IS_AARCH64_TLS_RELAX_RELOC (r_type)) return FALSE; symbol_got_type = elfNN_aarch64_symbol_got_type (h, input_bfd, r_symndx); @@ -4094,7 +4564,7 @@ aarch64_can_relax_tls (bfd *input_bfd, if (symbol_got_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (reloc_got_type)) return TRUE; - if (info->shared) + if (bfd_link_pic (info)) return FALSE; if (h && h->root.type == bfd_link_hash_undefweak) @@ -4289,9 +4759,9 @@ make_branch_to_erratum_835769_stub (struct bfd_hash_entry *gen_entry, abfd = stub_entry->target_section->owner; if (!aarch64_valid_branch_p (veneer_entry_loc, veneered_insn_loc)) - (*_bfd_error_handler) - (_("%B: error: Erratum 835769 stub out " - "of range (input file too large)"), abfd); + _bfd_error_handler + (_("%B: error: Erratum 835769 stub out " + "of range (input file too large)"), abfd); target = stub_entry->target_value; branch_insn = 0x14000000; @@ -4370,7 +4840,7 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry, abfd = stub_entry->target_section->owner; if (!aarch64_valid_branch_p (veneer_entry_loc, veneered_insn_loc)) - (*_bfd_error_handler) + _bfd_error_handler (_("%B: error: Erratum 843419 stub out " "of range (input file too large)"), abfd); @@ -4423,7 +4893,9 @@ elfNN_aarch64_write_section (bfd *output_bfd ATTRIBUTE_UNUSED, return FALSE; } -/* Perform a relocation as part of a final link. */ +/* Perform a relocation as part of a final link. The input relocation type + should be TLS relaxed. */ + static bfd_reloc_status_type elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd, @@ -4444,7 +4916,6 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, unsigned int r_type = howto->type; bfd_reloc_code_real_type bfd_r_type = elfNN_aarch64_bfd_reloc_from_howto (howto); - bfd_reloc_code_real_type new_bfd_r_type; unsigned long r_symndx; bfd_byte *hit_data = contents + rel->r_offset; bfd_vma place, off; @@ -4461,17 +4932,6 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, r_symndx = ELFNN_R_SYM (rel->r_info); - /* It is possible to have linker relaxations on some TLS access - models. Update our information here. */ - new_bfd_r_type = aarch64_tls_transition (input_bfd, info, r_type, h, r_symndx); - if (new_bfd_r_type != bfd_r_type) - { - bfd_r_type = new_bfd_r_type; - howto = elfNN_aarch64_howto_from_bfd_reloc (bfd_r_type); - BFD_ASSERT (howto != NULL); - r_type = howto->type; - } - place = input_section->output_section->vma + input_section->output_offset + rel->r_offset; @@ -4491,6 +4951,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, { asection *plt; const char *name; + bfd_vma addend = 0; if ((input_section->flags & SEC_ALLOC) == 0 || h->plt.offset == (bfd_vma) -1) @@ -4508,7 +4969,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, else name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, NULL); - (*_bfd_error_handler) + _bfd_error_handler (_("%B: relocation %s against STT_GNU_IFUNC " "symbol `%s' isn't handled by %s"), input_bfd, howto->name, name, __FUNCTION__); @@ -4523,7 +4984,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, else name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, NULL); - (*_bfd_error_handler) + _bfd_error_handler (_("%B: relocation %s against STT_GNU_IFUNC " "symbol `%s' has non-zero addend: %d"), input_bfd, howto->name, name, rel->r_addend); @@ -4533,7 +4994,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, /* Generate dynamic relocation only when there is a non-GOT reference in a shared object. */ - if (info->shared && h->non_got_ref) + if (bfd_link_pic (info) && h->non_got_ref) { Elf_Internal_Rela outrel; asection *sreloc; @@ -4553,7 +5014,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, if (h->dynindx == -1 || h->forced_local - || info->executable) + || bfd_link_executable (info)) { /* This symbol is resolved locally. */ outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (IRELATIVE)); @@ -4578,17 +5039,22 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, return bfd_reloc_ok; } /* FALLTHROUGH */ - case BFD_RELOC_AARCH64_JUMP26: case BFD_RELOC_AARCH64_CALL26: + case BFD_RELOC_AARCH64_JUMP26: value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, signed_addend, weak_undef_p); return _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type, howto, value); - case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: - case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: case BFD_RELOC_AARCH64_ADR_GOT_PAGE: case BFD_RELOC_AARCH64_GOT_LD_PREL19: + case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14: + case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: + case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: + case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: + case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: base_got = globals->root.sgot; off = h->got.offset; @@ -4647,11 +5113,28 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, value = aarch64_calculate_got_entry_vma (h, globals, info, value, output_bfd, unresolved_reloc_p); + + switch (bfd_r_type) + { + case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14: + case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: + addend = (globals->root.sgot->output_section->vma + + globals->root.sgot->output_offset); + break; + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: + case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: + value = (value - globals->root.sgot->output_section->vma + - globals->root.sgot->output_offset); + default: + break; + } + value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, - 0, weak_undef_p); + addend, weak_undef_p); return _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type, howto, value); - case BFD_RELOC_AARCH64_ADR_HI21_PCREL: case BFD_RELOC_AARCH64_ADD_LO12: + case BFD_RELOC_AARCH64_ADR_HI21_PCREL: break; } } @@ -4659,7 +5142,9 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, switch (bfd_r_type) { case BFD_RELOC_AARCH64_NONE: + case BFD_RELOC_AARCH64_TLSDESC_ADD: case BFD_RELOC_AARCH64_TLSDESC_CALL: + case BFD_RELOC_AARCH64_TLSDESC_LDR: *unresolved_reloc_p = FALSE; return bfd_reloc_ok; @@ -4668,7 +5153,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, /* When generating a shared object or relocatable executable, these relocations are copied into the output file to be resolved at run time. */ - if (((info->shared == TRUE) || globals->root.is_relocatable_executable) + if (((bfd_link_pic (info) == TRUE) + || globals->root.is_relocatable_executable) && (input_section->flags & SEC_ALLOC) && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT @@ -4703,7 +5189,9 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, memset (&outrel, 0, sizeof outrel); else if (h != NULL && h->dynindx != -1 - && (!info->shared || !SYMBOLIC_BIND (info, h) || !h->def_regular)) + && (!bfd_link_pic (info) + || !SYMBOLIC_BIND (info, h) + || !h->def_regular)) outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type); else { @@ -4713,6 +5201,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, relocate the text and data segments independently, so the symbol does not matter. */ symbol = 0; + relocate = globals->no_apply_dynamic_relocs ? FALSE : TRUE; outrel.r_info = ELFNN_R_INFO (symbol, AARCH64_R (RELATIVE)); outrel.r_addend += value; } @@ -4746,8 +5235,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, value += signed_addend; break; - case BFD_RELOC_AARCH64_JUMP26: case BFD_RELOC_AARCH64_CALL26: + case BFD_RELOC_AARCH64_JUMP26: { asection *splt = globals->root.splt; bfd_boolean via_plt_p = @@ -4766,48 +5255,48 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, /* If the call goes through a PLT entry, make sure to check distance to the right destination address. */ if (via_plt_p) + value = (splt->output_section->vma + + splt->output_offset + h->plt.offset); + + /* Check if a stub has to be inserted because the destination + is too far away. */ + struct elf_aarch64_stub_hash_entry *stub_entry = NULL; + + /* If the branch destination is directed to plt stub, "value" will be + the final destination, otherwise we should plus signed_addend, it may + contain non-zero value, for example call to local function symbol + which are turned into "sec_sym + sec_off", and sec_off is kept in + signed_addend. */ + if (! aarch64_valid_branch_p (via_plt_p ? value : value + signed_addend, + place)) + /* The target is out of reach, so redirect the branch to + the local stub for this function. */ + stub_entry = elfNN_aarch64_get_stub_entry (input_section, sym_sec, h, + rel, globals); + if (stub_entry != NULL) { - value = (splt->output_section->vma - + splt->output_offset + h->plt.offset); - *unresolved_reloc_p = FALSE; - } + value = (stub_entry->stub_offset + + stub_entry->stub_sec->output_offset + + stub_entry->stub_sec->output_section->vma); - /* If the target symbol is global and marked as a function the - relocation applies a function call or a tail call. In this - situation we can veneer out of range branches. The veneers - use IP0 and IP1 hence cannot be used arbitrary out of range - branches that occur within the body of a function. */ - if (h && h->type == STT_FUNC) - { - /* Check if a stub has to be inserted because the destination - is too far away. */ - if (! aarch64_valid_branch_p (value, place)) - { - /* The target is out of reach, so redirect the branch to - the local stub for this function. */ - struct elf_aarch64_stub_hash_entry *stub_entry; - stub_entry = elfNN_aarch64_get_stub_entry (input_section, - sym_sec, h, - rel, globals); - if (stub_entry != NULL) - value = (stub_entry->stub_offset - + stub_entry->stub_sec->output_offset - + stub_entry->stub_sec->output_section->vma); - } + /* We have redirected the destination to stub entry address, + so ignore any addend record in the original rela entry. */ + signed_addend = 0; } } value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, signed_addend, weak_undef_p); + *unresolved_reloc_p = FALSE; break; - case BFD_RELOC_AARCH64_ADR_LO21_PCREL: - case BFD_RELOC_AARCH64_ADR_HI21_PCREL: - case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL: - 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: - if (info->shared + 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_LD_LO19_PCREL: + if (bfd_link_pic (info) && (input_section->flags & SEC_ALLOC) != 0 && (input_section->flags & SEC_READONLY) != 0 && h != NULL @@ -4815,7 +5304,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, { int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START; - (*_bfd_error_handler) + _bfd_error_handler (_("%B: relocation %s against external symbol `%s' can not be used" " when making a shared object; recompile with -fPIC"), input_bfd, elfNN_aarch64_howto_table[howto_index].name, @@ -4823,6 +5312,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, bfd_set_error (bfd_error_bad_value); return FALSE; } + /* Fall through. */ case BFD_RELOC_AARCH64_16: #if ARCH_SIZE == 64 @@ -4830,50 +5320,58 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, #endif case BFD_RELOC_AARCH64_ADD_LO12: case BFD_RELOC_AARCH64_BRANCH19: - case BFD_RELOC_AARCH64_LDST8_LO12: + 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_MOVW_G0_S: - case BFD_RELOC_AARCH64_MOVW_G1_S: - case BFD_RELOC_AARCH64_MOVW_G2_S: + case BFD_RELOC_AARCH64_LDST8_LO12: 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_TSTBR14: value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, signed_addend, weak_undef_p); break; - case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: - case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: case BFD_RELOC_AARCH64_ADR_GOT_PAGE: case BFD_RELOC_AARCH64_GOT_LD_PREL19: + case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14: + case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC: + case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15: + case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC: if (globals->root.sgot == NULL) BFD_ASSERT (h != NULL); if (h != NULL) { + bfd_vma addend = 0; value = aarch64_calculate_got_entry_vma (h, globals, info, value, output_bfd, unresolved_reloc_p); + if (bfd_r_type == BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15 + || bfd_r_type == BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14) + addend = (globals->root.sgot->output_section->vma + + globals->root.sgot->output_offset); value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, - 0, weak_undef_p); + addend, weak_undef_p); } else { + bfd_vma addend = 0; struct elf_aarch64_local_symbol *locals = elf_aarch64_locals (input_bfd); if (locals == NULL) { int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START; - (*_bfd_error_handler) + _bfd_error_handler (_("%B: Local symbol descriptor table be NULL when applying " "relocation %s against local symbol"), input_bfd, elfNN_aarch64_howto_table[howto_index].name); @@ -4889,43 +5387,119 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, { bfd_put_64 (output_bfd, value, base_got->contents + off); - if (info->shared) + if (bfd_link_pic (info)) { asection *s; Elf_Internal_Rela outrel; - /* For local symbol, we have done absolute relocation in static - linking stageh. While for share library, we need to update - the content of GOT entry according to the share objects - loading base address. So we need to generate a - R_AARCH64_RELATIVE reloc for dynamic linker. */ - s = globals->root.srelgot; - if (s == NULL) - abort (); + /* For local symbol, we have done absolute relocation in static + linking stageh. While for share library, we need to update + the content of GOT entry according to the share objects + loading base address. So we need to generate a + R_AARCH64_RELATIVE reloc for dynamic linker. */ + s = globals->root.srelgot; + if (s == NULL) + abort (); + + outrel.r_offset = got_entry_addr; + outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE)); + outrel.r_addend = value; + elf_append_rela (output_bfd, s, &outrel); + } + + symbol_got_offset_mark (input_bfd, h, r_symndx); + } + + /* Update the relocation value to GOT entry addr as we have transformed + the direct data access into indirect data access through GOT. */ + value = got_entry_addr; + + if (bfd_r_type == BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15 + || bfd_r_type == BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14) + addend = base_got->output_section->vma + base_got->output_offset; + + value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, + addend, weak_undef_p); + } + + break; + + case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: + if (h != NULL) + value = aarch64_calculate_got_entry_vma (h, globals, info, value, + output_bfd, + unresolved_reloc_p); + else + { + struct elf_aarch64_local_symbol *locals + = elf_aarch64_locals (input_bfd); + + if (locals == NULL) + { + int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START; + _bfd_error_handler + (_("%B: Local symbol descriptor table be NULL when applying " + "relocation %s against local symbol"), + input_bfd, elfNN_aarch64_howto_table[howto_index].name); + abort (); + } + + off = symbol_got_offset (input_bfd, h, r_symndx); + base_got = globals->root.sgot; + if (base_got == NULL) + abort (); + + bfd_vma got_entry_addr = (base_got->output_section->vma + + base_got->output_offset + off); - outrel.r_offset = got_entry_addr; - outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE)); - outrel.r_addend = value; - elf_append_rela (output_bfd, s, &outrel); - } + if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx)) + { + bfd_put_64 (output_bfd, value, base_got->contents + off); - symbol_got_offset_mark (input_bfd, h, r_symndx); - } + if (bfd_link_pic (info)) + { + asection *s; + Elf_Internal_Rela outrel; + + /* For local symbol, we have done absolute relocation in static + linking stage. While for share library, we need to update + the content of GOT entry according to the share objects + loading base address. So we need to generate a + R_AARCH64_RELATIVE reloc for dynamic linker. */ + s = globals->root.srelgot; + if (s == NULL) + abort (); + + outrel.r_offset = got_entry_addr; + outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE)); + outrel.r_addend = value; + elf_append_rela (output_bfd, s, &outrel); + } - /* Update the relocation value to GOT entry addr as we have transformed - the direct data access into indirect data access through GOT. */ - value = got_entry_addr; - } + symbol_got_offset_mark (input_bfd, h, r_symndx); + } + } + /* Update the relocation value to GOT entry addr as we have transformed + the direct data access into indirect data access through GOT. */ + value = symbol_got_offset (input_bfd, h, r_symndx); + value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, + 0, weak_undef_p); + *unresolved_reloc_p = FALSE; break; + case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: - case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: - case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC: + case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: + case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: if (globals->root.sgot == NULL) return bfd_reloc_notsupported; @@ -4938,6 +5512,40 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, *unresolved_reloc_p = FALSE; break; + 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: + if (globals->root.sgot == NULL) + return bfd_reloc_notsupported; + + value = symbol_got_offset (input_bfd, h, r_symndx); + value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, + 0, weak_undef_p); + *unresolved_reloc_p = FALSE; + break; + + 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 = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, + signed_addend - dtpoff_base (info), + weak_undef_p); + break; + 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: @@ -4952,13 +5560,11 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, *unresolved_reloc_p = FALSE; break; - case BFD_RELOC_AARCH64_TLSDESC_ADD: case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC: - case BFD_RELOC_AARCH64_TLSDESC_LDR: case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: if (globals->root.sgot == NULL) return bfd_reloc_notsupported; @@ -4972,6 +5578,24 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, *unresolved_reloc_p = FALSE; break; + case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G1: + if (globals->root.sgot == NULL) + return bfd_reloc_notsupported; + + value = (symbol_tlsdesc_got_offset (input_bfd, h, r_symndx) + + globals->root.sgotplt->output_section->vma + + globals->root.sgotplt->output_offset + + globals->sgotplt_jump_table_size); + + value -= (globals->root.sgot->output_section->vma + + globals->root.sgot->output_offset); + + value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value, + 0, weak_undef_p); + *unresolved_reloc_p = FALSE; + break; + default: return bfd_reloc_notsupported; } @@ -5008,8 +5632,8 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, switch (elfNN_aarch64_bfd_reloc_from_type (r_type)) { - case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: if (is_local) { /* GD->LE relaxation: @@ -5120,6 +5744,52 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, return bfd_reloc_continue; } +#if ARCH_SIZE == 64 + case BFD_RELOC_AARCH64_TLSGD_MOVW_G1: + BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (TLSGD_MOVW_G0_NC)); + BFD_ASSERT (rel->r_offset + 12 == rel[2].r_offset); + BFD_ASSERT (ELFNN_R_TYPE (rel[2].r_info) == AARCH64_R (CALL26)); + + if (is_local) + { + /* Large GD->LE relaxation: + movz x0, #:tlsgd_g1:var => movz x0, #:tprel_g2:var, lsl #32 + movk x0, #:tlsgd_g0_nc:var => movk x0, #:tprel_g1_nc:var, lsl #16 + add x0, gp, x0 => movk x0, #:tprel_g0_nc:var + bl __tls_get_addr => mrs x1, tpidr_el0 + nop => add x0, x0, x1 + */ + rel[2].r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info), + AARCH64_R (TLSLE_MOVW_TPREL_G0_NC)); + rel[2].r_offset = rel->r_offset + 8; + + bfd_putl32 (0xd2c00000, contents + rel->r_offset + 0); + bfd_putl32 (0xf2a00000, contents + rel->r_offset + 4); + bfd_putl32 (0xf2800000, contents + rel->r_offset + 8); + bfd_putl32 (0xd53bd041, contents + rel->r_offset + 12); + bfd_putl32 (0x8b000020, contents + rel->r_offset + 16); + } + else + { + /* Large GD->IE relaxation: + movz x0, #:tlsgd_g1:var => movz x0, #:gottprel_g1:var, lsl #16 + movk x0, #:tlsgd_g0_nc:var => movk x0, #:gottprel_g0_nc:var + add x0, gp, x0 => ldr x0, [gp, x0] + bl __tls_get_addr => mrs x1, tpidr_el0 + nop => add x0, x0, x1 + */ + rel[2].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE); + bfd_putl32 (0xd2a80000, contents + rel->r_offset + 0); + bfd_putl32 (0x58000000, contents + rel->r_offset + 8); + bfd_putl32 (0xd53bd041, contents + rel->r_offset + 12); + bfd_putl32 (0x8b000020, contents + rel->r_offset + 16); + } + return bfd_reloc_continue; + + case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC: + return bfd_reloc_continue; +#endif + case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: return bfd_reloc_continue; @@ -5185,6 +5855,7 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, return bfd_reloc_continue; } + case BFD_RELOC_AARCH64_TLSDESC_ADD: case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_CALL: /* GD->IE/LE relaxation: @@ -5194,6 +5865,55 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, bfd_putl32 (INSN_NOP, contents + rel->r_offset); return bfd_reloc_ok; + case BFD_RELOC_AARCH64_TLSDESC_LDR: + if (is_local) + { + /* GD->LE relaxation: + ldr xd, [gp, xn] => movk x0, #:tprel_g0_nc:var + */ + bfd_putl32 (0xf2800000, contents + rel->r_offset); + return bfd_reloc_continue; + } + else + { + /* GD->IE relaxation: + ldr xd, [gp, xn] => ldr x0, [gp, xn] + */ + insn = bfd_getl32 (contents + rel->r_offset); + insn &= 0xffffffe0; + bfd_putl32 (insn, contents + rel->r_offset); + return bfd_reloc_ok; + } + + case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC: + /* GD->LE relaxation: + movk xd, #:tlsdesc_off_g0_nc:var => movk x0, #:tprel_g1_nc:var, lsl #16 + GD->IE relaxation: + movk xd, #:tlsdesc_off_g0_nc:var => movk xd, #:gottprel_g0_nc:var + */ + if (is_local) + bfd_putl32 (0xf2a00000, contents + rel->r_offset); + return bfd_reloc_continue; + + case BFD_RELOC_AARCH64_TLSDESC_OFF_G1: + if (is_local) + { + /* GD->LE relaxation: + movz xd, #:tlsdesc_off_g1:var => movz x0, #:tprel_g2:var, lsl #32 + */ + bfd_putl32 (0xd2c00000, contents + rel->r_offset); + return bfd_reloc_continue; + } + else + { + /* GD->IE relaxation: + movz xd, #:tlsdesc_off_g1:var => movz xd, #:gottprel_g1:var, lsl #16 + */ + insn = bfd_getl32 (contents + rel->r_offset); + bfd_putl32 (0xd2a00000 | (insn & 0x1f), contents + rel->r_offset); + return bfd_reloc_continue; + } + case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: /* IE->LE relaxation: adrp xd, :gottprel:var => movz xd, :tprel_g1:var @@ -5216,6 +5936,51 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals, } return bfd_reloc_continue; + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: + /* LD->LE relaxation (tiny): + adr x0, :tlsldm:x => mrs x0, tpidr_el0 + bl __tls_get_addr => add x0, x0, TCB_SIZE + */ + if (is_local) + { + BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset); + BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26)); + /* No need of CALL26 relocation for tls_get_addr. */ + rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE); + bfd_putl32 (0xd53bd040, contents + rel->r_offset + 0); + bfd_putl32 (0x91004000, contents + rel->r_offset + 4); + return bfd_reloc_ok; + } + return bfd_reloc_continue; + + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + /* LD->LE relaxation (small): + adrp x0, :tlsldm:x => mrs x0, tpidr_el0 + */ + if (is_local) + { + bfd_putl32 (0xd53bd040, contents + rel->r_offset); + return bfd_reloc_ok; + } + return bfd_reloc_continue; + + case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: + /* LD->LE relaxation (small): + add x0, #:tlsldm_lo12:x => add x0, x0, TCB_SIZE + bl __tls_get_addr => nop + */ + if (is_local) + { + BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset); + BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (CALL26)); + /* No need of CALL26 relocation for tls_get_addr. */ + rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE); + bfd_putl32 (0x91004000, contents + rel->r_offset + 0); + bfd_putl32 (0xd503201f, contents + rel->r_offset + 4); + return bfd_reloc_ok; + } + return bfd_reloc_continue; + default: return bfd_reloc_continue; } @@ -5276,7 +6041,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, if (howto == NULL) { - (*_bfd_error_handler) + _bfd_error_handler (_("%B: unrecognized relocation (0x%x) in section `%A'"), input_bfd, input_section, r_type); return FALSE; @@ -5299,18 +6064,15 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, if (r_type != R_AARCH64_NONE && r_type != R_AARCH64_NULL && bfd_is_und_section (sec) && ELF_ST_BIND (sym->st_info) != STB_WEAK) - { - if (!info->callbacks->undefined_symbol - (info, bfd_elf_string_from_elf_section - (input_bfd, symtab_hdr->sh_link, sym->st_name), - input_bfd, input_section, rel->r_offset, TRUE)) - return FALSE; - } + (*info->callbacks->undefined_symbol) + (info, bfd_elf_string_from_elf_section + (input_bfd, symtab_hdr->sh_link, sym->st_name), + input_bfd, input_section, rel->r_offset, TRUE); relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); /* Relocate against local STT_GNU_IFUNC symbol. */ - if (!info->relocatable + if (!bfd_link_relocatable (info) && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) { h = elfNN_aarch64_get_local_sym_hash (globals, input_bfd, @@ -5339,7 +6101,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel, 1, relend, howto, 0, contents); - if (info->relocatable) + if (bfd_link_relocatable (info)) continue; if (h != NULL) @@ -5360,7 +6122,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, || h->root.type == bfd_link_hash_defweak) && IS_AARCH64_TLS_RELOC (bfd_r_type) != (sym_type == STT_TLS)) { - (*_bfd_error_handler) + _bfd_error_handler ((sym_type == STT_TLS ? _("%B(%A+0x%lx): %s used with TLS symbol %s") : _("%B(%A+0x%lx): %s used with non-TLS symbol %s")), @@ -5407,9 +6169,14 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, switch (elfNN_aarch64_bfd_reloc_from_type (r_type)) { + case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: - case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G1: + case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: if (! symbol_got_offset_mark_p (input_bfd, h, r_symndx)) { bfd_boolean need_relocs = FALSE; @@ -5421,7 +6188,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, indx = h && h->dynindx != -1 ? h->dynindx : 0; need_relocs = - (info->shared || indx != 0) && + (bfd_link_pic (info) || indx != 0) && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak); @@ -5442,7 +6209,21 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, * RELOC_SIZE (htab); bfd_elfNN_swap_reloca_out (output_bfd, &rela, loc); - if (indx == 0) + bfd_reloc_code_real_type real_type = + elfNN_aarch64_bfd_reloc_from_type (r_type); + + if (real_type == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21 + || real_type == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21 + || real_type == BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC) + { + /* For local dynamic, don't generate DTPREL in any case. + Initialize the DTPREL slot into zero, so we get module + base address when invoke runtime TLS resolver. */ + bfd_put_NN (output_bfd, 0, + globals->root.sgot->contents + off + + GOT_ENTRY_SIZE); + } + else if (indx == 0) { bfd_put_NN (output_bfd, relocation - dtpoff_base (info), @@ -5488,6 +6269,8 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: case BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1: if (! symbol_got_offset_mark_p (input_bfd, h, r_symndx)) { bfd_boolean need_relocs = FALSE; @@ -5500,7 +6283,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, indx = h && h->dynindx != -1 ? h->dynindx : 0; need_relocs = - (info->shared || indx != 0) && + (bfd_link_pic (info) || indx != 0) && (h == NULL || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak); @@ -5537,21 +6320,13 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, } break; - case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12: - case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12: - case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC: - break; - case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G1: if (! symbol_tlsdesc_got_offset_mark_p (input_bfd, h, r_symndx)) { bfd_boolean need_relocs = FALSE; @@ -5609,10 +6384,6 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, break; } - if (!save_addend) - addend = 0; - - /* Dynamic relocs are not propagated for SEC_DEBUGGING sections because such sections are not SEC_ALLOC and thus ld.so will not process them. */ @@ -5622,7 +6393,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, && _bfd_elf_section_offset (output_bfd, info, input_section, +rel->r_offset) != (bfd_vma) - 1) { - (*_bfd_error_handler) + _bfd_error_handler (_ ("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), input_bfd, input_section, (long) rel->r_offset, howto->name, @@ -5632,20 +6403,58 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, if (r != bfd_reloc_ok && r != bfd_reloc_continue) { + bfd_reloc_code_real_type real_r_type + = elfNN_aarch64_bfd_reloc_from_type (r_type); + switch (r) { case bfd_reloc_overflow: - if (!(*info->callbacks->reloc_overflow) - (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, - input_bfd, input_section, rel->r_offset)) - return FALSE; + (*info->callbacks->reloc_overflow) + (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, + input_bfd, input_section, rel->r_offset); + if (real_r_type == BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15 + || real_r_type == BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14) + { + (*info->callbacks->warning) + (info, + _("Too many GOT entries for -fpic, " + "please recompile with -fPIC"), + name, input_bfd, input_section, rel->r_offset); + return FALSE; + } + /* Overflow can occur when a variable is referenced with a type + that has a larger alignment than the type with which it was + declared. eg: + file1.c: extern int foo; int a (void) { return foo; } + file2.c: char bar, foo, baz; + If the variable is placed into a data section at an offset + that is incompatible with the larger alignment requirement + overflow will occur. (Strictly speaking this is not overflow + but rather an alignment problem, but the bfd_reloc_ error + enum does not have a value to cover that situation). + + Try to catch this situation here and provide a more helpful + error message to the user. */ + if (addend & ((1 << howto->rightshift) - 1) + /* FIXME: Are we testing all of the appropriate reloc + types here ? */ + && (real_r_type == BFD_RELOC_AARCH64_LD_LO19_PCREL + || real_r_type == BFD_RELOC_AARCH64_LDST16_LO12 + || real_r_type == BFD_RELOC_AARCH64_LDST32_LO12 + || real_r_type == BFD_RELOC_AARCH64_LDST64_LO12 + || real_r_type == BFD_RELOC_AARCH64_LDST128_LO12)) + { + info->callbacks->warning + (info, _("One possible cause of this error is that the \ +symbol is being referenced in the indicated code as if it had a larger \ +alignment than was declared where it was defined."), + name, input_bfd, input_section, rel->r_offset); + } break; case bfd_reloc_undefined: - if (!((*info->callbacks->undefined_symbol) - (info, name, input_bfd, input_section, - rel->r_offset, TRUE))) - return FALSE; + (*info->callbacks->undefined_symbol) + (info, name, input_bfd, input_section, rel->r_offset, TRUE); break; case bfd_reloc_outofrange: @@ -5666,13 +6475,14 @@ elfNN_aarch64_relocate_section (bfd *output_bfd, common_error: BFD_ASSERT (error_message != NULL); - if (!((*info->callbacks->reloc_dangerous) - (info, error_message, input_bfd, input_section, - rel->r_offset))) - return FALSE; + (*info->callbacks->reloc_dangerous) + (info, error_message, input_bfd, input_section, rel->r_offset); break; } } + + if (!save_addend) + addend = 0; } return TRUE; @@ -5712,15 +6522,16 @@ elfNN_aarch64_set_private_flags (bfd *abfd, flagword flags) object file when linking. */ static bfd_boolean -elfNN_aarch64_merge_private_bfd_data (bfd *ibfd, bfd *obfd) +elfNN_aarch64_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { + bfd *obfd = info->output_bfd; flagword out_flags; flagword in_flags; bfd_boolean flags_compatible = TRUE; asection *sec; /* Check if we have the same endianess. */ - if (!_bfd_generic_verify_endian_match (ibfd, obfd)) + if (!_bfd_generic_verify_endian_match (ibfd, info)) return FALSE; if (!is_aarch64_elf (ibfd) || !is_aarch64_elf (obfd)) @@ -5837,7 +6648,7 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd, struct elf_aarch64_local_symbol *locals; const Elf_Internal_Rela *rel, *relend; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; htab = elf_aarch64_hash_table (info); @@ -5909,29 +6720,35 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd, { case BFD_RELOC_AARCH64_ADR_GOT_PAGE: case BFD_RELOC_AARCH64_GOT_LD_PREL19: + 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_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G1: case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G1: case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: - 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_TLSLE_MOVW_TPREL_G0: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1: + case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: if (h != NULL) { if (h->got.refcount > 0) @@ -5961,15 +6778,15 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd, h->plt.refcount -= 1; break; + 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_MOVW_G0_NC: case BFD_RELOC_AARCH64_MOVW_G1_NC: case BFD_RELOC_AARCH64_MOVW_G2_NC: case BFD_RELOC_AARCH64_MOVW_G3: - 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_NN: - if (h != NULL && info->executable) + if (h != NULL && bfd_link_executable (info)) { if (h->plt.refcount > 0) h->plt.refcount -= 1; @@ -6042,7 +6859,7 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info, only references to the symbol are via the global offset table. For such cases we need not do anything here; the relocations will be handled correctly by relocate_section. */ - if (info->shared) + if (bfd_link_pic (info)) return TRUE; /* If there are no references to this symbol that do not use the @@ -6178,7 +6995,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, struct elf_aarch64_link_hash_table *htab; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; BFD_ASSERT (is_aarch64_elf (abfd)); @@ -6203,8 +7020,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr)) { - (*_bfd_error_handler) (_("%B: bad symbol index: %d"), abfd, - r_symndx); + _bfd_error_handler (_("%B: bad symbol index: %d"), abfd, r_symndx); return FALSE; } @@ -6251,6 +7067,22 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, if (h != NULL) { + /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got. + This shows up in particular in an R_AARCH64_PREL64 in large model + when calculating the pc-relative address to .got section which is + used to initialize the gp register. */ + if (h->root.root.string + && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) + { + if (htab->root.dynobj == NULL) + htab->root.dynobj = abfd; + + if (! aarch64_elf_create_got_section (htab->root.dynobj, info)) + return FALSE; + + BFD_ASSERT (h == htab->root.hgot); + } + /* Create the ifunc sections for static executables. If we never see an indirect function symbol nor we are building a static executable, those sections will be empty and @@ -6260,15 +7092,20 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, default: break; - case BFD_RELOC_AARCH64_NN: + case BFD_RELOC_AARCH64_ADD_LO12: + case BFD_RELOC_AARCH64_ADR_GOT_PAGE: + case BFD_RELOC_AARCH64_ADR_HI21_PCREL: case BFD_RELOC_AARCH64_CALL26: + case BFD_RELOC_AARCH64_GOT_LD_PREL19: case BFD_RELOC_AARCH64_JUMP26: + 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_ADR_GOT_PAGE: - case BFD_RELOC_AARCH64_GOT_LD_PREL19: - case BFD_RELOC_AARCH64_ADR_HI21_PCREL: - case BFD_RELOC_AARCH64_ADD_LO12: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: + case BFD_RELOC_AARCH64_NN: if (htab->root.dynobj == NULL) htab->root.dynobj = abfd; if (!_bfd_elf_create_ifunc_sections (htab->root.dynobj, info)) @@ -6292,7 +7129,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, if (h != NULL) { - if (!info->shared) + if (!bfd_link_pic (info)) h->non_got_ref = 1; h->plt.refcount += 1; @@ -6301,7 +7138,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, /* No need to do anything if we're not creating a shared object. */ - if (! info->shared) + if (! bfd_link_pic (info)) break; { @@ -6377,26 +7214,35 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, there are no dangling GOT_PAGE relocs. */ case BFD_RELOC_AARCH64_ADR_GOT_PAGE: case BFD_RELOC_AARCH64_GOT_LD_PREL19: + 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_MOVW_GOTOFF_G0_NC: + case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1: case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21: case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC: case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC: + case BFD_RELOC_AARCH64_TLSDESC_OFF_G1: case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC: case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21: case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC: + case BFD_RELOC_AARCH64_TLSGD_MOVW_G1: case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19: - 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_TLSLE_MOVW_TPREL_G0: - case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC: + case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1: + case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC: + case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21: + case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21: case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1: case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC: case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2: @@ -6468,10 +7314,10 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, case BFD_RELOC_AARCH64_MOVW_G1_NC: case BFD_RELOC_AARCH64_MOVW_G2_NC: case BFD_RELOC_AARCH64_MOVW_G3: - if (info->shared) + if (bfd_link_pic (info)) { int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START; - (*_bfd_error_handler) + _bfd_error_handler (_("%B: relocation %s against `%s' can not be used when making " "a shared object; recompile with -fPIC"), abfd, elfNN_aarch64_howto_table[howto_index].name, @@ -6479,11 +7325,12 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, bfd_set_error (bfd_error_bad_value); return FALSE; } + /* Fall through. */ case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL: case BFD_RELOC_AARCH64_ADR_HI21_PCREL: case BFD_RELOC_AARCH64_ADR_LO21_PCREL: - if (h != NULL && info->executable) + if (h != NULL && bfd_link_executable (info)) { /* If this reloc is in a read-only section, we might need a copy reloc. We can't check reliably at this @@ -6841,38 +7688,6 @@ elfNN_aarch64_output_map_sym (output_arch_syminfo *osi, return osi->func (osi->finfo, names[type], &sym, osi->sec, NULL) == 1; } - - -/* Output mapping symbols for PLT entries associated with H. */ - -static bfd_boolean -elfNN_aarch64_output_plt_map (struct elf_link_hash_entry *h, void *inf) -{ - output_arch_syminfo *osi = (output_arch_syminfo *) inf; - bfd_vma addr; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - - if (h->root.type == bfd_link_hash_warning) - /* When warning symbols are created, they **replace** the "real" - entry in the hash table, thus we never get to see the real - symbol in a hash traversal. So look at it now. */ - h = (struct elf_link_hash_entry *) h->root.u.i.link; - - if (h->plt.offset == (bfd_vma) - 1) - return TRUE; - - addr = h->plt.offset; - if (addr == 32) - { - if (!elfNN_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr)) - return FALSE; - } - return TRUE; -} - - /* Output a single local symbol for a generated stub. */ static bfd_boolean @@ -7005,13 +7820,11 @@ elfNN_aarch64_output_arch_local_syms (bfd *output_bfd, if (!htab->root.splt || htab->root.splt->size == 0) return TRUE; - /* For now live without mapping symbols for the plt. */ osi.sec_shndx = _bfd_elf_section_from_bfd_section (output_bfd, htab->root.splt->output_section); osi.sec = htab->root.splt; - elf_link_hash_traverse (&htab->root, elfNN_aarch64_output_plt_map, - (void *) &osi); + elfNN_aarch64_output_map_sym (&osi, AARCH64_MAP_INSN, 0); return TRUE; @@ -7086,10 +7899,10 @@ elfNN_aarch64_create_dynamic_sections (bfd *dynobj, htab = elf_aarch64_hash_table (info); htab->sdynbss = bfd_get_linker_section (dynobj, ".dynbss"); - if (!info->shared) + if (!bfd_link_pic (info)) htab->srelbss = bfd_get_linker_section (dynobj, ".rela.bss"); - if (!htab->sdynbss || (!info->shared && !htab->srelbss)) + if (!htab->sdynbss || (!bfd_link_pic (info) && !htab->srelbss)) abort (); return TRUE; @@ -7141,7 +7954,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) return FALSE; } - if (info->shared || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) + if (bfd_link_pic (info) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) { asection *s = htab->root.splt; @@ -7157,7 +7970,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) location in the .plt. This is required to make function pointers compare as equal between the normal executable and the shared library. */ - if (!info->shared && !h->def_regular) + if (!bfd_link_pic (info) && !h->def_regular) { h->root.u.def.section = s; h->root.u.def.value = h->plt.offset; @@ -7231,7 +8044,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) htab->root.sgot->size += GOT_ENTRY_SIZE; if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) - && (info->shared + && (bfd_link_pic (info) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) { htab->root.srelgot->size += RELOC_SIZE (htab); @@ -7264,7 +8077,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) indx = h && h->dynindx != -1 ? h->dynindx : 0; if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT || h->root.type != bfd_link_hash_undefweak) - && (info->shared + && (bfd_link_pic (info) || indx != 0 || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))) { @@ -7301,7 +8114,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) space for pc-relative relocs that have become local due to symbol visibility changes. */ - if (info->shared) + if (bfd_link_pic (info)) { /* Relocs that use pc_count are those that appear on a call insn, or certain REL relocs that can generated via assembly. @@ -7424,9 +8237,11 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, && h->def_regular) return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, + NULL, htab->plt_entry_size, htab->plt_header_size, - GOT_ENTRY_SIZE); + GOT_ENTRY_SIZE, + FALSE); return TRUE; } @@ -7468,6 +8283,32 @@ elfNN_aarch64_allocate_local_ifunc_dynrelocs (void **slot, void *inf) return elfNN_aarch64_allocate_ifunc_dynrelocs (h, inf); } +/* Find any dynamic relocs that apply to read-only sections. */ + +static bfd_boolean +aarch64_readonly_dynrelocs (struct elf_link_hash_entry * h, void * inf) +{ + struct elf_aarch64_link_hash_entry * eh; + struct elf_dyn_relocs * p; + + eh = (struct elf_aarch64_link_hash_entry *) h; + for (p = eh->dyn_relocs; p != NULL; p = p->next) + { + asection *s = p->sec; + + if (s != NULL && (s->flags & SEC_READONLY) != 0) + { + struct bfd_link_info *info = (struct bfd_link_info *) inf; + + info->flags |= DF_TEXTREL; + + /* Not an error, just cut short the traversal. */ + return FALSE; + } + } + return TRUE; +} + /* This is the most important function of all . Innocuosly named though ! */ static bfd_boolean @@ -7487,7 +8328,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (htab->root.dynamic_sections_created) { - if (info->executable) + if (bfd_link_executable (info) && !info->nointerp) { s = bfd_get_linker_section (dynobj, ".interp"); if (s == NULL) @@ -7573,7 +8414,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { } - if (info->shared) + if (bfd_link_pic (info)) { if (got_type & GOT_TLSDESC_GD) { @@ -7726,7 +8567,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, #define add_dynamic_entry(TAG, VAL) \ _bfd_elf_add_dynamic_entry (info, TAG, VAL) - if (info->executable) + if (bfd_link_executable (info)) { if (!add_dynamic_entry (DT_DEBUG, 0)) return FALSE; @@ -7755,6 +8596,10 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* If any dynamic relocs apply to a read-only section, then we need a DT_TEXTREL entry. */ + if ((info->flags & DF_TEXTREL) == 0) + elf_link_hash_traverse (& htab->root, aarch64_readonly_dynrelocs, + info); + if ((info->flags & DF_TEXTREL) != 0) { if (!add_dynamic_entry (DT_TEXTREL, 0)) @@ -7863,7 +8708,7 @@ elfNN_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h, rela.r_offset = gotplt_entry_address; if (h->dynindx == -1 - || ((info->executable + || ((bfd_link_executable (info) || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) && h->def_regular && h->type == STT_GNU_IFUNC)) @@ -7898,7 +8743,7 @@ elfNN_aarch64_always_size_sections (bfd *output_bfd, { asection *tls_sec; - if (info->relocatable) + if (bfd_link_relocatable (info)) return TRUE; tls_sec = elf_hash_table (info)->tls_sec; @@ -7968,7 +8813,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, /* This symbol has an entry in the procedure linkage table. Set it up. */ if ((h->dynindx == -1 - && !((h->forced_local || info->executable) + && !((h->forced_local || bfd_link_executable (info)) && h->def_regular && h->type == STT_GNU_IFUNC)) || plt == NULL @@ -8013,7 +8858,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, if (h->def_regular && h->type == STT_GNU_IFUNC) { - if (info->shared) + if (bfd_link_pic (info)) { /* Generate R_AARCH64_GLOB_DAT. */ goto do_glob_dat; @@ -8037,7 +8882,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, return TRUE; } } - else if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h)) + else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) { if (!h->def_regular) return FALSE; @@ -8201,7 +9046,8 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, break; case DT_JMPREL: - dyn.d_un.d_ptr = htab->root.srelplt->output_section->vma; + s = htab->root.srelplt; + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; break; case DT_PLTRELSZ: @@ -8313,7 +9159,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, { if (bfd_is_abs_section (htab->root.sgotplt->output_section)) { - (*_bfd_error_handler) + _bfd_error_handler (_("discarded output section: `%A'"), htab->root.sgotplt); return FALSE; } @@ -8368,6 +9214,40 @@ elfNN_aarch64_plt_sym_val (bfd_vma i, const asection *plt, return plt->vma + PLT_ENTRY_SIZE + i * PLT_SMALL_ENTRY_SIZE; } +/* Returns TRUE if NAME is an AArch64 mapping symbol. + The ARM ELF standard defines $x (for A64 code) and $d (for data). + It also allows a period initiated suffix to be added to the symbol, ie: + "$[adtx]\.[:sym_char]+". */ + +static bfd_boolean +is_aarch64_mapping_symbol (const char * name) +{ + return name != NULL /* Paranoia. */ + && name[0] == '$' /* Note: if objcopy --prefix-symbols has been used then + the mapping symbols could have acquired a prefix. + We do not support this here, since such symbols no + longer conform to the ARM ELF ABI. */ + && (name[1] == 'd' || name[1] == 'x') + && (name[2] == 0 || name[2] == '.'); + /* FIXME: Strictly speaking the symbol is only a valid mapping symbol if + any characters that follow the period are legal characters for the body + of a symbol's name. For now we just assume that this is the case. */ +} + +/* Make sure that mapping symbols in object files are not removed via the + "strip --strip-unneeded" tool. These symbols might needed in order to + correctly generate linked files. Once an object file has been linked, + it should be safe to remove them. */ + +static void +elfNN_aarch64_backend_symbol_processing (bfd *abfd, asymbol *sym) +{ + if (((abfd->flags & (EXEC_P | DYNAMIC)) == 0) + && sym->section != bfd_abs_section_ptr + && is_aarch64_mapping_symbol (sym->name)) + sym->flags |= BSF_KEEP; +} + /* We use this so we can override certain functions (though currently we don't). */ @@ -8507,6 +9387,9 @@ const struct elf_size_info elfNN_aarch64_size_info = #define elf_backend_write_section \ elfNN_aarch64_write_section +#define elf_backend_symbol_processing \ + elfNN_aarch64_backend_symbol_processing + #define elf_backend_can_refcount 1 #define elf_backend_can_gc_sections 1 #define elf_backend_plt_readonly 1 @@ -8518,8 +9401,28 @@ const struct elf_size_info elfNN_aarch64_size_info = #define elf_backend_rela_normal 1 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 3) #define elf_backend_default_execstack 0 +#define elf_backend_extern_protected_data 1 #undef elf_backend_obj_attrs_section #define elf_backend_obj_attrs_section ".ARM.attributes" #include "elfNN-target.h" + +/* CloudABI support. */ + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM aarch64_elfNN_le_cloudabi_vec +#undef TARGET_LITTLE_NAME +#define TARGET_LITTLE_NAME "elfNN-littleaarch64-cloudabi" +#undef TARGET_BIG_SYM +#define TARGET_BIG_SYM aarch64_elfNN_be_cloudabi_vec +#undef TARGET_BIG_NAME +#define TARGET_BIG_NAME "elfNN-bigaarch64-cloudabi" + +#undef ELF_OSABI +#define ELF_OSABI ELFOSABI_CLOUDABI + +#undef elfNN_bed +#define elfNN_bed elfNN_aarch64_cloudabi_bed + +#include "elfNN-target.h"