return &ret->root.root;
}
+/* Perform relocation R_TYPE. Returns TRUE upon success, FALSE otherwise. */
+
static bfd_boolean
aarch64_relocate (unsigned int r_type, bfd *input_bfd, asection *input_section,
bfd_vma offset, bfd_vma value)
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,
- howto, value);
+ howto, value) == bfd_reloc_ok;
}
static enum elf_aarch64_stub_type
switch (stub_entry->stub_type)
{
case aarch64_stub_adrp_branch:
- if (aarch64_relocate (AARCH64_R (ADR_PREL_PG_HI21), stub_bfd, stub_sec,
- stub_entry->stub_offset, sym_value))
+ if (!aarch64_relocate (AARCH64_R (ADR_PREL_PG_HI21), stub_bfd, stub_sec,
+ stub_entry->stub_offset, sym_value))
/* The stub would not have been relaxed if the offset was out
of range. */
BFD_FAIL ();
- if (aarch64_relocate (AARCH64_R (ADD_ABS_LO12_NC), stub_bfd, stub_sec,
- stub_entry->stub_offset + 4, sym_value))
+ if (!aarch64_relocate (AARCH64_R (ADD_ABS_LO12_NC), stub_bfd, stub_sec,
+ stub_entry->stub_offset + 4, sym_value))
BFD_FAIL ();
break;
case aarch64_stub_long_branch:
/* We want the value relative to the address 12 bytes back from the
value itself. */
- if (aarch64_relocate (AARCH64_R (PRELNN), stub_bfd, stub_sec,
- stub_entry->stub_offset + 16, sym_value + 12))
+ if (!aarch64_relocate (AARCH64_R (PRELNN), stub_bfd, stub_sec,
+ stub_entry->stub_offset + 16, sym_value + 12))
BFD_FAIL ();
break;
break;
case aarch64_stub_erratum_843419_veneer:
- if (aarch64_relocate (AARCH64_R (JUMP26), stub_bfd, stub_sec,
- stub_entry->stub_offset + 4, sym_value + 4))
+ if (!aarch64_relocate (AARCH64_R (JUMP26), stub_bfd, stub_sec,
+ stub_entry->stub_offset + 4, sym_value + 4))
BFD_FAIL ();
break;
uint32_t v = 0;
uint32_t opc_v = 0;
- /* Bail out quickly if INSN doesn't fall into the the load-store
+ /* Bail out quickly if INSN doesn't fall into the load-store
encoding space. */
if (!AARCH64_LDST (insn))
return FALSE;
return FALSE;
}
+/* Return TRUE if RELOC is a relocation against the base of GOT table. */
+
+static bfd_boolean
+aarch64_relocation_aginst_gp_p (bfd_reloc_code_real_type reloc)
+{
+ return (reloc == BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14
+ || reloc == BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15
+ || reloc == BFD_RELOC_AARCH64_LD64_GOTOFF_LO15
+ || reloc == BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC
+ || reloc == BFD_RELOC_AARCH64_MOVW_GOTOFF_G1);
+}
+
/* Perform a relocation as part of a final link. The input relocation type
should be TLS relaxed. */
= elfNN_aarch64_bfd_reloc_from_howto (howto);
unsigned long r_symndx;
bfd_byte *hit_data = contents + rel->r_offset;
- bfd_vma place, off;
+ bfd_vma place, off, got_entry_addr = 0;
bfd_signed_vma signed_addend;
struct elf_aarch64_link_hash_table *globals;
bfd_boolean weak_undef_p;
+ bfd_boolean relative_reloc;
asection *base_got;
+ bfd_vma orig_value = value;
+ bfd_boolean resolved_to_zero;
globals = elf_aarch64_hash_table (info);
const char *name;
bfd_vma addend = 0;
- if ((input_section->flags & SEC_ALLOC) == 0
- || h->plt.offset == (bfd_vma) -1)
- abort ();
+ if ((input_section->flags & SEC_ALLOC) == 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. */
+ if ((input_section->flags & SEC_DEBUGGING) != 0)
+ return bfd_reloc_ok;
+
+ if (h->root.root.string)
+ name = h->root.root.string;
+ else
+ name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, NULL);
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
+ input_bfd, input_section, rel->r_offset, howto->name, name);
+ bfd_set_error (bfd_error_bad_value);
+ return bfd_reloc_notsupported;
+ }
+ else if (h->plt.offset == (bfd_vma) -1)
+ goto bad_ifunc_reloc;
/* STT_GNU_IFUNC symbol must go through PLT. */
plt = globals->root.splt ? globals->root.splt : globals->root.iplt;
switch (bfd_r_type)
{
default:
+bad_ifunc_reloc:
if (h->root.root.string)
name = h->root.root.string;
else
"symbol `%s' isn't handled by %s"), input_bfd,
howto->name, name, __FUNCTION__);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return bfd_reloc_notsupported;
case BFD_RELOC_AARCH64_NN:
if (rel->r_addend != 0)
_bfd_error_handler
/* xgettext:c-format */
(_("%B: relocation %s against STT_GNU_IFUNC "
- "symbol `%s' has non-zero addend: %d"),
+ "symbol `%s' has non-zero addend: %Ld"),
input_bfd, howto->name, name, rel->r_addend);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return bfd_reloc_notsupported;
}
/* Generate dynamic relocation only when there is a
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;
- }
+ if (aarch64_relocation_aginst_gp_p (bfd_r_type))
+ addend = (globals->root.sgot->output_section->vma
+ + globals->root.sgot->output_offset);
value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
addend, weak_undef_p);
}
}
+ resolved_to_zero = (h != NULL
+ && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+
switch (bfd_r_type)
{
case BFD_RELOC_AARCH64_NONE:
|| globals->root.is_relocatable_executable)
&& (input_section->flags & SEC_ALLOC)
&& (h == NULL
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ && !resolved_to_zero)
|| h->root.type != bfd_link_hash_undefweak))
/* Or we are creating an executable, we may need to keep relocations
for symbols satisfied by a dynamic library if we manage to avoid
input_bfd, elfNN_aarch64_howto_table[howto_index].name,
h->root.root.string);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return bfd_reloc_notsupported;
}
/* Fall through. */
case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
+ case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15:
+ case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
+ case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
if (globals->root.sgot == NULL)
BFD_ASSERT (h != NULL);
+ relative_reloc = FALSE;
if (h != NULL)
{
bfd_vma addend = 0;
+
+ /* If a symbol is not dynamic and is not undefined weak, bind it
+ locally and generate a RELATIVE relocation under PIC mode.
+
+ NOTE: one symbol may be referenced by several relocations, we
+ should only generate one RELATIVE relocation for that symbol.
+ Therefore, check GOT offset mark first. */
+ if (h->dynindx == -1
+ && !h->forced_local
+ && h->root.type != bfd_link_hash_undefweak
+ && bfd_link_pic (info)
+ && !symbol_got_offset_mark_p (input_bfd, h, r_symndx))
+ relative_reloc = TRUE;
+
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)
+ /* Record the GOT entry address which will be used when generating
+ RELATIVE relocation. */
+ if (relative_reloc)
+ got_entry_addr = value;
+
+ if (aarch64_relocation_aginst_gp_p (bfd_r_type))
addend = (globals->root.sgot->output_section->vma
+ globals->root.sgot->output_offset);
value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
off = symbol_got_offset (input_bfd, h, r_symndx);
base_got = globals->root.sgot;
- bfd_vma got_entry_addr = (base_got->output_section->vma
- + base_got->output_offset + off);
+ got_entry_addr = (base_got->output_section->vma
+ + base_got->output_offset + off);
if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx))
{
bfd_put_64 (output_bfd, value, base_got->contents + off);
+ /* For local symbol, we have done absolute relocation in static
+ linking stage. While for shared library, we need to update the
+ content of GOT entry according to the shared object's runtime
+ base address. So, we need to generate a R_AARCH64_RELATIVE reloc
+ for dynamic linker. */
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 ();
-
- 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);
- }
+ relative_reloc = TRUE;
symbol_got_offset_mark (input_bfd, h, r_symndx);
}
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)
+ if (aarch64_relocation_aginst_gp_p (bfd_r_type))
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
+ if (relative_reloc)
{
- 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
- /* xgettext:c-format */
- (_("%B: Local symbol descriptor table be NULL when applying "
- "relocation %s against local symbol"),
- input_bfd, elfNN_aarch64_howto_table[howto_index].name);
- abort ();
- }
+ asection *s;
+ Elf_Internal_Rela outrel;
- off = symbol_got_offset (input_bfd, h, r_symndx);
- base_got = globals->root.sgot;
- if (base_got == NULL)
+ s = globals->root.srelgot;
+ if (s == NULL)
abort ();
- bfd_vma got_entry_addr = (base_got->output_section->vma
- + base_got->output_offset + off);
-
- if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx))
- {
- bfd_put_64 (output_bfd, value, base_got->contents + off);
-
- 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);
- }
-
- symbol_got_offset_mark (input_bfd, h, r_symndx);
- }
+ outrel.r_offset = got_entry_addr;
+ outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE));
+ outrel.r_addend = orig_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 = 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:
r_symndx = ELFNN_R_SYM (rel->r_info);
r_type = ELFNN_R_TYPE (rel->r_info);
- bfd_reloc.howto = elfNN_aarch64_howto_from_type (r_type);
- howto = bfd_reloc.howto;
+ howto = bfd_reloc.howto = elfNN_aarch64_howto_from_type (r_type);
if (howto == NULL)
- {
- /* xgettext:c-format */
- _bfd_error_handler
- (_("%B: unrecognized relocation (0x%x) in section `%A'"),
- input_bfd, r_type, input_section);
- return FALSE;
- }
+ return _bfd_unrecognized_reloc (input_bfd, input_section, r_type);
+
bfd_r_type = elfNN_aarch64_bfd_reloc_from_howto (howto);
h = NULL;
_bfd_error_handler
((sym_type == STT_TLS
/* xgettext:c-format */
- ? _("%B(%A+0x%lx): %s used with TLS symbol %s")
+ ? _("%B(%A+%#Lx): %s used with TLS symbol %s")
/* xgettext:c-format */
- : _("%B(%A+0x%lx): %s used with non-TLS symbol %s")),
+ : _("%B(%A+%#Lx): %s used with non-TLS symbol %s")),
input_bfd,
- input_section, (long) rel->r_offset, howto->name, name);
+ input_section, rel->r_offset, howto->name, name);
}
/* We relax only if we can see that there can be a valid transition
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"),
- input_bfd, input_section, (long) rel->r_offset, howto->name,
+ (_("%B(%A+%#Lx): unresolvable %s relocation against symbol `%s'"),
+ input_bfd, input_section, rel->r_offset, howto->name,
h->root.root.string);
return FALSE;
}
return TRUE;
}
-/* Update the got entry reference counts for the section being removed. */
-
-static bfd_boolean
-elfNN_aarch64_gc_sweep_hook (bfd *abfd,
- struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela * relocs)
-{
- struct elf_aarch64_link_hash_table *htab;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- struct elf_aarch64_local_symbol *locals;
- const Elf_Internal_Rela *rel, *relend;
-
- if (bfd_link_relocatable (info))
- return TRUE;
-
- htab = elf_aarch64_hash_table (info);
-
- if (htab == NULL)
- return FALSE;
-
- elf_section_data (sec)->local_dynrel = NULL;
-
- symtab_hdr = &elf_symtab_hdr (abfd);
- sym_hashes = elf_sym_hashes (abfd);
-
- locals = elf_aarch64_locals (abfd);
-
- relend = relocs + sec->reloc_count;
- for (rel = relocs; rel < relend; rel++)
- {
- unsigned long r_symndx;
- unsigned int r_type;
- struct elf_link_hash_entry *h = NULL;
-
- r_symndx = ELFNN_R_SYM (rel->r_info);
-
- if (r_symndx >= symtab_hdr->sh_info)
- {
-
- h = sym_hashes[r_symndx - symtab_hdr->sh_info];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- }
- else
- {
- Elf_Internal_Sym *isym;
-
- /* A local symbol. */
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
- abfd, r_symndx);
-
- /* Check relocation against local STT_GNU_IFUNC symbol. */
- if (isym != NULL
- && ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
- {
- h = elfNN_aarch64_get_local_sym_hash (htab, abfd, rel, FALSE);
- if (h == NULL)
- abort ();
- }
- }
-
- if (h)
- {
- struct elf_aarch64_link_hash_entry *eh;
- struct elf_dyn_relocs **pp;
- struct elf_dyn_relocs *p;
-
- eh = (struct elf_aarch64_link_hash_entry *) h;
-
- for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
- if (p->sec == sec)
- {
- /* Everything must go for SEC. */
- *pp = p->next;
- break;
- }
- }
-
- r_type = ELFNN_R_TYPE (rel->r_info);
- switch (aarch64_tls_transition (abfd,info, r_type, h ,r_symndx))
- {
- 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:
- 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:
- 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_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)
- h->got.refcount -= 1;
-
- if (h->type == STT_GNU_IFUNC)
- {
- if (h->plt.refcount > 0)
- h->plt.refcount -= 1;
- }
- }
- else if (locals != NULL)
- {
- if (locals[r_symndx].got_refcount > 0)
- locals[r_symndx].got_refcount -= 1;
- }
- break;
-
- case BFD_RELOC_AARCH64_CALL26:
- case BFD_RELOC_AARCH64_JUMP26:
- /* If this is a local symbol then we resolve it
- directly without creating a PLT entry. */
- if (h == NULL)
- continue;
-
- if (h->plt.refcount > 0)
- h->plt.refcount -= 1;
- break;
-
- case BFD_RELOC_AARCH64_ADD_LO12:
- 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_LDST128_LO12:
- case BFD_RELOC_AARCH64_LDST16_LO12:
- case BFD_RELOC_AARCH64_LDST32_LO12:
- case BFD_RELOC_AARCH64_LDST64_LO12:
- case BFD_RELOC_AARCH64_LDST8_LO12:
- case BFD_RELOC_AARCH64_LD_LO19_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_NN:
- if (h != NULL && !bfd_link_pic (info))
- {
- if (h->plt.refcount > 0)
- h->plt.refcount -= 1;
- }
- break;
-
- default:
- break;
- }
- }
-
- return TRUE;
-}
-
/* Return true if we need copy relocation against EH. */
static bfd_boolean
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
- if (h->u.weakdef != NULL)
+ if (h->is_weakalias)
{
- BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
- || h->u.weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->u.weakdef->root.u.def.section;
- h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ struct elf_link_hash_entry *def = weakdef (h);
+ BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+ h->root.u.def.section = def->root.u.def.section;
+ h->root.u.def.value = def->root.u.def.value;
if (ELIMINATE_COPY_RELOCS || info->nocopyreloc)
- h->non_got_ref = h->u.weakdef->non_got_ref;
+ h->non_got_ref = def->non_got_ref;
return TRUE;
}
for (rel = relocs; rel < rel_end; rel++)
{
struct elf_link_hash_entry *h;
- unsigned long r_symndx;
+ unsigned int r_symndx;
unsigned int r_type;
bfd_reloc_code_real_type bfd_r_type;
Elf_Internal_Sym *isym;
const asection *rel_sec ATTRIBUTE_UNUSED,
const Elf_Internal_Rela *rela)
{
+ struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
+
+ if (htab->root.dynsym != NULL
+ && htab->root.dynsym->contents != NULL)
+ {
+ /* Check relocation against STT_GNU_IFUNC symbol if there are
+ dynamic symbols. */
+ bfd *abfd = info->output_bfd;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ unsigned long r_symndx = ELFNN_R_SYM (rela->r_info);
+ if (r_symndx != STN_UNDEF)
+ {
+ Elf_Internal_Sym sym;
+ if (!bed->s->swap_symbol_in (abfd,
+ (htab->root.dynsym->contents
+ + r_symndx * bed->s->sizeof_sym),
+ 0, &sym))
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B symbol number %lu references"
+ " nonexistent SHT_SYMTAB_SHNDX section"),
+ abfd, r_symndx);
+ /* Ideally an error class should be returned here. */
+ }
+ else if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
+ return reloc_class_ifunc;
+ }
+ }
+
switch ((int) ELFNN_R_TYPE (rela->r_info))
{
+ case AARCH64_R (IRELATIVE):
+ return reloc_class_ifunc;
case AARCH64_R (RELATIVE):
return reloc_class_relative;
case AARCH64_R (JUMP_SLOT):
{
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
- if (h->dynindx == -1 && !h->forced_local)
+ if (h->dynindx == -1 && !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak)
{
if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
- if (dyn && h->dynindx == -1 && !h->forced_local)
+ if (dyn && h->dynindx == -1 && !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak)
{
if (!bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
&& (bfd_link_pic (info)
- || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
+ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
+ /* Undefined weak symbol in static PIE resolves to 0 without
+ any dynamic relocations. */
+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
{
htab->root.srelgot->size += RELOC_SIZE (htab);
}
visibility. */
if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak)
{
- if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
eh->dyn_relocs = NULL;
/* Make sure undefined weak symbols are output as a dynamic
symbol in PIEs. */
else if (h->dynindx == -1
&& !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak
&& !bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
}
Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1
&& !h->forced_local
+ && h->root.type == bfd_link_hash_undefweak
&& !bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
{
reloc_howto_type *howto = elfNN_aarch64_howto_from_bfd_reloc (r_type);
- _bfd_aarch64_elf_put_addend (output_bfd, plt_entry, r_type, howto, value);
+ /* FIXME: We should check the return value from this function call. */
+ (void) _bfd_aarch64_elf_put_addend (output_bfd, plt_entry, r_type, howto, value);
}
static void
}
if (h->got.offset != (bfd_vma) - 1
- && elf_aarch64_hash_entry (h)->got_type == GOT_NORMAL)
+ && elf_aarch64_hash_entry (h)->got_type == GOT_NORMAL
+ /* Undefined weak symbol in static PIE resolves to 0 without
+ any dynamic relocations. */
+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
{
Elf_Internal_Rela rela;
bfd_byte *loc;
#define elf_backend_finish_dynamic_symbol \
elfNN_aarch64_finish_dynamic_symbol
-#define elf_backend_gc_sweep_hook \
- elfNN_aarch64_gc_sweep_hook
-
#define elf_backend_object_p \
elfNN_aarch64_object_p