edir->tls_mask |= eind->tls_mask;
edir->has_sda_refs |= eind->has_sda_refs;
- /* If called to transfer flags for a weakdef during processing
- of elf_adjust_dynamic_symbol, don't copy non_got_ref.
- We clear it ourselves for ELIMINATE_COPY_RELOCS. */
- if (!(ELIMINATE_COPY_RELOCS
- && eind->elf.root.type != bfd_link_hash_indirect
- && edir->elf.dynamic_adjusted))
- edir->elf.non_got_ref |= eind->elf.non_got_ref;
-
if (edir->elf.versioned != versioned_hidden)
edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
edir->elf.ref_regular |= eind->elf.ref_regular;
edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
+ edir->elf.non_got_ref |= eind->elf.non_got_ref;
edir->elf.needs_plt |= eind->elf.needs_plt;
edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
+ /* If we were called to copy over info for a weak sym, that's all. */
+ if (eind->elf.root.type != bfd_link_hash_indirect)
+ return;
+
if (eind->dyn_relocs != NULL)
{
if (edir->dyn_relocs != NULL)
eind->dyn_relocs = NULL;
}
- /* If we were called to copy over info for a weak sym, that's all.
- You might think dyn_relocs need not be copied over; After all,
- both syms will be dynamic or both non-dynamic so we're just
- moving reloc accounting around. However, ELIMINATE_COPY_RELOCS
- code in ppc_elf_adjust_dynamic_symbol needs to check for
- dyn_relocs in read-only sections, and it does so on what is the
- DIR sym here. */
- if (eind->elf.root.type != bfd_link_hash_indirect)
- return;
-
/* Copy over the GOT refcount entries that we may have already seen to
the symbol which just became indirect. */
edir->elf.got.refcount += eind->elf.got.refcount;
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;
}
/* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
return TRUE;
}
\f
-/* Return true if we have dynamic relocs that apply to read-only sections. */
+/* Find dynamic relocs for H that apply to read-only sections. */
-static bfd_boolean
-readonly_dynrelocs (struct elf_link_hash_entry *h,
- struct bfd_link_info *info)
+static asection *
+readonly_dynrelocs (struct elf_link_hash_entry *h)
{
struct elf_dyn_relocs *p;
{
asection *s = p->sec->output_section;
- if (s != NULL
- && ((s->flags & (SEC_READONLY | SEC_ALLOC))
- == (SEC_READONLY | SEC_ALLOC)))
- {
- if (info)
- info->callbacks->minfo (_("%B: dynamic relocation in read-only section `%A'\n"),
- p->sec->owner, p->sec);
-
- return TRUE;
- }
+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
+ return p->sec;
}
+ return NULL;
+}
+
+/* Return true if we have dynamic relocs against H or any of its weak
+ aliases, that apply to read-only sections. Cannot be used after
+ size_dynamic_sections. */
+
+static bfd_boolean
+alias_readonly_dynrelocs (struct elf_link_hash_entry *h)
+{
+ struct ppc_elf_link_hash_entry *eh = ppc_elf_hash_entry (h);
+ do
+ {
+ if (readonly_dynrelocs (&eh->elf))
+ return TRUE;
+ eh = ppc_elf_hash_entry (eh->elf.u.alias);
+ } while (eh != NULL && &eh->elf != h);
+
+ return FALSE;
+}
+
+/* Return whether H has pc-relative dynamic relocs. */
+
+static bfd_boolean
+pc_dynrelocs (struct elf_link_hash_entry *h)
+{
+ struct elf_dyn_relocs *p;
+
+ for (p = ppc_elf_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
+ if (p->pc_count != 0)
+ return TRUE;
return FALSE;
}
BFD_ASSERT (htab->elf.dynobj != NULL
&& (h->needs_plt
|| h->type == STT_GNU_IFUNC
- || h->u.weakdef != NULL
+ || h->is_weakalias
|| (h->def_dynamic
&& h->ref_regular
&& !h->def_regular)));
|| h->type == STT_GNU_IFUNC
|| h->needs_plt)
{
+ bfd_boolean local = (SYMBOL_CALLS_LOCAL (info, h)
+ || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
+ /* Discard dyn_relocs when non-pic if we've decided that a
+ function symbol is local. */
+ if (!bfd_link_pic (info) && local)
+ ppc_elf_hash_entry (h)->dyn_relocs = NULL;
+
/* Clear procedure linkage table information for any symbol that
won't need a .plt entry. */
struct plt_entry *ent;
if (ent->plt.refcount > 0)
break;
if (ent == NULL
- || (h->type != STT_GNU_IFUNC
- && (SYMBOL_CALLS_LOCAL (info, h)
- || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))))
+ || (h->type != STT_GNU_IFUNC && local))
{
/* A PLT entry is not required/allowed when:
resolution of the symbol to be set at load time rather
than link time. */
if ((h->pointer_equality_needed
- || (!h->ref_regular_nonweak && h->non_got_ref))
+ || (h->non_got_ref
+ && !h->ref_regular_nonweak
+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
&& !htab->is_vxworks
&& !ppc_elf_hash_entry (h)->has_sda_refs
- && !readonly_dynrelocs (h, NULL))
+ && !readonly_dynrelocs (h))
{
h->pointer_equality_needed = 0;
- /* After adjust_dynamic_symbol, non_got_ref set in the
- non-pic case means that dyn_relocs for this symbol
- should be discarded. */
- h->non_got_ref = 0;
+ /* If we haven't seen a branch reloc then we don't need
+ a plt entry. */
+ if (!h->needs_plt)
+ h->plt.plist = NULL;
}
+ else if (!bfd_link_pic (info))
+ /* We are going to be defining the function symbol on the
+ plt stub, so no dyn_relocs needed when non-pic. */
+ ppc_elf_hash_entry (h)->dyn_relocs = NULL;
}
h->protected_def = 0;
+ /* Function symbols can't have copy relocs. */
return TRUE;
}
else
/* 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;
- if (ELIMINATE_COPY_RELOCS)
- h->non_got_ref = h->u.weakdef->non_got_ref;
+ 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 (def->root.u.def.section == htab->elf.sdynbss
+ || def->root.u.def.section == htab->elf.sdynrelro
+ || def->root.u.def.section == htab->dynsbss)
+ ppc_elf_hash_entry (h)->dyn_relocs = NULL;
return TRUE;
}
&& htab->params->pic_fixup == 0
&& info->disable_target_specific_optimizations <= 1)
htab->params->pic_fixup = 1;
- h->non_got_ref = 0;
return TRUE;
}
/* If -z nocopyreloc was given, we won't generate them either. */
if (info->nocopyreloc)
- {
- h->non_got_ref = 0;
- return TRUE;
- }
+ return TRUE;
- /* If we didn't find any dynamic relocs in read-only sections, then
+ /* If we don't find any dynamic relocs in read-only sections, then
we'll be keeping the dynamic relocs and avoiding the copy reloc.
We can't do this if there are any small data relocations. This
doesn't work on VxWorks, where we can not have dynamic
&& !ppc_elf_hash_entry (h)->has_sda_refs
&& !htab->is_vxworks
&& !h->def_regular
- && !readonly_dynrelocs (h, NULL))
- {
- h->non_got_ref = 0;
- return TRUE;
- }
+ && !alias_readonly_dynrelocs (h))
+ return TRUE;
/* We must allocate the symbol in our .dynbss section, which will
become part of the .bss section of the executable. There will be
Of course, if the symbol is referenced using SDAREL relocs, we
must instead allocate it in .sbss. */
-
if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->dynsbss;
else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
s = htab->elf.sdynbss;
BFD_ASSERT (s != NULL);
- /* We must generate a R_PPC_COPY reloc to tell the dynamic linker to
- copy the initial value out of the dynamic object and into the
- runtime process image. We need to remember the offset into the
- .rela.bss section we are going to use. */
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
asection *srel;
+ /* We must generate a R_PPC_COPY reloc to tell the dynamic
+ linker to copy the initial value out of the dynamic object
+ and into the runtime process image. */
if (ppc_elf_hash_entry (h)->has_sda_refs)
srel = htab->relsbss;
else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
h->needs_copy = 1;
}
+ /* We no longer want dyn_relocs. */
+ ppc_elf_hash_entry (h)->dyn_relocs = NULL;
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
\f
return where;
}
+/* Calculate size of GOT entries for symbol given its TLS_MASK.
+ TLS_LD is excluded because those go in a special GOT slot. */
+
+static inline unsigned int
+got_entries_needed (int tls_mask)
+{
+ unsigned int need;
+ if ((tls_mask & TLS_TLS) == 0)
+ need = 4;
+ else
+ {
+ need = 0;
+ if ((tls_mask & TLS_GD) != 0)
+ need += 8;
+ if ((tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
+ need += 4;
+ if ((tls_mask & TLS_DTPREL) != 0)
+ need += 4;
+ }
+ return need;
+}
+
+/* Calculate size of relocs needed for symbol given its TLS_MASK and
+ NEEDed GOT entries. KNOWN says a TPREL offset can be calculated at
+ link time. */
+
+static inline unsigned int
+got_relocs_needed (int tls_mask, unsigned int need, bfd_boolean known)
+{
+ /* All the entries we allocated need relocs.
+ Except IE in executable with a local symbol. We could also omit
+ the DTPREL reloc on the second word of a GD entry under the same
+ condition as that for IE, but ld.so needs to differentiate
+ LD and GD entries. */
+ if ((tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0 && known)
+ need -= 4;
+ return need * sizeof (Elf32_External_Rela) / 4;
+}
+
/* If H is undefined, make it dynamic if that makes sense. */
static bfd_boolean
return FALSE;
need = 0;
- if ((eh->tls_mask & TLS_TLS) != 0)
+ if ((eh->tls_mask & TLS_LD) != 0)
{
- if ((eh->tls_mask & TLS_LD) != 0)
- {
- if (!eh->elf.def_dynamic)
- /* We'll just use htab->tlsld_got.offset. This should
- always be the case. It's a little odd if we have
- a local dynamic reloc against a non-local symbol. */
- htab->tlsld_got.refcount += 1;
- else
- need += 8;
- }
- if ((eh->tls_mask & TLS_GD) != 0)
+ if (!eh->elf.def_dynamic)
+ /* We'll just use htab->tlsld_got.offset. This should
+ always be the case. It's a little odd if we have
+ a local dynamic reloc against a non-local symbol. */
+ htab->tlsld_got.refcount += 1;
+ else
need += 8;
- if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
- need += 4;
- if ((eh->tls_mask & TLS_DTPREL) != 0)
- need += 4;
}
- else
- need += 4;
+ need += got_entries_needed (eh->tls_mask);
if (need == 0)
eh->elf.got.offset = (bfd_vma) -1;
else
&& !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
&& !UNDEFWEAK_NO_DYNAMIC_RELOC (info, &eh->elf))
{
- asection *rsec = htab->elf.srelgot;
-
+ asection *rsec;
+ bfd_boolean tprel_known = (bfd_link_executable (info)
+ && SYMBOL_REFERENCES_LOCAL (info,
+ &eh->elf));
+
+ need = got_relocs_needed (eh->tls_mask, need, tprel_known);
+ if ((eh->tls_mask & TLS_LD) != 0 && eh->elf.def_dynamic)
+ need -= sizeof (Elf32_External_Rela);
+ rsec = htab->elf.srelgot;
if (eh->elf.type == STT_GNU_IFUNC)
rsec = htab->elf.irelplt;
- /* All the entries we allocated need relocs.
- Except LD only needs one. */
- if ((eh->tls_mask & TLS_LD) != 0
- && eh->elf.def_dynamic)
- need -= 4;
- rsec->size += need * (sizeof (Elf32_External_Rela) / 4);
+ rsec->size += need;
}
}
}
&& h->type != STT_GNU_IFUNC)
eh->dyn_relocs = NULL;
+ /* Discard relocs on undefined symbols that must be local. */
+ else if (h->root.type == bfd_link_hash_undefined
+ && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ eh->dyn_relocs = NULL;
+
+ /* Also discard relocs on undefined weak syms with non-default
+ visibility, or when dynamic_undefined_weak says so. */
+ else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+ eh->dyn_relocs = NULL;
+
if (eh->dyn_relocs == NULL)
;
changes. */
else if (bfd_link_pic (info))
{
- /* Discard relocs on undefined symbols that must be local. */
- if (h->root.type == bfd_link_hash_undefined
- && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- eh->dyn_relocs = NULL;
-
- /* Also discard relocs on undefined weak syms with non-default
- visibility, or when dynamic_undefined_weak says so. */
- else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
- eh->dyn_relocs = NULL;
-
/* Relocs that use pc_count are those that appear on a call insn,
or certain REL relocs (see must_be_dyn_reloc) that can be
generated via assembly. We want calls to protected symbols to
resolve directly to the function rather than going via the plt.
If people want function pointer comparisons to work as expected
then they should avoid writing weird assembly. */
- else if (SYMBOL_CALLS_LOCAL (info, h))
+ if (SYMBOL_CALLS_LOCAL (info, h))
{
struct elf_dyn_relocs **pp;
/* For the non-pic case, discard space for relocs against
symbols which turn out to need copy relocs or are not
dynamic. */
- if (!h->non_got_ref
+ if (h->dynamic_adjusted
&& !h->def_regular
+ && !ELF_COMMON_DEF_P (h)
&& !(h->protected_def
&& eh->has_addr16_ha
&& eh->has_addr16_lo
static bfd_boolean
maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
{
- struct bfd_link_info *info;
+ asection *sec;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- info = (struct bfd_link_info *) info_p;
- if (readonly_dynrelocs (h, info))
+ sec = readonly_dynrelocs (h);
+ if (sec != NULL)
{
+ struct bfd_link_info *info = (struct bfd_link_info *) info_p;
+
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;
for (; local_got < end_local_got; ++local_got, ++lgot_masks)
if (*local_got > 0)
{
- unsigned int need = 0;
- if ((*lgot_masks & TLS_TLS) != 0)
- {
- if ((*lgot_masks & TLS_GD) != 0)
- need += 8;
- if ((*lgot_masks & TLS_LD) != 0)
- htab->tlsld_got.refcount += 1;
- if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
- need += 4;
- if ((*lgot_masks & TLS_DTPREL) != 0)
- need += 4;
- }
- else
- need += 4;
+ unsigned int need;
+ if ((*lgot_masks & TLS_LD) != 0)
+ htab->tlsld_got.refcount += 1;
+ need = got_entries_needed (*lgot_masks);
if (need == 0)
*local_got = (bfd_vma) -1;
else
*local_got = allocate_got (htab, need);
if (bfd_link_pic (info))
{
- asection *srel = htab->elf.srelgot;
+ asection *srel;
+ bfd_boolean tprel_known = bfd_link_executable (info);
+
+ need = got_relocs_needed (*lgot_masks, need, tprel_known);
+ srel = htab->elf.srelgot;
if ((*lgot_masks & PLT_IFUNC) != 0)
srel = htab->elf.irelplt;
- srel->size += need * (sizeof (Elf32_External_Rela) / 4);
+ srel->size += need;
}
}
}
|| (bfd_link_pic (info)
&& (h == NULL
|| !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
- || offp == &htab->tlsld_got.offset)))
+ || offp == &htab->tlsld_got.offset)
+ && !(tls_ty == (TLS_TLS | TLS_TPREL)
+ && bfd_link_executable (info)
+ && SYMBOL_REFERENCES_LOCAL (info, h))))
{
asection *rsec = htab->elf.srelgot;
bfd_byte * loc;
|| is_vxworks_tls)
break;
- if ((bfd_link_pic (info)
- && !(h != NULL
- && ((h->root.type == bfd_link_hash_undefined
- && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
- && (must_be_dyn_reloc (info, r_type)
- || !SYMBOL_CALLS_LOCAL (info, h)))
- || (ELIMINATE_COPY_RELOCS
- && !bfd_link_pic (info)
- && h != NULL
- && h->dynindx != -1
- && !h->non_got_ref
- && !h->def_regular
- && !(h->protected_def
- && ppc_elf_hash_entry (h)->has_addr16_ha
- && ppc_elf_hash_entry (h)->has_addr16_lo
- && htab->params->pic_fixup > 0)))
+ if (bfd_link_pic (info)
+ ? ((h == NULL
+ || ppc_elf_hash_entry (h)->dyn_relocs != NULL)
+ && ((h != NULL && pc_dynrelocs (h))
+ || must_be_dyn_reloc (info, r_type)))
+ : (h != NULL
+ && ppc_elf_hash_entry (h)->dyn_relocs != NULL))
{
int skip;
bfd_byte *loc;
#define elf_backend_relocate_section ppc_elf_relocate_section
#define elf_backend_create_dynamic_sections ppc_elf_create_dynamic_sections
#define elf_backend_check_relocs ppc_elf_check_relocs
+#define elf_backend_relocs_compatible _bfd_elf_relocs_compatible
#define elf_backend_copy_indirect_symbol ppc_elf_copy_indirect_symbol
#define elf_backend_adjust_dynamic_symbol ppc_elf_adjust_dynamic_symbol
#define elf_backend_add_symbol_hook ppc_elf_add_symbol_hook