/* PowerPC-specific support for 32-bit ELF
- Copyright (C) 1994-2017 Free Software Foundation, Inc.
+ Copyright (C) 1994-2018 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of BFD, the Binary File Descriptor library.
/* For new-style .glink and .plt. */
#define GLINK_PLTRESOLVE 16*4
-#define GLINK_ENTRY_SIZE 4*4
-#define TLS_GET_ADDR_GLINK_SIZE 12*4
+#define GLINK_ENTRY_SIZE(htab, h) \
+ ((4*4 \
+ + (h != NULL \
+ && h == htab->tls_get_addr \
+ && !htab->params->no_tls_get_addr_opt ? 8*4 : 0) \
+ + (1u << htab->params->plt_stub_align) - 1) \
+ & -(1u << htab->params->plt_stub_align))
/* VxWorks uses its own plt layout, filled in by the static linker. */
static const bfd_vma ppc_elf_vxworks_plt_entry
[VXWORKS_PLT_ENTRY_SIZE / 4] =
{
- 0x3d800000, /* lis r12,0 */
- 0x818c0000, /* lwz r12,0(r12) */
- 0x7d8903a6, /* mtctr r12 */
- 0x4e800420, /* bctr */
- 0x39600000, /* li r11,0 */
- 0x48000000, /* b 14 <.PLT0resolve+0x4> */
- 0x60000000, /* nop */
- 0x60000000, /* nop */
+ 0x3d800000, /* lis r12,0 */
+ 0x818c0000, /* lwz r12,0(r12) */
+ 0x7d8903a6, /* mtctr r12 */
+ 0x4e800420, /* bctr */
+ 0x39600000, /* li r11,0 */
+ 0x48000000, /* b 14 <.PLT0resolve+0x4> */
+ 0x60000000, /* nop */
+ 0x60000000, /* nop */
};
static const bfd_vma ppc_elf_vxworks_pic_plt_entry
[VXWORKS_PLT_ENTRY_SIZE / 4] =
static const bfd_vma ppc_elf_vxworks_plt0_entry
[VXWORKS_PLT_INITIAL_ENTRY_SIZE / 4] =
{
- 0x3d800000, /* lis r12,0 */
- 0x398c0000, /* addi r12,r12,0 */
- 0x800c0008, /* lwz r0,8(r12) */
- 0x7c0903a6, /* mtctr r0 */
- 0x818c0004, /* lwz r12,4(r12) */
- 0x4e800420, /* bctr */
- 0x60000000, /* nop */
- 0x60000000, /* nop */
+ 0x3d800000, /* lis r12,0 */
+ 0x398c0000, /* addi r12,r12,0 */
+ 0x800c0008, /* lwz r0,8(r12) */
+ 0x7c0903a6, /* mtctr r0 */
+ 0x818c0004, /* lwz r12,4(r12) */
+ 0x4e800420, /* bctr */
+ 0x60000000, /* nop */
+ 0x60000000, /* nop */
};
static const bfd_vma ppc_elf_vxworks_pic_plt0_entry
[VXWORKS_PLT_INITIAL_ENTRY_SIZE / 4] =
{
0x819e0008, /* lwz r12,8(r30) */
- 0x7d8903a6, /* mtctr r12 */
+ 0x7d8903a6, /* mtctr r12 */
0x819e0004, /* lwz r12,4(r30) */
- 0x4e800420, /* bctr */
- 0x60000000, /* nop */
- 0x60000000, /* nop */
- 0x60000000, /* nop */
- 0x60000000, /* nop */
+ 0x4e800420, /* bctr */
+ 0x60000000, /* nop */
+ 0x60000000, /* nop */
+ 0x60000000, /* nop */
+ 0x60000000, /* nop */
};
/* For executables, we have some additional relocations in
/* Set the howto pointer for a PowerPC ELF reloc. */
-static void
+static bfd_boolean
ppc_elf_info_to_howto (bfd *abfd,
arelent *cache_ptr,
Elf_Internal_Rela *dst)
if (r_type >= R_PPC_max)
{
/* xgettext:c-format */
- _bfd_error_handler (_("%B: unrecognised PPC reloc number: %d"),
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
abfd, r_type);
bfd_set_error (bfd_error_bad_value);
- r_type = R_PPC_NONE;
+ return FALSE;
}
+
cache_ptr->howto = ppc_elf_howto_table[r_type];
/* Just because the above assert didn't trigger doesn't mean that
ELF32_R_TYPE (dst->r_info) is necessarily a valid relocation. */
- if (!cache_ptr->howto)
+ if (cache_ptr->howto == NULL)
{
/* xgettext:c-format */
- _bfd_error_handler (_("%B: invalid relocation type %d"),
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
abfd, r_type);
bfd_set_error (bfd_error_bad_value);
- cache_ptr->howto = ppc_elf_howto_table[R_PPC_NONE];
+ return FALSE;
}
+
+ return TRUE;
}
/* Handle the R_PPC_ADDR16_HA and R_PPC_REL16_HA relocs. */
/* This is what we want for new plt/got. */
static struct bfd_elf_special_section ppc_alt_plt =
- { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC };
+ { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC };
static const struct bfd_elf_special_section *
ppc_elf_get_sec_type_attr (bfd *abfd, asection *sec)
continue;
/* xgettext:c-format */
- error_message = _("corrupt %s section in %B");
+ error_message = _("corrupt %s section in %pB");
length = asec->size;
if (length < 20)
goto fail;
|| (bfd_bread (buffer, length, ibfd) != length))
{
/* xgettext:c-format */
- error_message = _("unable to read in %s section from %B");
+ error_message = _("unable to read in %s section from %pB");
goto fail;
}
{
ibfd = abfd;
/* xgettext:c-format */
- error_message = _("warning: unable to set size of %s section in %B");
+ error_message = _("warning: unable to set size of %s section in %pB");
}
}
if (buffer == NULL)
{
_bfd_error_handler
- (_("failed to allocate space for new APUinfo section."));
+ (_("failed to allocate space for new APUinfo section"));
return;
}
}
if (length != asec->size)
- _bfd_error_handler (_("failed to compute new APUinfo section."));
+ _bfd_error_handler (_("failed to compute new APUinfo section"));
if (! bfd_set_section_contents (abfd, asec, buffer, (file_ptr) 0, length))
- _bfd_error_handler (_("failed to install new APUinfo section."));
+ _bfd_error_handler (_("failed to install new APUinfo section"));
free (buffer);
static bfd_boolean
is_nonpic_glink_stub (bfd *abfd, asection *glink, bfd_vma off)
{
- bfd_byte buf[GLINK_ENTRY_SIZE];
+ bfd_byte buf[4 * 4];
- if (!bfd_get_section_contents (abfd, glink, buf, off, GLINK_ENTRY_SIZE))
+ if (!bfd_get_section_contents (abfd, glink, buf, off, sizeof buf))
return FALSE;
return ((bfd_get_32 (abfd, buf + 0) & 0xffff0000) == LIS_11
asection *plt, *relplt, *dynamic, *glink;
bfd_vma glink_vma = 0;
bfd_vma resolv_vma = 0;
- bfd_vma stub_vma;
+ bfd_vma stub_off;
asymbol *s;
arelent *p;
- long count, i;
+ long count, i, stub_delta;
size_t size;
char *names;
bfd_byte buf[4];
/* If the stubs are those for -shared/-pie then we might have
multiple stubs for each plt entry. If that is the case then
there is no way to associate stubs with their plt entries short
- of figuring out the GOT pointer value used in the stub. */
- if (!is_nonpic_glink_stub (abfd, glink,
- glink_vma - GLINK_ENTRY_SIZE - glink->vma))
+ of figuring out the GOT pointer value used in the stub.
+ The offsets tested here need to cover all possible values of
+ GLINK_ENTRY_SIZE for other than __tls_get_addr_opt. */
+ stub_off = glink_vma - glink->vma;
+ for (stub_delta = 16; stub_delta <= 32; stub_delta += 8)
+ if (is_nonpic_glink_stub (abfd, glink, stub_off - stub_delta))
+ break;
+ if (stub_delta > 32)
return 0;
slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
if (s == NULL)
return -1;
- stub_vma = glink_vma;
+ stub_off = glink_vma - glink->vma;
names = (char *) (s + count + 1 + (resolv_vma != 0));
p = relplt->relocation + count - 1;
for (i = 0; i < count; i++)
{
size_t len;
+ stub_off -= stub_delta;
+ if (strcmp ((*p->sym_ptr_ptr)->name, "__tls_get_addr_opt") == 0)
+ stub_off -= 32;
*s = **p->sym_ptr_ptr;
/* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set. Since
we are defining a symbol, ensure one of them is set. */
s->flags |= BSF_GLOBAL;
s->flags |= BSF_SYNTHETIC;
s->section = glink;
- stub_vma -= 16;
- if (strcmp ((*p->sym_ptr_ptr)->name, "__tls_get_addr_opt") == 0)
- stub_vma -= 32;
- s->value = stub_vma - glink->vma;
+ s->value = stub_off;
s->name = names;
s->udata.p = NULL;
len = strlen ((*p->sym_ptr_ptr)->name);
{
struct ppc_elf_link_hash_table *ret;
static struct ppc_elf_params default_params
- = { PLT_OLD, 0, 1, 0, 0, 12, 0, 0, 0 };
+ = { PLT_OLD, 0, 0, 1, 0, 0, 12, 0, 0, 0 };
ret = bfd_zmalloc (sizeof (struct ppc_elf_link_hash_table));
if (ret == NULL)
struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
asection *s;
flagword flags;
+ int p2align;
flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
s = bfd_make_section_anyway_with_flags (abfd, ".glink", flags);
htab->glink = s;
+ p2align = htab->params->ppc476_workaround ? 6 : 4;
+ if (p2align < htab->params->plt_stub_align)
+ p2align = htab->params->plt_stub_align;
if (s == NULL
- || !bfd_set_section_alignment (abfd, s,
- htab->params->ppc476_workaround ? 6 : 4))
+ || !bfd_set_section_alignment (abfd, s, p2align))
return FALSE;
if (!info->no_ld_generated_unwind_info)
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;
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: relocation %s cannot be used when making a shared object"),
+ (_("%pB: relocation %s cannot be used when making a shared object"),
abfd,
ppc_elf_howto_table[r_type]->name);
bfd_set_error (bfd_error_bad_value);
return TRUE;
#ifdef DEBUG
- _bfd_error_handler ("ppc_elf_check_relocs called for section %A in %B",
+ _bfd_error_handler ("ppc_elf_check_relocs called for section %pA in %pB",
sec, abfd);
#endif
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.
else if (out_fp != 2 && in_fp == 2)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses hard float, %B uses soft float"), obfd, ibfd);
+ (_("warning: %pB uses hard float, %pB uses soft float"), obfd, ibfd);
else if (out_fp == 2 && in_fp != 2)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses hard float, %B uses soft float"), ibfd, obfd);
+ (_("warning: %pB uses hard float, %pB uses soft float"), ibfd, obfd);
else if (out_fp == 1 && in_fp == 3)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses double-precision hard float, "
- "%B uses single-precision hard float"), obfd, ibfd);
+ (_("warning: %pB uses double-precision hard float, "
+ "%pB uses single-precision hard float"), obfd, ibfd);
else if (out_fp == 3 && in_fp == 1)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses double-precision hard float, "
- "%B uses single-precision hard float"), ibfd, obfd);
+ (_("warning: %pB uses double-precision hard float, "
+ "%pB uses single-precision hard float"), ibfd, obfd);
in_fp = in_attr->i & 0xc;
out_fp = out_attr->i & 0xc;
else if (out_fp != 2 * 4 && in_fp == 2 * 4)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses 64-bit long double, "
- "%B uses 128-bit long double"), ibfd, obfd);
+ (_("warning: %pB uses 64-bit long double, "
+ "%pB uses 128-bit long double"), ibfd, obfd);
else if (in_fp != 2 * 4 && out_fp == 2 * 4)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses 64-bit long double, "
- "%B uses 128-bit long double"), obfd, ibfd);
+ (_("warning: %pB uses 64-bit long double, "
+ "%pB uses 128-bit long double"), obfd, ibfd);
else if (out_fp == 1 * 4 && in_fp == 3 * 4)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses IBM long double, "
- "%B uses IEEE long double"), ibfd, obfd);
+ (_("warning: %pB uses IBM long double, "
+ "%pB uses IEEE long double"), ibfd, obfd);
else if (out_fp == 3 * 4 && in_fp == 1 * 4)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses IBM long double, "
- "%B uses IEEE long double"), obfd, ibfd);
+ (_("warning: %pB uses IBM long double, "
+ "%pB uses IEEE long double"), obfd, ibfd);
}
}
else if (out_vec < in_vec)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses AltiVec vector ABI, %B uses SPE vector ABI"),
+ (_("warning: %pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
obfd, ibfd);
else if (out_vec > in_vec)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses AltiVec vector ABI, %B uses SPE vector ABI"),
+ (_("warning: %pB uses AltiVec vector ABI, %pB uses SPE vector ABI"),
ibfd, obfd);
}
else if (out_struct < in_struct)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses r3/r4 for small structure returns, "
- "%B uses memory"), obfd, ibfd);
+ (_("warning: %pB uses r3/r4 for small structure returns, "
+ "%pB uses memory"), obfd, ibfd);
else if (out_struct > in_struct)
_bfd_error_handler
/* xgettext:c-format */
- (_("Warning: %B uses r3/r4 for small structure returns, "
- "%B uses memory"), ibfd, obfd);
+ (_("warning: %pB uses r3/r4 for small structure returns, "
+ "%pB uses memory"), ibfd, obfd);
}
/* Merge Tag_compatibility attributes and any common GNU ones. */
{
error = TRUE;
_bfd_error_handler
- (_("%B: compiled with -mrelocatable and linked with "
+ (_("%pB: compiled with -mrelocatable and linked with "
"modules compiled normally"), ibfd);
}
else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
{
error = TRUE;
_bfd_error_handler
- (_("%B: compiled normally and linked with "
+ (_("%pB: compiled normally and linked with "
"modules compiled with -mrelocatable"), ibfd);
}
error = TRUE;
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: uses different e_flags (%#x) fields "
+ (_("%pB: uses different e_flags (%#x) fields "
"than previous modules (%#x)"),
ibfd, new_flags, old_flags);
}
else
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+0x%lx): expected 16A style relocation on 0x%08x insn"),
+ (_("%pB(%pA+0x%lx): expected 16A style relocation on 0x%08x insn"),
input_bfd, input_section, offset, opcode);
}
}
else
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+0x%lx): expected 16D style relocation on 0x%08x insn"),
+ (_("%pB(%pA+0x%lx): expected 16D style relocation on 0x%08x insn"),
input_bfd, input_section, offset, opcode);
}
}
if (htab->plt_type == PLT_OLD && htab->params->plt_style == PLT_NEW)
{
if (htab->old_bfd != NULL)
- info->callbacks->einfo (_("%P: bss-plt forced due to %B\n"),
- htab->old_bfd);
+ _bfd_error_handler (_("bss-plt forced due to %pB"), htab->old_bfd);
else
- info->callbacks->einfo (_("%P: bss-plt forced by profiling\n"));
+ _bfd_error_handler (_("bss-plt forced by profiling"));
}
BFD_ASSERT (htab->plt_type != PLT_VXWORKS);
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;
+}
+
/* 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
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)
{
- /* Prior to adjust_dynamic_symbol, non_got_ref set means that
- we might need to generate a copy reloc for this symbol.
- After adjust_dynamic_symbol, non_got_ref is only relevant for
- non-pic and means that the symbol might have dynamic
- relocations. If it is clear then dyn_relocs for this symbol
- should be discarded; We either want the symbol to remain
- undefined, or we have a local definition of some sort. The
- "local definition" for non-function symbols may be due to
- creating a local definition in .dynbss, and for function
- symbols, defining the symbol on the PLT call stub code. */
bfd_boolean local = (SYMBOL_CALLS_LOCAL (info, h)
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
- /* Arrange to discard dyn_relocs if we've decided that a
- function symbol is local. It might be possible to discard
- dyn_relocs here, but when a symbol has a weakdef they have
- been transferred to the weakdef symbol for the benefit of
- readonly_dynrelocs. (See ppc_elf_copy_indirect_symbol.)
- Not only would we need to handle weakdefs here, but also in
- allocate_dynrelocs and relocate_section. The latter is
- impossible since the weakdef field has been overwritten by
- that time. In relocate_section we need a proxy for
- dyn_relocs and non_got_ref is that proxy.
- Note that function symbols are not supposed to have weakdefs,
- but since symbols may not be correctly typed we handle them
- here. */
- h->non_got_ref = (h->u.weakdef != NULL
- ? h->u.weakdef->non_got_ref
- : !local && (((struct ppc_elf_link_hash_entry *) h)
- ->dyn_relocs != NULL));
+ /* 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. */
if (!h->needs_plt)
h->plt.plist = NULL;
}
- else
+ 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. */
- h->non_got_ref = 0;
+ ppc_elf_hash_entry (h)->dyn_relocs = NULL;
}
h->protected_def = 0;
/* Function symbols can't have copy relocs. */
/* 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;
}
if (info->nocopyreloc)
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))
+ && !alias_readonly_dynrelocs (h))
return TRUE;
/* We must allocate the symbol in our .dynbss section, which will
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)
}
/* We no longer want dyn_relocs. */
- h->non_got_ref = 0;
+ ppc_elf_hash_entry (h)->dyn_relocs = NULL;
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
\f
eh->dyn_relocs = NULL;
if (eh->dyn_relocs == NULL)
- h->non_got_ref = 0;
+ ;
/* In the shared -Bsymbolic case, discard space allocated for
dynamic pc-relative relocs against symbols which turn out to be
symbols which turn out to need copy relocs or are not
dynamic. */
if (h->dynamic_adjusted
- && h->non_got_ref
&& !h->def_regular
&& !ELF_COMMON_DEF_P (h)
&& !(h->protected_def
return FALSE;
if (h->dynindx == -1)
- {
- h->non_got_ref = 0;
- eh->dyn_relocs = NULL;
- }
+ eh->dyn_relocs = NULL;
}
else
- {
- h->non_got_ref = 0;
- eh->dyn_relocs = NULL;
- }
+ eh->dyn_relocs = NULL;
}
/* Allocate space. */
if (!doneone || bfd_link_pic (info))
{
glink_offset = s->size;
- s->size += GLINK_ENTRY_SIZE;
- if (h == htab->tls_get_addr
- && !htab->params->no_tls_get_addr_opt)
- s->size += TLS_GET_ADDR_GLINK_SIZE - GLINK_ENTRY_SIZE;
+ s->size += GLINK_ENTRY_SIZE (htab, h);
}
if (!doneone
&& !bfd_link_pic (info)
info->flags |= DF_TEXTREL;
info->callbacks->minfo
- (_("%B: dynamic relocation in read-only section `%A'\n"),
- sec->owner, sec);
+ (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"),
+ sec->owner, h->root.root.string, sec);
/* Not an error, just cut short the traversal. */
return FALSE;
== (SEC_READONLY | SEC_ALLOC))
{
info->flags |= DF_TEXTREL;
- info->callbacks->minfo (_("%B: dynamic relocation in read-only section `%A'\n"),
+ info->callbacks->minfo (_("%pB: dynamic relocation in read-only section `%pA'\n"),
p->sec->owner, p->sec);
}
}
if (!doneone || bfd_link_pic (info))
{
glink_offset = s->size;
- s->size += GLINK_ENTRY_SIZE;
+ s->size += GLINK_ENTRY_SIZE (htab, NULL);
}
ent->glink_offset = glink_offset;
&& htab->elf.dynamic_sections_created)
{
htab->glink_pltresolve = htab->glink->size;
- /* Space for the branch table. ??? We don't need entries for
- non-dynamic symbols in this table. This case can arise with
- static ifuncs or forced local ifuncs. */
- htab->glink->size += htab->glink->size / (GLINK_ENTRY_SIZE / 4) - 4;
+ /* Space for the branch table. */
+ htab->glink->size
+ += htab->elf.srelplt->size / (sizeof (Elf32_External_Rela) / 4) - 4;
/* Pad out to align the start of PLTresolve. */
htab->glink->size += -htab->glink->size & (htab->params->ppc476_workaround
? 63 : 15);
#define PPC_HA(v) PPC_HI ((v) + 0x8000)
static void
-write_glink_stub (struct plt_entry *ent, asection *plt_sec, unsigned char *p,
+write_glink_stub (struct elf_link_hash_entry *h, struct plt_entry *ent,
+ asection *plt_sec, unsigned char *p,
struct bfd_link_info *info)
{
struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
bfd *output_bfd = info->output_bfd;
bfd_vma plt;
+ unsigned char *end = p + GLINK_ENTRY_SIZE (htab, h);
+
+ if (h != NULL
+ && h == htab->tls_get_addr
+ && !htab->params->no_tls_get_addr_opt)
+ {
+ bfd_put_32 (output_bfd, LWZ_11_3, p);
+ p += 4;
+ bfd_put_32 (output_bfd, LWZ_12_3 + 4, p);
+ p += 4;
+ bfd_put_32 (output_bfd, MR_0_3, p);
+ p += 4;
+ bfd_put_32 (output_bfd, CMPWI_11_0, p);
+ p += 4;
+ bfd_put_32 (output_bfd, ADD_3_12_2, p);
+ p += 4;
+ bfd_put_32 (output_bfd, BEQLR, p);
+ p += 4;
+ bfd_put_32 (output_bfd, MR_3_0, p);
+ p += 4;
+ bfd_put_32 (output_bfd, NOP, p);
+ p += 4;
+ }
plt = ((ent->plt.offset & ~1)
+ plt_sec->output_section->vma
plt -= got;
if (plt + 0x8000 < 0x10000)
- {
- bfd_put_32 (output_bfd, LWZ_11_30 + PPC_LO (plt), p);
- p += 4;
- bfd_put_32 (output_bfd, MTCTR_11, p);
- p += 4;
- bfd_put_32 (output_bfd, BCTR, p);
- p += 4;
- bfd_put_32 (output_bfd, htab->params->ppc476_workaround ? BA : NOP, p);
- p += 4;
- }
+ bfd_put_32 (output_bfd, LWZ_11_30 + PPC_LO (plt), p);
else
{
bfd_put_32 (output_bfd, ADDIS_11_30 + PPC_HA (plt), p);
p += 4;
bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p);
- p += 4;
- bfd_put_32 (output_bfd, MTCTR_11, p);
- p += 4;
- bfd_put_32 (output_bfd, BCTR, p);
- p += 4;
}
}
else
bfd_put_32 (output_bfd, LIS_11 + PPC_HA (plt), p);
p += 4;
bfd_put_32 (output_bfd, LWZ_11_11 + PPC_LO (plt), p);
- p += 4;
- bfd_put_32 (output_bfd, MTCTR_11, p);
- p += 4;
- bfd_put_32 (output_bfd, BCTR, p);
+ }
+ p += 4;
+ bfd_put_32 (output_bfd, MTCTR_11, p);
+ p += 4;
+ bfd_put_32 (output_bfd, BCTR, p);
+ p += 4;
+ while (p < end)
+ {
+ bfd_put_32 (output_bfd, htab->params->ppc476_workaround ? BA : NOP, p);
p += 4;
}
}
struct ppc_elf_relax_info *relax_info = NULL;
#ifdef DEBUG
- _bfd_error_handler ("ppc_elf_relocate_section called for %B section %A, "
+ _bfd_error_handler ("ppc_elf_relocate_section called for %pB section %pA, "
"%ld relocations%s",
input_bfd, input_section,
(long) input_section->reloc_count,
else
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+%#Lx): error: %s with unexpected instruction %#x"),
- input_bfd, input_section, rel->r_offset,
+ (_("%pB(%pA+%#" PRIx64 "): error: "
+ "%s with unexpected instruction %#x"),
+ input_bfd, input_section, (uint64_t) rel->r_offset,
"R_PPC_ADDR16_HA", insn);
}
else if (r_type == R_PPC_ADDR16_LO)
else
_bfd_error_handler
/* xgettext:c-format */
- (_("%B(%A+%#Lx): error: %s with unexpected instruction %#x"),
- input_bfd, input_section, rel->r_offset,
+ (_("%pB(%pA+%#" PRIx64 "): error: "
+ "%s with unexpected instruction %#x"),
+ input_bfd, input_section, (uint64_t) rel->r_offset,
"R_PPC_ADDR16_LO", insn);
}
}
{
unsigned char *p = ((unsigned char *) htab->glink->contents
+ ent->glink_offset);
- write_glink_stub (ent, htab->elf.iplt, p, info);
+
+ write_glink_stub (NULL, ent, htab->elf.iplt, p, info);
ent->glink_offset |= 1;
}
switch (r_type)
{
default:
- info->callbacks->einfo
- /* xgettext:c-format */
- (_("%P: %B: unknown relocation type %d for symbol %s\n"),
- input_bfd, (int) r_type, sym_name);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: %s unsupported"),
+ input_bfd, howto->name);
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
|| 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->non_got_ref))
+ 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;
if (!(strcmp (name, ".sdata") == 0
|| strcmp (name, ".sbss") == 0))
{
- info->callbacks->einfo
+ _bfd_error_handler
/* xgettext:c-format */
- (_("%P: %B: the target (%s) of a %s relocation is "
- "in the wrong output section (%s)\n"),
+ (_("%pB: the target (%s) of a %s relocation is "
+ "in the wrong output section (%s)"),
input_bfd,
sym_name,
howto->name,
if (!(strcmp (name, ".sdata2") == 0
|| strcmp (name, ".sbss2") == 0))
{
- info->callbacks->einfo
+ _bfd_error_handler
/* xgettext:c-format */
- (_("%P: %B: the target (%s) of a %s relocation is "
- "in the wrong output section (%s)\n"),
+ (_("%pB: the target (%s) of a %s relocation is "
+ "in the wrong output section (%s)"),
input_bfd,
sym_name,
howto->name,
}
else
{
- info->callbacks->einfo
+ _bfd_error_handler
/* xgettext:c-format */
- (_("%P: %B: the target (%s) of a %s relocation is "
- "in the wrong output section (%s)\n"),
+ (_("%pB: the target (%s) of a %s relocation is "
+ "in the wrong output section (%s)"),
input_bfd,
sym_name,
howto->name,
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: the target (%s) of a %s relocation is "
+ (_("%pB: the target (%s) of a %s relocation is "
"in the wrong output section (%s)"),
input_bfd,
sym_name,
case R_PPC_EMB_RELST_HI:
case R_PPC_EMB_RELST_HA:
case R_PPC_EMB_BIT_FLD:
- info->callbacks->einfo
- /* xgettext:c-format */
- (_("%P: %B: relocation %s is not yet supported for symbol %s\n"),
- input_bfd,
- howto->name,
- sym_name);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: %s unsupported"),
+ input_bfd, howto->name);
bfd_set_error (bfd_error_invalid_operation);
ret = FALSE;
. new_page: new_page:
. */
insn = bfd_get_32 (input_bfd, contents + offset);
- if ((insn & (0x3f << 26)) == (18u << 26) /* b,bl,ba,bla */
- || ((insn & (0x3f << 26)) == (16u << 26) /* bc,bcl,bca,bcla*/
- && (insn & (0x14 << 21)) == (0x14 << 21)) /* with BO=0x14 */
+ if ((insn & (0x3f << 26)) == (18u << 26) /* b,bl,ba,bla */
+ || ((insn & (0x3f << 26)) == (16u << 26) /* bc,bcl,bca,bcla*/
+ && (insn & (0x14 << 21)) == (0x14 << 21)) /* with BO=0x14 */
|| ((insn & (0x3f << 26)) == (19u << 26)
&& (insn & (0x3ff << 1)) == (16u << 1) /* bclr,bclrl */
- && (insn & (0x14 << 21)) == (0x14 << 21)))/* with BO=0x14 */
+ && (insn & (0x14 << 21)) == (0x14 << 21)))/* with BO=0x14 */
continue;
patch_addr = (start_addr + input_section->size
{
unsigned char *p;
asection *splt = htab->elf.splt;
+
if (!htab->elf.dynamic_sections_created
|| h->dynindx == -1)
splt = htab->elf.iplt;
p = (unsigned char *) htab->glink->contents + ent->glink_offset;
-
- if (h == htab->tls_get_addr && !htab->params->no_tls_get_addr_opt)
- {
- bfd_put_32 (output_bfd, LWZ_11_3, p);
- p += 4;
- bfd_put_32 (output_bfd, LWZ_12_3 + 4, p);
- p += 4;
- bfd_put_32 (output_bfd, MR_0_3, p);
- p += 4;
- bfd_put_32 (output_bfd, CMPWI_11_0, p);
- p += 4;
- bfd_put_32 (output_bfd, ADD_3_12_2, p);
- p += 4;
- bfd_put_32 (output_bfd, BEQLR, p);
- p += 4;
- bfd_put_32 (output_bfd, MR_3_0, p);
- p += 4;
- bfd_put_32 (output_bfd, NOP, p);
- p += 4;
- }
-
- write_glink_stub (ent, splt, p, info);
+ write_glink_stub (h, ent, splt, p, info);
if (!bfd_link_pic (info))
/* We only need one non-PIC glink stub. */
else
{
/* xgettext:c-format */
- info->callbacks->einfo (_("%P: %s not defined in linker created %s\n"),
- htab->elf.hgot->root.root.string,
- (htab->elf.sgotplt != NULL
- ? htab->elf.sgotplt->name
- : htab->elf.sgot->name));
+ _bfd_error_handler (_("%s not defined in linker created %pA"),
+ htab->elf.hgot->root.root.string,
+ (htab->elf.sgotplt != NULL
+ ? htab->elf.sgotplt : htab->elf.sgot));
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
}
unsigned char *p;
unsigned char *endp;
bfd_vma res0;
- unsigned int i;
/*
* PIC glink code is the following:
* 1: addi 11,11,(1b-res_0)@l
* mflr 12
* mtlr 0
- * sub 11,11,12 # r11 = index * 4
+ * sub 11,11,12 # r11 = index * 4
* addis 12,12,(got+4-1b)@ha
- * lwz 0,(got+4-1b)@l(12) # got[1] address of dl_runtime_resolve
- * lwz 12,(got+8-1b)@l(12) # got[2] contains the map address
+ * lwz 0,(got+4-1b)@l(12) # got[1] address of dl_runtime_resolve
+ * lwz 12,(got+8-1b)@l(12) # got[2] contains the map address
* mtctr 0
* add 0,11,11
- * add 11,0,11 # r11 = index * 12 = reloc offset.
+ * add 11,0,11 # r11 = index * 12 = reloc offset.
* bctr
- */
- static const unsigned int pic_plt_resolve[] =
- {
- ADDIS_11_11,
- MFLR_0,
- BCL_20_31,
- ADDI_11_11,
- MFLR_12,
- MTLR_0,
- SUB_11_11_12,
- ADDIS_12_12,
- LWZ_0_12,
- LWZ_12_12,
- MTCTR_0,
- ADD_0_11_11,
- ADD_11_0_11,
- BCTR,
- NOP,
- NOP
- };
-
- /*
+ *
* Non-PIC glink code is a little simpler.
*
* # ith PLT code stub.
* PLTresolve:
* lis 12,(got+4)@ha
* addis 11,11,(-res_0)@ha
- * lwz 0,(got+4)@l(12) # got[1] address of dl_runtime_resolve
- * addi 11,11,(-res_0)@l # r11 = index * 4
+ * lwz 0,(got+4)@l(12) # got[1] address of dl_runtime_resolve
+ * addi 11,11,(-res_0)@l # r11 = index * 4
* mtctr 0
* add 0,11,11
- * lwz 12,(got+8)@l(12) # got[2] contains the map address
- * add 11,0,11 # r11 = index * 12 = reloc offset.
+ * lwz 12,(got+8)@l(12) # got[2] contains the map address
+ * add 11,0,11 # r11 = index * 12 = reloc offset.
* bctr
*/
- static const unsigned int plt_resolve[] =
- {
- LIS_12,
- ADDIS_11_11,
- LWZ_0_12,
- ADDI_11_11,
- MTCTR_0,
- ADD_0_11_11,
- LWZ_12_12,
- ADD_11_0_11,
- BCTR,
- NOP,
- NOP,
- NOP,
- NOP,
- NOP,
- NOP,
- NOP
- };
-
- if (ARRAY_SIZE (pic_plt_resolve) != GLINK_PLTRESOLVE / 4)
- abort ();
- if (ARRAY_SIZE (plt_resolve) != GLINK_PLTRESOLVE / 4)
- abort ();
/* Build the branch table, one for each plt entry (less one),
and perhaps some padding. */
}
/* Last comes the PLTresolve stub. */
+ endp = p + GLINK_PLTRESOLVE;
if (bfd_link_pic (info))
{
bfd_vma bcl;
- for (i = 0; i < ARRAY_SIZE (pic_plt_resolve); i++)
- {
- unsigned int insn = pic_plt_resolve[i];
-
- if (htab->params->ppc476_workaround && insn == NOP)
- insn = BA + 0;
- bfd_put_32 (output_bfd, insn, p);
- p += 4;
- }
- p -= 4 * ARRAY_SIZE (pic_plt_resolve);
-
bcl = (htab->glink->size - GLINK_PLTRESOLVE + 3*4
+ htab->glink->output_section->vma
+ htab->glink->output_offset);
- bfd_put_32 (output_bfd,
- ADDIS_11_11 + PPC_HA (bcl - res0), p + 0*4);
- bfd_put_32 (output_bfd,
- ADDI_11_11 + PPC_LO (bcl - res0), p + 3*4);
- bfd_put_32 (output_bfd,
- ADDIS_12_12 + PPC_HA (got + 4 - bcl), p + 7*4);
+ bfd_put_32 (output_bfd, ADDIS_11_11 + PPC_HA (bcl - res0), p);
+ p += 4;
+ bfd_put_32 (output_bfd, MFLR_0, p);
+ p += 4;
+ bfd_put_32 (output_bfd, BCL_20_31, p);
+ p += 4;
+ bfd_put_32 (output_bfd, ADDI_11_11 + PPC_LO (bcl - res0), p);
+ p += 4;
+ bfd_put_32 (output_bfd, MFLR_12, p);
+ p += 4;
+ bfd_put_32 (output_bfd, MTLR_0, p);
+ p += 4;
+ bfd_put_32 (output_bfd, SUB_11_11_12, p);
+ p += 4;
+ bfd_put_32 (output_bfd, ADDIS_12_12 + PPC_HA (got + 4 - bcl), p);
+ p += 4;
if (PPC_HA (got + 4 - bcl) == PPC_HA (got + 8 - bcl))
{
- bfd_put_32 (output_bfd,
- LWZ_0_12 + PPC_LO (got + 4 - bcl), p + 8*4);
- bfd_put_32 (output_bfd,
- LWZ_12_12 + PPC_LO (got + 8 - bcl), p + 9*4);
+ bfd_put_32 (output_bfd, LWZ_0_12 + PPC_LO (got + 4 - bcl), p);
+ p += 4;
+ bfd_put_32 (output_bfd, LWZ_12_12 + PPC_LO (got + 8 - bcl), p);
+ p += 4;
}
else
{
- bfd_put_32 (output_bfd,
- LWZU_0_12 + PPC_LO (got + 4 - bcl), p + 8*4);
- bfd_put_32 (output_bfd,
- LWZ_12_12 + 4, p + 9*4);
+ bfd_put_32 (output_bfd, LWZU_0_12 + PPC_LO (got + 4 - bcl), p);
+ p += 4;
+ bfd_put_32 (output_bfd, LWZ_12_12 + 4, p);
+ p += 4;
}
+ bfd_put_32 (output_bfd, MTCTR_0, p);
+ p += 4;
+ bfd_put_32 (output_bfd, ADD_0_11_11, p);
}
else
{
- for (i = 0; i < ARRAY_SIZE (plt_resolve); i++)
- {
- unsigned int insn = plt_resolve[i];
-
- if (htab->params->ppc476_workaround && insn == NOP)
- insn = BA + 0;
- bfd_put_32 (output_bfd, insn, p);
- p += 4;
- }
- p -= 4 * ARRAY_SIZE (plt_resolve);
-
- bfd_put_32 (output_bfd,
- LIS_12 + PPC_HA (got + 4), p + 0*4);
- bfd_put_32 (output_bfd,
- ADDIS_11_11 + PPC_HA (-res0), p + 1*4);
- bfd_put_32 (output_bfd,
- ADDI_11_11 + PPC_LO (-res0), p + 3*4);
+ bfd_put_32 (output_bfd, LIS_12 + PPC_HA (got + 4), p);
+ p += 4;
+ bfd_put_32 (output_bfd, ADDIS_11_11 + PPC_HA (-res0), p);
+ p += 4;
if (PPC_HA (got + 4) == PPC_HA (got + 8))
- {
- bfd_put_32 (output_bfd,
- LWZ_0_12 + PPC_LO (got + 4), p + 2*4);
- bfd_put_32 (output_bfd,
- LWZ_12_12 + PPC_LO (got + 8), p + 6*4);
- }
+ bfd_put_32 (output_bfd, LWZ_0_12 + PPC_LO (got + 4), p);
else
- {
- bfd_put_32 (output_bfd,
- LWZU_0_12 + PPC_LO (got + 4), p + 2*4);
- bfd_put_32 (output_bfd,
- LWZ_12_12 + 4, p + 6*4);
- }
+ bfd_put_32 (output_bfd, LWZU_0_12 + PPC_LO (got + 4), p);
+ p += 4;
+ bfd_put_32 (output_bfd, ADDI_11_11 + PPC_LO (-res0), p);
+ p += 4;
+ bfd_put_32 (output_bfd, MTCTR_0, p);
+ p += 4;
+ bfd_put_32 (output_bfd, ADD_0_11_11, p);
+ p += 4;
+ if (PPC_HA (got + 4) == PPC_HA (got + 8))
+ bfd_put_32 (output_bfd, LWZ_12_12 + PPC_LO (got + 8), p);
+ else
+ bfd_put_32 (output_bfd, LWZ_12_12 + 4, p);
+ }
+ p += 4;
+ bfd_put_32 (output_bfd, ADD_11_0_11, p);
+ p += 4;
+ bfd_put_32 (output_bfd, BCTR, p);
+ p += 4;
+ while (p < endp)
+ {
+ bfd_put_32 (output_bfd,
+ htab->params->ppc476_workaround ? BA : NOP, p);
+ p += 4;
}
+ BFD_ASSERT (p == endp);
}
if (htab->glink_eh_frame != NULL