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;
-
- /* PR15323, ref flags aren't set for references in the same
- object. */
- h->root.non_ir_ref_regular = 1;
}
/* Create got section and local_got_refcounts array if they
}
-/* Update the got entry reference counts for the section being removed. */
-
-static bfd_boolean
-elf_s390_gc_sweep_hook (bfd *abfd,
- struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela *relocs)
-{
- struct elf_s390_link_hash_table *htab;
- Elf_Internal_Shdr *symtab_hdr;
- struct elf_link_hash_entry **sym_hashes;
- bfd_signed_vma *local_got_refcounts;
- const Elf_Internal_Rela *rel, *relend;
-
- if (bfd_link_relocatable (info))
- return TRUE;
-
- htab = elf_s390_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);
- local_got_refcounts = elf_local_got_refcounts (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 = ELF32_R_SYM (rel->r_info);
- if (r_symndx >= symtab_hdr->sh_info)
- {
- struct elf_s390_link_hash_entry *eh;
- struct elf_dyn_relocs **pp;
- struct elf_dyn_relocs *p;
-
- 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;
- eh = (struct elf_s390_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;
- }
- }
- else
- {
- Elf_Internal_Sym *isym;
-
- /* A local symbol. */
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
- abfd, r_symndx);
- if (isym == NULL)
- return FALSE;
-
- if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
- {
- struct plt_entry *plt = elf_s390_local_plt (abfd);
- if (plt[r_symndx].plt.refcount > 0)
- plt[r_symndx].plt.refcount--;
- }
- }
-
- r_type = ELF32_R_TYPE (rel->r_info);
- r_type = elf_s390_tls_transition (info, r_type, h != NULL);
- switch (r_type)
- {
- case R_390_TLS_LDM32:
- if (elf_s390_hash_table (info)->tls_ldm_got.refcount > 0)
- elf_s390_hash_table (info)->tls_ldm_got.refcount -= 1;
- break;
-
- case R_390_GOTOFF16:
- case R_390_GOTOFF32:
- if (h != NULL && s390_is_ifunc_symbol_p (h) && h->def_regular)
- {
- h->plt.refcount--;
- break;
- }
-
- case R_390_GOTPC:
- case R_390_GOTPCDBL:
- break;
-
- case R_390_TLS_GD32:
- case R_390_TLS_IE32:
- case R_390_TLS_GOTIE12:
- case R_390_TLS_GOTIE20:
- case R_390_TLS_GOTIE32:
- case R_390_TLS_IEENT:
- case R_390_GOT12:
- case R_390_GOT16:
- case R_390_GOT20:
- case R_390_GOT32:
- case R_390_GOTENT:
- if (h != NULL)
- {
- if (h->got.refcount > 0)
- h->got.refcount -= 1;
- }
- else if (local_got_refcounts != NULL)
- {
- if (local_got_refcounts[r_symndx] > 0)
- local_got_refcounts[r_symndx] -= 1;
- }
- break;
-
- case R_390_8:
- case R_390_12:
- case R_390_16:
- case R_390_20:
- case R_390_32:
- case R_390_PC16:
- case R_390_PC12DBL:
- case R_390_PC16DBL:
- case R_390_PC24DBL:
- case R_390_PC32DBL:
- case R_390_PC32:
- if (bfd_link_pic (info))
- break;
- /* Fall through. */
-
- case R_390_PLT12DBL:
- case R_390_PLT16DBL:
- case R_390_PLT24DBL:
- case R_390_PLT32DBL:
- case R_390_PLT32:
- case R_390_PLTOFF16:
- case R_390_PLTOFF32:
- if (h != NULL)
- {
- if (h->plt.refcount > 0)
- h->plt.refcount -= 1;
- }
- break;
-
- case R_390_GOTPLT12:
- case R_390_GOTPLT16:
- case R_390_GOTPLT20:
- case R_390_GOTPLT32:
- case R_390_GOTPLTENT:
- if (h != NULL)
- {
- if (h->plt.refcount > 0)
- {
- ((struct elf_s390_link_hash_entry *) h)->gotplt_refcount--;
- h->plt.refcount -= 1;
- }
- }
- else if (local_got_refcounts != NULL)
- {
- if (local_got_refcounts[r_symndx] > 0)
- local_got_refcounts[r_symndx] -= 1;
- }
- break;
-
- default:
- break;
- }
- }
-
- return TRUE;
-}
-
/* Make sure we emit a GOT entry if the symbol was supposed to have a PLT
entry but we found we will not create any. Called when we find we will
not have any PLT for this symbol, by for example
h->gotplt_refcount = -1;
}
+/* Find dynamic relocs for H that apply to read-only sections. */
+
+static asection *
+readonly_dynrelocs (struct elf_link_hash_entry *h)
+{
+ struct elf_dyn_relocs *p;
+
+ for (p = elf_s390_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
+ {
+ asection *s = p->sec->output_section;
+
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
+ return p->sec;
+ }
+ return NULL;
+}
+
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
/* 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;
}
return TRUE;
}
-/* Find any dynamic relocs that apply to read-only sections. */
+/* Set DF_TEXTREL if we find any dynamic relocs that apply to
+ read-only sections. */
static bfd_boolean
-readonly_dynrelocs (struct elf_link_hash_entry *h, void * inf)
+maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
{
- struct elf_s390_link_hash_entry *eh;
- struct elf_dyn_relocs *p;
+ asection *sec;
- eh = (struct elf_s390_link_hash_entry *) h;
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
- {
- asection *s = p->sec->output_section;
+ if (h->root.type == bfd_link_hash_indirect)
+ return TRUE;
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
- {
- struct bfd_link_info *info = (struct bfd_link_info *) inf;
+ sec = readonly_dynrelocs (h);
+ if (sec != NULL)
+ {
+ struct bfd_link_info *info = (struct bfd_link_info *) info_p;
- info->flags |= DF_TEXTREL;
+ info->flags |= DF_TEXTREL;
+ info->callbacks->minfo
+ (_("%B: dynamic relocation against `%T' in read-only section `%A'\n"),
+ sec->owner, h->root.root.string, sec);
- /* Not an error, just cut short the traversal. */
- return FALSE;
- }
+ /* Not an error, just cut short the traversal. */
+ return FALSE;
}
return TRUE;
}
/* 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->elf, readonly_dynrelocs, info);
+ elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info);
if ((info->flags & DF_TEXTREL) != 0)
{
#define elf_backend_finish_dynamic_sections elf_s390_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf_s390_finish_dynamic_symbol
#define elf_backend_gc_mark_hook elf_s390_gc_mark_hook
-#define elf_backend_gc_sweep_hook elf_s390_gc_sweep_hook
#define elf_backend_reloc_type_class elf_s390_reloc_type_class
#define elf_backend_relocate_section elf_s390_relocate_section
#define elf_backend_size_dynamic_sections elf_s390_size_dynamic_sections