#define VXWORKS_PLT_NON_JMP_SLOT_RELOCS 3
/* The number of relocations in the PLTResolve slot. */
#define VXWORKS_PLTRESOLVE_RELOCS 2
-/* The number of relocations in the PLTResolve slot when when creating
+/* The number of relocations in the PLTResolve slot when creating
a shared library. */
#define VXWORKS_PLTRESOLVE_RELOCS_SHLIB 0
0x3e007ff, /* dst_mask */
FALSE), /* pcrel_offset */
+ /* e_li split20 format. */
+ HOWTO (R_PPC_VLE_ADDR20, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 20, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_VLE_ADDR20", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x1f07ff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
HOWTO (R_PPC_IRELATIVE, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
0x1fffc1, /* dst_mask */
TRUE), /* pcrel_offset */
+ /* A split-field reloc for addpcis, non-relative (gas internal use only). */
+ HOWTO (R_PPC_16DX_HA, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_elf_addr16_ha_reloc, /* special_function */
+ "R_PPC_16DX_HA", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0x1fffc1, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
/* GNU extension to record C++ vtable hierarchy. */
HOWTO (R_PPC_GNU_VTINHERIT, /* type */
0, /* rightshift */
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
};
-
-/* External 32-bit PPC structure for PRPSINFO. This structure is
- ABI-defined, thus we choose to use char arrays here in order to
- avoid dealing with different types in different architectures.
-
- The PPC 32-bit structure uses int for `pr_uid' and `pr_gid' while
- most non-PPC architectures use `short int'.
-
- This structure will ultimately be written in the corefile's note
- section, as the PRPSINFO. */
-
-struct elf_external_ppc_linux_prpsinfo32
- {
- char pr_state; /* Numeric process state. */
- char pr_sname; /* Char for pr_state. */
- char pr_zomb; /* Zombie. */
- char pr_nice; /* Nice val. */
- char pr_flag[4]; /* Flags. */
- char pr_uid[4];
- char pr_gid[4];
- char pr_pid[4];
- char pr_ppid[4];
- char pr_pgrp[4];
- char pr_sid[4];
- char pr_fname[16]; /* Filename of executable. */
- char pr_psargs[80]; /* Initial part of arg list. */
- };
-
-/* Helper function to copy an elf_internal_linux_prpsinfo in host
- endian to an elf_external_ppc_linux_prpsinfo32 in target endian. */
-
-static inline void
-swap_ppc_linux_prpsinfo32_out (bfd *obfd,
- const struct elf_internal_linux_prpsinfo *from,
- struct elf_external_ppc_linux_prpsinfo32 *to)
-{
- bfd_put_8 (obfd, from->pr_state, &to->pr_state);
- bfd_put_8 (obfd, from->pr_sname, &to->pr_sname);
- bfd_put_8 (obfd, from->pr_zomb, &to->pr_zomb);
- bfd_put_8 (obfd, from->pr_nice, &to->pr_nice);
- bfd_put_32 (obfd, from->pr_flag, to->pr_flag);
- bfd_put_32 (obfd, from->pr_uid, to->pr_uid);
- bfd_put_32 (obfd, from->pr_gid, to->pr_gid);
- bfd_put_32 (obfd, from->pr_pid, to->pr_pid);
- bfd_put_32 (obfd, from->pr_ppid, to->pr_ppid);
- bfd_put_32 (obfd, from->pr_pgrp, to->pr_pgrp);
- bfd_put_32 (obfd, from->pr_sid, to->pr_sid);
- strncpy (to->pr_fname, from->pr_fname, sizeof (to->pr_fname));
- strncpy (to->pr_psargs, from->pr_psargs, sizeof (to->pr_psargs));
-}
\f
/* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */
case BFD_RELOC_LO16_PCREL: r = R_PPC_REL16_LO; break;
case BFD_RELOC_HI16_PCREL: r = R_PPC_REL16_HI; break;
case BFD_RELOC_HI16_S_PCREL: r = R_PPC_REL16_HA; break;
+ case BFD_RELOC_PPC_16DX_HA: r = R_PPC_16DX_HA; break;
case BFD_RELOC_PPC_REL16DX_HA: r = R_PPC_REL16DX_HA; break;
case BFD_RELOC_VTABLE_INHERIT: r = R_PPC_GNU_VTINHERIT; break;
case BFD_RELOC_VTABLE_ENTRY: r = R_PPC_GNU_VTENTRY; break;
/* Set the howto pointer for a PowerPC ELF reloc. */
static void
-ppc_elf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+ppc_elf_info_to_howto (bfd *abfd,
arelent *cache_ptr,
Elf_Internal_Rela *dst)
{
/* Handle the R_PPC_ADDR16_HA and R_PPC_REL16_HA relocs. */
static bfd_reloc_status_type
-ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+ppc_elf_addr16_ha_reloc (bfd *abfd,
arelent *reloc_entry,
asymbol *symbol,
- void *data ATTRIBUTE_UNUSED,
+ void *data,
asection *input_section,
bfd *output_bfd,
char **error_message ATTRIBUTE_UNUSED)
return TRUE;
}
-char *
-elfcore_write_ppc_linux_prpsinfo32
- (bfd *abfd,
- char *buf,
- int *bufsiz,
- const struct elf_internal_linux_prpsinfo *prpsinfo)
-{
- struct elf_external_ppc_linux_prpsinfo32 data;
-
- swap_ppc_linux_prpsinfo32_out (abfd, prpsinfo, &data);
- return elfcore_write_note (abfd, buf, bufsiz,
- "CORE", NT_PRPSINFO, &data, sizeof (data));
-}
-
static char *
ppc_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type, ...)
{
amt += (m->count - j - 1) * sizeof (asection *);
n = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (n == NULL)
- return FALSE;
+ return FALSE;
n->p_type = PT_LOAD;
n->count = m->count - j;
{ STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC };
static const struct bfd_elf_special_section *
-ppc_elf_get_sec_type_attr (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
+ppc_elf_get_sec_type_attr (bfd *abfd, asection *sec)
{
const struct bfd_elf_special_section *ssect;
free (buffer);
if (error_message)
- _bfd_error_handler (error_message, ibfd, APUINFO_SECTION_NAME);
+ _bfd_error_handler (error_message, APUINFO_SECTION_NAME, ibfd);
}
/* Prevent the output section from accumulating the input sections'
bfd_vma glink_offset;
};
-/* Of those relocs that might be copied as dynamic relocs, this function
- selects those that must be copied when linking a shared library,
- even when the symbol is local. */
+/* Of those relocs that might be copied as dynamic relocs, this
+ function selects those that must be copied when linking a shared
+ library or PIE, even when the symbol is local. */
static int
must_be_dyn_reloc (struct bfd_link_info *info,
switch (r_type)
{
default:
+ /* Only relative relocs can be resolved when the object load
+ address isn't fixed. DTPREL32 is excluded because the
+ dynamic linker needs to differentiate global dynamic from
+ local dynamic __tls_index pairs when PPC_OPT_TLS is set. */
return 1;
case R_PPC_REL24:
case R_PPC_TPREL16_LO:
case R_PPC_TPREL16_HI:
case R_PPC_TPREL16_HA:
- return !bfd_link_executable (info);
+ /* These relocations are relative but in a shared library the
+ linker doesn't know the thread pointer base. */
+ return bfd_link_dll (info);
}
}
/* True if the target system is VxWorks. */
unsigned int is_vxworks:1;
+ /* Whether there exist local gnu indirect function resolvers,
+ referenced by dynamic relocations. */
+ unsigned int local_ifunc_resolver:1;
+ unsigned int maybe_local_ifunc_resolver:1;
+
+ /* Set if tls optimization is enabled. */
+ unsigned int do_tls_opt:1;
+
/* The size of PLT entries. */
int plt_entry_size;
/* The distance between adjacent PLT slots. */
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 = 1;
}
/* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
case R_PPC_GOT_TPREL16_LO:
case R_PPC_GOT_TPREL16_HI:
case R_PPC_GOT_TPREL16_HA:
- if (bfd_link_pic (info))
+ if (bfd_link_dll (info))
info->flags |= DF_STATIC_TLS;
tls_type = TLS_TLS | TLS_TPREL;
goto dogottls;
case R_PPC_VLE_HI16D:
case R_PPC_VLE_HA16A:
case R_PPC_VLE_HA16D:
+ case R_PPC_VLE_ADDR20:
break;
case R_PPC_EMB_SDA2REL:
case R_PPC_RELAX:
case R_PPC_RELAX_PLT:
case R_PPC_RELAX_PLTREL24:
+ case R_PPC_16DX_HA:
break;
/* These should only appear in dynamic objects. */
return FALSE;
break;
- /* We shouldn't really be seeing these. */
+ /* We shouldn't really be seeing TPREL32. */
case R_PPC_TPREL32:
case R_PPC_TPREL16:
case R_PPC_TPREL16_LO:
case R_PPC_TPREL16_HI:
case R_PPC_TPREL16_HA:
- if (bfd_link_pic (info))
+ if (bfd_link_dll (info))
info->flags |= DF_STATIC_TLS;
goto dodyn;
error = TRUE;
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: uses different e_flags (0x%lx) fields "
- "than previous modules (0x%lx)"),
- ibfd, (long) new_flags, (long) old_flags);
+ (_("%B: uses different e_flags (%#x) fields "
+ "than previous modules (%#x)"),
+ ibfd, new_flags, old_flags);
}
if (error)
unsigned int insn, opcode, top5;
insn = bfd_get_32 (input_bfd, loc);
- opcode = insn & 0xf300f800;
+ opcode = insn & 0xfc00f800;
if (opcode == E_OR2I_INSN
|| opcode == E_AND2I_DOT_INSN
|| opcode == E_OR2IS_INSN
insn |= value & 0x7ff;
bfd_put_32 (input_bfd, insn, loc);
}
+
+static void
+ppc_elf_vle_split20 (bfd *output_bfd, bfd_byte *loc, bfd_vma value)
+{
+ unsigned int insn;
+
+ insn = bfd_get_32 (output_bfd, loc);
+ /* We have an li20 field, bits 17..20, 11..15, 21..31. */
+ /* Top 4 bits of value to 17..20. */
+ insn |= (value & 0xf0000) >> 5;
+ /* Next 5 bits of the value to 11..15. */
+ insn |= (value & 0xf800) << 5;
+ /* And the final 11 bits of the value to bits 21 to 31. */
+ insn |= value & 0x7ff;
+ bfd_put_32 (output_bfd, insn, loc);
+}
+
\f
/* Choose which PLT scheme to use, and set .plt flags appropriately.
Returns -1 on error, 0 for old PLT, 1 for new PLT. */
|| h->needs_plt)
&& h->ref_regular
&& !(SYMBOL_CALLS_LOCAL (info, h)
- || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
- && h->root.type == bfd_link_hash_undefweak)))
+ || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)))
{
/* Profiling of shared libs (and pies) is not supported with
secure plt, because ppc32 does profiling before a
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
-
-/* Update the got, plt and dynamic reloc reference counts for the
- section being removed. */
-
-static bfd_boolean
-ppc_elf_gc_sweep_hook (bfd *abfd,
- struct bfd_link_info *info,
- asection *sec,
- const Elf_Internal_Rela *relocs)
-{
- struct ppc_elf_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;
- asection *got2;
-
- if (bfd_link_relocatable (info))
- return TRUE;
-
- if ((sec->flags & SEC_ALLOC) == 0)
- return TRUE;
-
- elf_section_data (sec)->local_dynrel = NULL;
-
- htab = ppc_elf_hash_table (info);
- symtab_hdr = &elf_symtab_hdr (abfd);
- sym_hashes = elf_sym_hashes (abfd);
- local_got_refcounts = elf_local_got_refcounts (abfd);
- got2 = bfd_get_section_by_name (abfd, ".got2");
-
- relend = relocs + sec->reloc_count;
- for (rel = relocs; rel < relend; rel++)
- {
- unsigned long r_symndx;
- enum elf_ppc_reloc_type 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_dyn_relocs **pp, *p;
- struct ppc_elf_link_hash_entry *eh;
-
- 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 ppc_elf_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 = ELF32_R_TYPE (rel->r_info);
- if (!htab->is_vxworks
- && h == NULL
- && local_got_refcounts != NULL
- && (!bfd_link_pic (info)
- || is_branch_reloc (r_type)))
- {
- struct plt_entry **local_plt = (struct plt_entry **)
- (local_got_refcounts + symtab_hdr->sh_info);
- char *local_got_tls_masks = (char *)
- (local_plt + symtab_hdr->sh_info);
- if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
- {
- struct plt_entry **ifunc = local_plt + r_symndx;
- bfd_vma addend = 0;
- struct plt_entry *ent;
-
- if (r_type == R_PPC_PLTREL24 && bfd_link_pic (info))
- addend = rel->r_addend;
- ent = find_plt_ent (ifunc, got2, addend);
- if (ent->plt.refcount > 0)
- ent->plt.refcount -= 1;
- continue;
- }
- }
-
- switch (r_type)
- {
- case R_PPC_GOT_TLSLD16:
- case R_PPC_GOT_TLSLD16_LO:
- case R_PPC_GOT_TLSLD16_HI:
- case R_PPC_GOT_TLSLD16_HA:
- case R_PPC_GOT_TLSGD16:
- case R_PPC_GOT_TLSGD16_LO:
- case R_PPC_GOT_TLSGD16_HI:
- case R_PPC_GOT_TLSGD16_HA:
- case R_PPC_GOT_TPREL16:
- case R_PPC_GOT_TPREL16_LO:
- case R_PPC_GOT_TPREL16_HI:
- case R_PPC_GOT_TPREL16_HA:
- case R_PPC_GOT_DTPREL16:
- case R_PPC_GOT_DTPREL16_LO:
- case R_PPC_GOT_DTPREL16_HI:
- case R_PPC_GOT_DTPREL16_HA:
- case R_PPC_GOT16:
- case R_PPC_GOT16_LO:
- case R_PPC_GOT16_HI:
- case R_PPC_GOT16_HA:
- if (h != NULL)
- {
- if (h->got.refcount > 0)
- h->got.refcount--;
- if (!bfd_link_pic (info))
- {
- struct plt_entry *ent;
-
- ent = find_plt_ent (&h->plt.plist, NULL, 0);
- if (ent != NULL && ent->plt.refcount > 0)
- ent->plt.refcount -= 1;
- }
- }
- else if (local_got_refcounts != NULL)
- {
- if (local_got_refcounts[r_symndx] > 0)
- local_got_refcounts[r_symndx]--;
- }
- break;
-
- case R_PPC_REL24:
- case R_PPC_REL14:
- case R_PPC_REL14_BRTAKEN:
- case R_PPC_REL14_BRNTAKEN:
- case R_PPC_REL32:
- if (h == NULL || h == htab->elf.hgot)
- break;
- /* Fall through. */
-
- case R_PPC_ADDR32:
- case R_PPC_ADDR24:
- case R_PPC_ADDR16:
- case R_PPC_ADDR16_LO:
- case R_PPC_ADDR16_HI:
- case R_PPC_ADDR16_HA:
- case R_PPC_ADDR14:
- case R_PPC_ADDR14_BRTAKEN:
- case R_PPC_ADDR14_BRNTAKEN:
- case R_PPC_UADDR32:
- case R_PPC_UADDR16:
- if (bfd_link_pic (info))
- break;
- /* Fall through. */
-
- case R_PPC_PLT32:
- case R_PPC_PLTREL24:
- case R_PPC_PLTREL32:
- case R_PPC_PLT16_LO:
- case R_PPC_PLT16_HI:
- case R_PPC_PLT16_HA:
- if (h != NULL)
- {
- bfd_vma addend = 0;
- struct plt_entry *ent;
-
- if (r_type == R_PPC_PLTREL24 && bfd_link_pic (info))
- addend = rel->r_addend;
- ent = find_plt_ent (&h->plt.plist, got2, addend);
- if (ent != NULL && ent->plt.refcount > 0)
- ent->plt.refcount -= 1;
- }
- break;
-
- default:
- break;
- }
- }
- return TRUE;
-}
\f
/* Set plt output section type, htab->tls_get_addr, and call the
generic ELF tls_setup function. */
&& (tga->type == STT_FUNC
|| tga->needs_plt)
&& !(SYMBOL_CALLS_LOCAL (info, tga)
- || (ELF_ST_VISIBILITY (tga->other) != STV_DEFAULT
- && tga->root.type == bfd_link_hash_undefweak)))
+ || UNDEFWEAK_NO_DYNAMIC_RELOC (info, tga)))
{
struct plt_entry *ent;
for (ent = tga->plt.plist; ent != NULL; ent = ent->next)
symtab_hdr->contents = (unsigned char *) locsyms;
}
}
+ htab->do_tls_opt = 1;
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
+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)))
- 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)
- || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
- && h->root.type == bfd_link_hash_undefweak))))
+ || (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))
{
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;
+ 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)
- h->non_got_ref = h->u.weakdef->non_got_ref;
+ h->non_got_ref = def->non_got_ref;
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
we'll be keeping the dynamic relocs and avoiding the copy reloc.
&& !ppc_elf_hash_entry (h)->has_sda_refs
&& !htab->is_vxworks
&& !h->def_regular
- && !readonly_dynrelocs (h))
- {
- 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
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;
}
-/* If H is undefined weak, make it dynamic if that makes sense. */
+/* 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
-ensure_undefweak_dynamic (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
+ensure_undef_dynamic (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
{
struct elf_link_hash_table *htab = elf_hash_table (info);
if (htab->dynamic_sections_created
- && h->root.type == bfd_link_hash_undefweak
+ && ((info->dynamic_undefined_weak != 0
+ && h->root.type == bfd_link_hash_undefweak)
+ || h->root.type == bfd_link_hash_undefined)
&& h->dynindx == -1
&& !h->forced_local
&& ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
{
unsigned int need;
- /* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
- if (!ensure_undefweak_dynamic (info, &eh->elf))
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (!ensure_undef_dynamic (info, &eh->elf))
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
|| (htab->elf.dynamic_sections_created
&& eh->elf.dynindx != -1
&& !SYMBOL_REFERENCES_LOCAL (info, &eh->elf)))
- && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
- || eh->elf.root.type != bfd_link_hash_undefweak))
+ && !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;
}
}
}
else
eh->elf.got.offset = (bfd_vma) -1;
+ /* If no dynamic sections we can't have dynamic relocs, except for
+ IFUNCs which are handled even in static executables. */
if (!htab->elf.dynamic_sections_created
&& 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)
;
}
}
- /* Discard relocs on undefined symbols that must be local. */
- if (eh->dyn_relocs != NULL
- && h->root.type == bfd_link_hash_undefined
- && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
- || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
- eh->dyn_relocs = NULL;
-
- /* Also discard relocs on undefined weak syms with non-default
- visibility. */
- if (eh->dyn_relocs != NULL
- && h->root.type == bfd_link_hash_undefweak)
+ if (eh->dyn_relocs != NULL)
{
- if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
- eh->dyn_relocs = NULL;
-
- /* Make sure undefined weak symbols are output as a dynamic
- symbol in PIEs. */
- else if (!ensure_undefweak_dynamic (info, h))
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (!ensure_undef_dynamic (info, h))
return FALSE;
}
}
/* 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
&& htab->params->pic_fixup > 0))
{
- /* Make sure this symbol is output as a dynamic symbol.
- Undefined weak syms won't yet be marked as dynamic. */
- if (!ensure_undefweak_dynamic (info, h))
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (!ensure_undef_dynamic (info, h))
return FALSE;
if (h->dynindx == -1)
read-only sections. */
static bfd_boolean
-maybe_set_textrel (struct elf_link_hash_entry *h, void *info)
+maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
{
+ asection *sec;
+
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- if (readonly_dynrelocs (h))
+ sec = readonly_dynrelocs (h);
+ if (sec != NULL)
{
- ((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
+ struct bfd_link_info *info = (struct bfd_link_info *) info_p;
+
+ info->flags |= DF_TEXTREL;
+ info->callbacks->minfo
+ (_("%B: dynamic relocation in read-only section `%A'\n"),
+ sec->owner, sec);
/* Not an error, just cut short the traversal. */
return FALSE;
if ((p->sec->output_section->flags
& (SEC_READONLY | SEC_ALLOC))
== (SEC_READONLY | SEC_ALLOC))
- info->flags |= DF_TEXTREL;
+ {
+ info->flags |= DF_TEXTREL;
+ info->callbacks->minfo (_("%B: dynamic relocation in read-only section `%A'\n"),
+ p->sec->owner, p->sec);
+ }
}
}
}
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;
}
}
}
wrel->r_addend = 0;
/* For ld -r, remove relocations in debug sections against
- sections defined in discarded sections. Not done for
+ symbols defined in discarded sections. Not done for
non-debug to preserve relocs in .eh_frame which the
eh_frame editing code expects to be present. */
if (bfd_link_relocatable (info)
wrel->r_info = ELF32_R_INFO (0, R_PPC_ADDR16_HA);
wrel->r_addend = got_addr;
insn &= ~0xffff;
- insn |= ((unsigned int )(got_addr + 0x8000) >> 16) & 0xffff;
+ insn |= ((unsigned int) (got_addr + 0x8000) >> 16) & 0xffff;
bfd_put_32 (input_bfd, insn, p);
/* Convert lis to lwz, loading address from GOT. */
r_type = R_PPC_GOT16_LO;
}
else
- info->callbacks->einfo
+ _bfd_error_handler
/* xgettext:c-format */
- (_("%H: error: %s with unexpected instruction %x\n"),
+ (_("%B(%A+%#Lx): error: %s with unexpected instruction %#x"),
input_bfd, input_section, rel->r_offset,
"R_PPC_ADDR16_HA", insn);
}
rel->r_info = ELF32_R_INFO (0, r_type);
}
else
- info->callbacks->einfo
+ _bfd_error_handler
/* xgettext:c-format */
- (_("%H: error: %s with unexpected instruction %x\n"),
+ (_("%B(%A+%#Lx): error: %s with unexpected instruction %#x"),
input_bfd, input_section, rel->r_offset,
"R_PPC_ADDR16_LO", insn);
}
loc += (htab->elf.irelplt->reloc_count++
* sizeof (Elf32_External_Rela));
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
+ htab->local_ifunc_resolver = 1;
ent->plt.offset |= 1;
}
}
addend = rel->r_addend;
- tls_type = 0;
howto = NULL;
if (r_type < R_PPC_max)
howto = ppc_elf_howto_table[r_type];
+
+ switch (r_type)
+ {
+ default:
+ break;
+
+ case R_PPC_TPREL16_HA:
+ if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+ {
+ bfd_byte *p = contents + (rel->r_offset & ~3);
+ unsigned int insn = bfd_get_32 (input_bfd, p);
+ if ((insn & ((0x3f << 26) | 0x1f << 16))
+ != ((15u << 26) | (2 << 16)) /* addis rt,2,imm */)
+ /* xgettext:c-format */
+ info->callbacks->minfo
+ (_("%H: warning: %s unexpected insn %#x.\n"),
+ input_bfd, input_section, rel->r_offset, howto->name, insn);
+ else
+ bfd_put_32 (input_bfd, NOP, p);
+ }
+ break;
+
+ case R_PPC_TPREL16_LO:
+ if (htab->do_tls_opt && relocation + addend + 0x8000 < 0x10000)
+ {
+ bfd_byte *p = contents + (rel->r_offset & ~3);
+ unsigned int insn = bfd_get_32 (input_bfd, p);
+ insn &= ~(0x1f << 16);
+ insn |= 2 << 16;
+ bfd_put_32 (input_bfd, insn, p);
+ }
+ break;
+ }
+
+ tls_type = 0;
switch (r_type)
{
default:
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1
|| SYMBOL_REFERENCES_LOCAL (info, h)
- || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
- && h->root.type == bfd_link_hash_undefweak))
+ || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
locally, or the symbol was forced to be local
if (indx != 0
|| (bfd_link_pic (info)
&& (h == NULL
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
- || h->root.type != bfd_link_hash_undefweak
- || offp == &htab->tlsld_got.offset)))
+ || !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
+ || 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;
if (ifunc != NULL)
- rsec = htab->elf.irelplt;
+ {
+ rsec = htab->elf.irelplt;
+ if (indx == 0)
+ htab->local_ifunc_resolver = 1;
+ else if (is_static_defined (h))
+ htab->maybe_local_ifunc_resolver = 1;
+ }
outrel.r_offset = (htab->elf.sgot->output_section->vma
+ htab->elf.sgot->output_offset
+ off);
else
{
bfd_vma value = relocation;
- int tlsopt = (htab->plt_type == PLT_NEW
- && !htab->params->no_tls_get_addr_opt
- && htab->tls_get_addr != NULL
- && htab->tls_get_addr->plt.plist != NULL);
if (tls_ty != 0)
{
value = 0;
else
value -= htab->elf.tls_sec->vma + DTP_OFFSET;
- if ((tls_ty & TLS_TPREL)
- || (tlsopt && !(tls_ty & TLS_DTPREL)))
+ if (tls_ty & TLS_TPREL)
value += DTP_OFFSET - TP_OFFSET;
}
{
bfd_put_32 (input_bfd, value,
htab->elf.sgot->contents + off + 4);
- value = !tlsopt;
+ value = 1;
}
}
bfd_put_32 (input_bfd, value,
if (htab->elf.tls_sec != NULL)
addend -= htab->elf.tls_sec->vma + TP_OFFSET;
/* The TPREL16 relocs shouldn't really be used in shared
- libs as they will result in DT_TEXTREL being set, but
- support them anyway. */
+ libs or with non-local symbols as that will result in
+ DT_TEXTREL being set, but support them anyway. */
goto dodyn;
case R_PPC_TPREL32:
|| is_vxworks_tls)
break;
- if ((bfd_link_pic (info)
- && !(h != NULL
- && ((h->root.type == bfd_link_hash_undefined
- && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
- || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
- || (h->root.type == bfd_link_hash_undefweak
- && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)))
- && (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;
asection *sreloc;
+ long indx = 0;
+
#ifdef DEBUG
fprintf (stderr, "ppc_elf_relocate_section needs to "
"create relocation for %s\n",
/* When generating a shared object, these relocations
are copied into the output file to be resolved at run
time. */
- sreloc = elf_section_data (input_section)->sreloc;
- if (ifunc)
- sreloc = htab->elf.irelplt;
- if (sreloc == NULL)
- return FALSE;
-
skip = 0;
outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
input_section,
if (skip)
memset (&outrel, 0, sizeof outrel);
- else if ((h != NULL
- && (h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak))
- || !SYMBOL_REFERENCES_LOCAL (info, h))
+ else if (!SYMBOL_REFERENCES_LOCAL (info, h))
{
- BFD_ASSERT (h->dynindx != -1);
+ indx = h->dynindx;
+ BFD_ASSERT (indx != -1);
unresolved_reloc = FALSE;
- outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
+ outrel.r_info = ELF32_R_INFO (indx, r_type);
outrel.r_addend = rel->r_addend;
}
else
if (r_type != R_PPC_ADDR32)
{
- long indx = 0;
-
if (ifunc != NULL)
{
/* If we get here when building a static
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
}
+ sreloc = elf_section_data (input_section)->sreloc;
+ if (ifunc)
+ {
+ sreloc = htab->elf.irelplt;
+ if (indx == 0)
+ htab->local_ifunc_resolver = 1;
+ else if (is_static_defined (h))
+ htab->maybe_local_ifunc_resolver = 1;
+ }
+ if (sreloc == NULL)
+ return FALSE;
+
loc = sreloc->contents;
loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
break;
}
}
- else if (r_type == R_PPC_DTPMOD32
- && htab->plt_type == PLT_NEW
- && !htab->params->no_tls_get_addr_opt
- && htab->tls_get_addr != NULL
- && htab->tls_get_addr->plt.plist != NULL)
- {
- /* Set up for __tls_get_addr_opt stub when this entry
- does not have dynamic relocs. */
- relocation = 0;
- /* Set up the next word for local dynamic. If it turns
- out to be global dynamic, the reloc will overwrite
- this value. */
- if (rel->r_offset + 8 <= input_section->size)
- bfd_put_32 (input_bfd, DTP_OFFSET - TP_OFFSET,
- contents + rel->r_offset + 4);
- }
- else if (r_type == R_PPC_DTPREL32
- && htab->plt_type == PLT_NEW
- && !htab->params->no_tls_get_addr_opt
- && htab->tls_get_addr != NULL
- && htab->tls_get_addr->plt.plist != NULL
- && rel > relocs
- && rel[-1].r_info == ELF32_R_INFO (r_symndx, R_PPC_DTPMOD32)
- && rel[-1].r_offset + 4 == rel->r_offset)
- {
- /* __tls_get_addr_opt stub value. */
- addend += DTP_OFFSET - TP_OFFSET;
- }
break;
case R_PPC_RELAX_PLT:
}
goto copy_reloc;
+ case R_PPC_VLE_ADDR20:
+ ppc_elf_vle_split20 (output_bfd, contents + rel->r_offset, relocation);
+ continue;
+
/* Relocate against the beginning of the section. */
case R_PPC_SECTOFF:
case R_PPC_SECTOFF_LO:
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
- loc = (htab->elf.irelplt->contents
- + (htab->elf.irelplt->reloc_count++
- * sizeof (Elf32_External_Rela)));
+ {
+ loc = (htab->elf.irelplt->contents
+ + (htab->elf.irelplt->reloc_count++
+ * sizeof (Elf32_External_Rela)));
+ htab->local_ifunc_resolver = 1;
+ }
else
- loc = (htab->elf.srelplt->contents
- + reloc_index * sizeof (Elf32_External_Rela));
+ {
+ loc = (htab->elf.srelplt->contents
+ + reloc_index * sizeof (Elf32_External_Rela));
+ if (h->type == STT_GNU_IFUNC && is_static_defined (h))
+ htab->maybe_local_ifunc_resolver = 1;
+ }
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
if (!h->def_regular)
if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->relsbss;
- else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ else if (h->root.u.def.section == htab->elf.sdynrelro)
s = htab->elf.sreldynrelro;
else
s = htab->elf.srelbss;
dyn.d_un.d_ptr = got;
break;
+ case DT_TEXTREL:
+ if (htab->local_ifunc_resolver)
+ info->callbacks->einfo
+ (_("%X%P: text relocations and GNU indirect "
+ "functions will result in a segfault at runtime\n"));
+ else if (htab->maybe_local_ifunc_resolver)
+ info->callbacks->einfo
+ (_("%P: warning: text relocations and GNU indirect "
+ "functions may result in a segfault at runtime\n"));
+ continue;
+
default:
if (htab->is_vxworks
&& elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
#define elf_backend_object_p ppc_elf_object_p
#define elf_backend_gc_mark_hook ppc_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook ppc_elf_gc_sweep_hook
#define elf_backend_section_from_shdr ppc_elf_section_from_shdr
#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
#define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections
#define elf_backend_fake_sections ppc_elf_fake_sections
#define elf_backend_additional_program_headers ppc_elf_additional_program_headers
-#define elf_backend_modify_segment_map ppc_elf_modify_segment_map
+#define elf_backend_modify_segment_map ppc_elf_modify_segment_map
#define elf_backend_grok_prstatus ppc_elf_grok_prstatus
#define elf_backend_grok_psinfo ppc_elf_grok_psinfo
#define elf_backend_write_core_note ppc_elf_write_core_note
/* VxWorks uses the elf default section flags for .plt. */
static const struct bfd_elf_special_section *
-ppc_elf_vxworks_get_sec_type_attr (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
+ppc_elf_vxworks_get_sec_type_attr (bfd *abfd, asection *sec)
{
if (sec->name == NULL)
return NULL;
if (ret)
{
struct ppc_elf_link_hash_table *htab
- = (struct ppc_elf_link_hash_table *)ret;
+ = (struct ppc_elf_link_hash_table *)ret;
htab->is_vxworks = 1;
htab->plt_type = PLT_VXWORKS;
htab->plt_entry_size = VXWORKS_PLT_ENTRY_SIZE;
ppc_elf_vxworks_add_symbol_hook (bfd *abfd,
struct bfd_link_info *info,
Elf_Internal_Sym *sym,
- const char **namep ATTRIBUTE_UNUSED,
- flagword *flagsp ATTRIBUTE_UNUSED,
+ const char **namep,
+ flagword *flagsp,
asection **secp,
bfd_vma *valp)
{
- if (!elf_vxworks_add_symbol_hook(abfd, info, sym,namep, flagsp, secp,
- valp))
+ if (!elf_vxworks_add_symbol_hook (abfd, info, sym, namep, flagsp, secp,
+ valp))
return FALSE;
- return ppc_elf_add_symbol_hook(abfd, info, sym,namep, flagsp, secp, valp);
+ return ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp);
}
static void
ppc_elf_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
{
- ppc_elf_final_write_processing(abfd, linker);
- elf_vxworks_final_write_processing(abfd, linker);
+ ppc_elf_final_write_processing (abfd, linker);
+ elf_vxworks_final_write_processing (abfd, linker);
}
/* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so