/* 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. */
/* 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. */
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)
{
_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
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);
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 against `%T' in read-only section `%A'\n"),
+ (_("%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. */
== (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;
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;
{
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:
* add 0,11,11
* 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.
* 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