|| (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_LDST16_TPREL_LO12 \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12 \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12 \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12 \
+ || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_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 \
0xfff, /* dst_mask */
FALSE), /* pcrel_offset */
+ /* LD/ST16: bit[11:1] of byte offset to module TLS base address. */
+ HOWTO (AARCH64_R (TLSLE_LDST16_TPREL_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 (TLSLE_LDST16_TPREL_LO12), /* name */
+ FALSE, /* partial_inplace */
+ 0x1ffc00, /* src_mask */
+ 0x1ffc00, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Same as BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12, but no overflow check. */
+ HOWTO (AARCH64_R (TLSLE_LDST16_TPREL_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 (TLSLE_LDST16_TPREL_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. */
+ HOWTO (AARCH64_R (TLSLE_LDST32_TPREL_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 (TLSLE_LDST32_TPREL_LO12), /* name */
+ FALSE, /* partial_inplace */
+ 0xffc00, /* src_mask */
+ 0xffc00, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Same as BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12, but no overflow check. */
+ HOWTO (AARCH64_R (TLSLE_LDST32_TPREL_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 (TLSLE_LDST32_TPREL_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. */
+ HOWTO (AARCH64_R (TLSLE_LDST64_TPREL_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 (TLSLE_LDST64_TPREL_LO12), /* name */
+ FALSE, /* partial_inplace */
+ 0x7fc00, /* src_mask */
+ 0x7fc00, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Same as BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12, but no overflow check. */
+ HOWTO (AARCH64_R (TLSLE_LDST64_TPREL_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 (TLSLE_LDST64_TPREL_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. */
+ HOWTO (AARCH64_R (TLSLE_LDST8_TPREL_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 (TLSLE_LDST8_TPREL_LO12), /* name */
+ FALSE, /* partial_inplace */
+ 0x3ffc00, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* Same as BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12, but no overflow check. */
+ HOWTO (AARCH64_R (TLSLE_LDST8_TPREL_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 (TLSLE_LDST8_TPREL_LO12_NC), /* name */
+ FALSE, /* partial_inplace */
+ 0x3ffc00, /* src_mask */
+ 0x3ffc00, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
HOWTO (AARCH64_R (TLSDESC_LD_PREL19), /* type */
2, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
/* 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)
+elfNN_aarch64_bfd_reloc_from_type (bfd *abfd, unsigned int r_type)
{
static bfd_boolean initialized_p = FALSE;
/* Indexed by R_TYPE, values are offsets in the howto_table. */
/* PR 17512: file: b371e70a. */
if (r_type >= R_AARCH64_end)
{
- _bfd_error_handler (_("Invalid AArch64 reloc number: %d"), r_type);
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, r_type);
bfd_set_error (bfd_error_bad_value);
return BFD_RELOC_AARCH64_NONE;
}
}
static reloc_howto_type *
-elfNN_aarch64_howto_from_type (unsigned int r_type)
+elfNN_aarch64_howto_from_type (bfd *abfd, unsigned int r_type)
{
bfd_reloc_code_real_type val;
reloc_howto_type *howto;
if (r_type == R_AARCH64_NONE)
return &elfNN_aarch64_howto_none;
- val = elfNN_aarch64_bfd_reloc_from_type (r_type);
+ val = elfNN_aarch64_bfd_reloc_from_type (abfd, r_type);
howto = elfNN_aarch64_howto_from_bfd_reloc (val);
if (howto != NULL)
return NULL;
}
-static void
-elfNN_aarch64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
+static bfd_boolean
+elfNN_aarch64_info_to_howto (bfd *abfd, 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);
+ bfd_reloc->howto = elfNN_aarch64_howto_from_type (abfd, r_type);
+
+ if (bfd_reloc->howto == NULL)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type);
+ return FALSE;
+ }
+ return TRUE;
}
static reloc_howto_type *
reloc_howto_type *howto;
bfd_vma place;
- howto = elfNN_aarch64_howto_from_type (r_type);
+ howto = elfNN_aarch64_howto_from_type (input_bfd, r_type);
place = (input_section->output_section->vma + input_section->output_offset
+ offset);
- r_type = elfNN_aarch64_bfd_reloc_from_type (r_type);
+ r_type = elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
value = _bfd_aarch64_elf_resolve_relocation (r_type, place, value, 0, FALSE);
return _bfd_aarch64_elf_put_addend (input_bfd,
input_section->contents + offset, r_type,
if (!strstr (section->name, STUB_SUFFIX))
continue;
+ /* Add space for a branch. Add 8 bytes to keep section 8 byte aligned,
+ as long branch stubs contain a 64-bit address. */
if (section->size)
- section->size += 4;
+ section->size += 8;
/* Ensure all stub sections have a size which is a multiple of
4096. This is important in order to ensure that the insertion
}
}
-
-/* Construct an erratum 843419 workaround stub name.
- */
+/* Construct an erratum 843419 workaround stub name. */
static char *
_bfd_aarch64_erratum_843419_stub_name (asection *input_section,
return FALSE;
stub_sec->size = 0;
+ /* Add a branch around the stub section, and a nop, to keep it 8 byte
+ aligned, as long branch stubs contain a 64-bit address. */
bfd_putl32 (0x14000000 | (size >> 2), stub_sec->contents);
- stub_sec->size += 4;
+ bfd_putl32 (INSN_NOP, stub_sec->contents + 4);
+ stub_sec->size += 8;
}
/* Build the stubs as directed by the stub hash table. */
unsigned long r_symndx)
{
bfd_reloc_code_real_type bfd_r_type
- = elfNN_aarch64_bfd_reloc_from_type (r_type);
+ = elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
if (! aarch64_can_relax_tls (input_bfd, info, bfd_r_type, h, r_symndx))
return bfd_r_type;
abfd = stub_entry->target_section->owner;
if (!aarch64_valid_branch_p (veneer_entry_loc, veneered_insn_loc))
_bfd_error_handler
- (_("%pB: error: Erratum 835769 stub out "
+ (_("%pB: error: erratum 835769 stub out "
"of range (input file too large)"), abfd);
target = stub_entry->target_value;
abfd = stub_entry->target_section->owner;
if (!aarch64_valid_branch_p (veneer_entry_loc, veneered_insn_loc))
_bfd_error_handler
- (_("%pB: error: Erratum 843419 stub out "
+ (_("%pB: error: erratum 843419 stub out "
"of range (input file too large)"), abfd);
branch_insn = 0x14000000;
asection *base_got;
bfd_vma orig_value = value;
bfd_boolean resolved_to_zero;
+ bfd_boolean abs_symbol_p;
globals = elf_aarch64_hash_table (info);
weak_undef_p = (h ? h->root.type == bfd_link_hash_undefweak
: bfd_is_und_section (sym_sec));
+ abs_symbol_p = (h !=NULL && h->root.type == bfd_link_hash_defined
+ && bfd_is_abs_section (h->root.u.def.section));
+
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle
it here if it is defined in a non-shared object. */
if ((input_section->flags & SEC_ALLOC) == 0)
{
+ /* If this is a SHT_NOTE section without SHF_ALLOC, treat
+ STT_GNU_IFUNC symbol as STT_FUNC. */
+ if (elf_section_type (input_section) == SHT_NOTE)
+ goto skip_ifunc;
+
/* Dynamic relocs are not propagated for SEC_DEBUGGING
sections because such sections are not SEC_ALLOC and
thus ld.so will not process them. */
}
}
+ skip_ifunc:
resolved_to_zero = (h != NULL
&& UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
skip = TRUE;
relocate = TRUE;
}
+ else if (abs_symbol_p)
+ {
+ /* Local absolute symbol. */
+ skip = (h->forced_local || (h->dynindx == -1));
+ relocate = skip;
+ }
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
else if (h != NULL
&& h->dynindx != -1
&& (!bfd_link_pic (info)
- || !(bfd_link_pie (info)
- || SYMBOLIC_BIND (info, h))
+ || !(bfd_link_pie (info) || SYMBOLIC_BIND (info, h))
|| !h->def_regular))
outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
else
int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
_bfd_error_handler
/* xgettext:c-format */
- (_("%pB: Local symbol descriptor table be NULL when applying "
+ (_("%pB: local symbol descriptor table be NULL when applying "
"relocation %s against local symbol"),
input_bfd, elfNN_aarch64_howto_table[howto_index].name);
abort ();
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_LDST16_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_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:
BFD_ASSERT (globals && input_bfd && contents && rel);
- switch (elfNN_aarch64_bfd_reloc_from_type (r_type))
+ switch (elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type))
{
case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
r_symndx = ELFNN_R_SYM (rel->r_info);
r_type = ELFNN_R_TYPE (rel->r_info);
- howto = bfd_reloc.howto = elfNN_aarch64_howto_from_type (r_type);
+ bfd_reloc.howto = elfNN_aarch64_howto_from_type (input_bfd, r_type);
+ howto = bfd_reloc.howto;
if (howto == NULL)
return _bfd_unrecognized_reloc (input_bfd, input_section, r_type);
h, &unresolved_reloc,
save_addend, &addend, sym);
- switch (elfNN_aarch64_bfd_reloc_from_type (r_type))
+ switch (elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type))
{
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
bfd_elfNN_swap_reloca_out (output_bfd, &rela, loc);
bfd_reloc_code_real_type real_type =
- elfNN_aarch64_bfd_reloc_from_type (r_type);
+ elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
if (real_type == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21
|| real_type == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21
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);
+ = elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
switch (r)
{
{
(*info->callbacks->warning)
(info,
- _("Too many GOT entries for -fpic, "
+ _("too many GOT entries for -fpic, "
"please recompile with -fPIC"),
name, input_bfd, input_section, rel->r_offset);
return FALSE;
|| real_r_type == BFD_RELOC_AARCH64_LDST128_LO12))
{
info->callbacks->warning
- (info, _("One possible cause of this error is that the \
+ (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."),
+alignment than was declared where it was defined"),
name, input_bfd, input_section, rel->r_offset);
}
break;