#define LD_R11_0R11 0xe96b0000 /* ld %r11,xxx+16@l(%r11) */
#define BCTR 0x4e800420 /* bctr */
-#define CRSETEQ 0x4c421242 /* crset 4*%cr0+%eq */
-#define BEQCTRM 0x4dc20420 /* beqctr- */
-#define BEQCTRLM 0x4dc20421 /* beqctrl- */
-
#define ADDI_R11_R11 0x396b0000 /* addi %r11,%r11,off@l */
#define ADDIS_R2_R2 0x3c420000 /* addis %r2,%r2,off@ha */
#define ADDI_R2_R2 0x38420000 /* addi %r2,%r2,off@l */
/* __glink_PLTresolve stub instructions. We enter with the index in R0. */
#define GLINK_PLTRESOLVE_SIZE(htab) \
- (8u + (htab->opd_abi ? 11 * 4 : 14 * 4) \
- + (!htab->params->speculate_indirect_jumps ? 2 * 4 : 0))
+ (8u + (htab->opd_abi ? 11 * 4 : 14 * 4))
/* 0: */
/* .quad plt0-1f */
/* __glink: */
/* Relocation HOWTO's. */
static reloc_howto_type *ppc64_elf_howto_table[(int) R_PPC64_max];
-static reloc_howto_type ppc64_elf_howto_raw[] = {
+static reloc_howto_type ppc64_elf_howto_raw[] =
+{
/* This reloc does nothing. */
HOWTO (R_PPC64_NONE, /* type */
0, /* rightshift */
}
static reloc_howto_type *
-ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ppc64_elf_reloc_type_lookup (bfd *abfd,
bfd_reloc_code_real_type code)
{
enum elf_ppc64_reloc_type r = R_PPC64_NONE;
switch (code)
{
default:
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, (int) code);
+ bfd_set_error (bfd_error_bad_value);
return NULL;
case BFD_RELOC_NONE: r = R_PPC64_NONE;
&& strcasecmp (ppc64_elf_howto_raw[i].name, r_name) == 0)
return &ppc64_elf_howto_raw[i];
+
return NULL;
}
/* Set the howto pointer for a PowerPC ELF reloc. */
-static void
+static bfd_boolean
ppc64_elf_info_to_howto (bfd *abfd, arelent *cache_ptr,
Elf_Internal_Rela *dst)
{
if (type >= ARRAY_SIZE (ppc64_elf_howto_table))
{
/* xgettext:c-format */
- _bfd_error_handler (_("%B: invalid relocation type %d"),
- abfd, (int) type);
- type = R_PPC64_NONE;
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, type);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
cache_ptr->howto = ppc64_elf_howto_table[type];
+ if (cache_ptr->howto == NULL || cache_ptr->howto->name == NULL)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, type);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ return TRUE;
}
/* Handle the R_PPC64_ADDR16_HA and similar relocs. */
asymbol **ret)
{
asymbol *s;
- long i;
- long count;
+ size_t i, j, count;
char *names;
- long symcount, codesecsym, codesecsymend, secsymend, opdsymend;
+ size_t symcount, codesecsym, codesecsymend, secsymend, opdsymend;
asection *opd = NULL;
bfd_boolean relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
asymbol **syms;
else
memcpy (syms, static_syms, (symcount + 1) * sizeof (*syms));
+ /* Trim uninteresting symbols. Interesting symbols are section,
+ function, and notype symbols. */
+ for (i = 0, j = 0; i < symcount; ++i)
+ if ((syms[i]->flags & (BSF_FILE | BSF_OBJECT | BSF_THREAD_LOCAL
+ | BSF_RELC | BSF_SRELC)) == 0)
+ syms[j++] = syms[i];
+ symcount = j;
+
synthetic_relocatable = relocatable;
synthetic_opd = opd;
qsort (syms, symcount, sizeof (*syms), compare_symbols);
if (!relocatable && symcount > 1)
{
- long j;
/* Trim duplicate syms, since we may have merged the normal and
dynamic symbols. Actually, we only care about syms that have
different values, so trim any with the same value. */
sym->section directly. With separate debug info files, the
symbols will be extracted from the debug file while abfd passed
to this function is the real binary. */
- if (opd != NULL && strcmp (syms[i]->section->name, ".opd") == 0)
+ if (strcmp (syms[i]->section->name, ".opd") == 0)
++i;
codesecsym = i;
bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
arelent *r;
size_t size;
- long relcount;
+ size_t relcount;
if (opdsymend == secsymend)
goto done;
bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
bfd_byte *contents = NULL;
size_t size;
- long plt_count = 0;
+ size_t plt_count = 0;
bfd_vma glink_vma = 0, resolv_vma = 0;
asection *dynamic, *glink = NULL, *relplt = NULL;
arelent *p;
ent = bfd_get_64 (abfd, contents + syms[i]->value);
if (!sym_exists_at (syms, opdsymend, symcount, -1, ent))
{
- long lo, hi;
+ size_t lo, hi;
size_t len;
asection *sec = abfd->sections;
hi = codesecsymend;
while (lo < hi)
{
- long mid = (lo + hi) >> 1;
+ size_t mid = (lo + hi) >> 1;
if (syms[mid]->section->vma < ent)
lo = mid + 1;
else if (syms[mid]->section->vma > ent)
if (stub_entry == NULL)
{
/* xgettext:c-format */
- info->callbacks->einfo (_("%P: %B: cannot create stub entry %s\n"),
- section->owner, stub_name);
+ _bfd_error_handler (_("%pB: cannot create stub entry %s"),
+ section->owner, stub_name);
return NULL;
}
set_abiversion (ibfd, 2);
else if (abiversion (ibfd) == 1)
{
- info->callbacks->einfo (_("%P: symbol '%s' has invalid st_other"
- " for ABI version 1\n"), name);
+ _bfd_error_handler (_("symbol '%s' has invalid st_other"
+ " for ABI version 1"), *name);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
else if (abiversion (ibfd) >= 2)
{
/* xgettext:c-format */
- info->callbacks->einfo (_("%P: %B .opd not allowed in ABI"
- " version %d\n"),
- ibfd, abiversion (ibfd));
+ _bfd_error_handler (_("%pB .opd not allowed in ABI version %d"),
+ ibfd, abiversion (ibfd));
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
ppc_howto_init ();
/* xgettext:c-format */
info->callbacks->einfo (_("%H: %s reloc unsupported "
- "in shared libraries and PIEs.\n"),
+ "in shared libraries and PIEs\n"),
abfd, sec, rel->r_offset,
ppc64_elf_howto_table[r_type]->name);
bfd_set_error (bfd_error_bad_value);
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B uses unknown e_flags 0x%lx"), ibfd, iflags);
+ (_("%pB uses unknown e_flags 0x%lx"), ibfd, iflags);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: ABI version %ld is not compatible with ABI version %ld output"),
+ (_("%pB: ABI version %ld is not compatible with ABI version %ld output"),
ibfd, iflags, oflags);
bfd_set_error (bfd_error_bad_value);
return FALSE;
{
s->root.type = bfd_link_hash_defined;
s->root.u.def.section = stub_sec;
- s->root.u.def.value = (stub_sec->size
+ s->root.u.def.value = (stub_sec->size - htab->sfpr->size
+ h->elf.root.u.def.value);
s->ref_regular = 1;
s->def_regular = 1;
sections. Allow them to proceed, but warn that this might
break at runtime. */
info->callbacks->einfo
- (_("%P: copy reloc against `%T' requires lazy plt linking; "
+ (_("%P: copy reloc against `%pT' requires lazy plt linking; "
"avoid setting LD_BIND_NOW=1 or upgrade gcc\n"),
h->root.root.string);
}
if (ent.sec == NULL || ent.sec->output_section == NULL)
{
_bfd_error_handler
- (_("%B: undefined symbol on R_PPC64_TOCSAVE relocation"), ibfd);
+ (_("%pB: undefined symbol on R_PPC64_TOCSAVE relocation"), ibfd);
return NULL;
}
}
/* xgettext:c-format */
- info->callbacks->einfo (_("%P: dynreloc miscount for %B, section %A\n"),
- sec->owner, sec);
+ _bfd_error_handler (_("dynreloc miscount for %pB, section %pA"),
+ sec->owner, sec);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
optimization for them! */
broken_opd:
_bfd_error_handler
- (_("%B: .opd is not a regular array of opd entries"), ibfd);
+ (_("%pB: .opd is not a regular array of opd entries"), ibfd);
broken = TRUE;
break;
}
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: unexpected reloc type %u in .opd section"),
+ (_("%pB: unexpected reloc type %u in .opd section"),
ibfd, r_type);
broken = TRUE;
break;
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: undefined sym `%s' in .opd section"),
+ (_("%pB: undefined sym `%s' in .opd section"),
ibfd, sym_name);
broken = TRUE;
break;
if (htab->params->plt_localentry0
&& elf_link_hash_lookup (&htab->elf, "GLIBC_2.26",
FALSE, FALSE, FALSE) == NULL)
- info->callbacks->einfo
- (_("%P: warning: --plt-localentry is especially dangerous without "
- "ld.so support to detect ABI violations.\n"));
+ _bfd_error_handler
+ (_("warning: --plt-localentry is especially dangerous without "
+ "ld.so support to detect ABI violations"));
htab->tls_get_addr = ((struct ppc_link_hash_entry *)
elf_link_hash_lookup (&htab->elf, ".__tls_get_addr",
info->callbacks->einfo
/* xgettext:c-format */
(_("%H: toc optimization is not supported for"
- " %s instruction.\n"),
+ " %s instruction\n"),
ibfd, sec, rel->r_offset & ~3, str);
}
}
unsigned int align_power;
stub_size = 16;
- if (!htab->params->speculate_indirect_jumps)
- stub_size += 8;
stub_off = s->size;
if (htab->params->plt_stub_align >= 0)
align_power = htab->params->plt_stub_align;
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. */
size += 4;
if (PPC_HA (off) != 0)
size += 4;
- if (!htab->params->speculate_indirect_jumps)
- size += 8;
if (htab->opd_abi)
{
size += 4;
size += 7 * 4;
if (ALWAYS_EMIT_R2SAVE
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
- {
- size += 6 * 4;
- if (!htab->params->speculate_indirect_jumps)
- size -= 4;
- }
+ size += 6 * 4;
}
return size;
}
return 0;
}
-static inline bfd_byte *
-output_bctr (struct ppc_link_hash_table *htab, bfd *obfd, bfd_byte *p)
-{
- if (!htab->params->speculate_indirect_jumps)
- {
- bfd_put_32 (obfd, CRSETEQ, p);
- p += 4;
- bfd_put_32 (obfd, BEQCTRM, p);
- p += 4;
- bfd_put_32 (obfd, B_DOT, p);
- p += 4;
- }
- else
- {
- bfd_put_32 (obfd, BCTR, p);
- p += 4;
- }
- return p;
-}
-
/* Build a .plt call stub. */
static inline bfd_byte *
if (!ALWAYS_USE_FAKE_DEP
&& plt_load_toc
&& plt_thread_safe
- && htab->params->speculate_indirect_jumps
&& !((stub_entry->h == htab->tls_get_addr_fd
|| stub_entry->h == htab->tls_get_addr)
&& htab->params->tls_get_addr_opt))
bfd_put_32 (obfd, B_DOT | (cmp_branch_off & 0x3fffffc), p), p += 4;
}
else
- p = output_bctr (htab, obfd, p);
+ bfd_put_32 (obfd, BCTR, p), p += 4;
return p;
}
if (r != NULL)
r[0].r_offset += 2 * 4;
p = build_plt_stub (htab, stub_entry, p, offset, r);
- if (!htab->params->speculate_indirect_jumps)
- {
- p -= 4;
- bfd_put_32 (obfd, BEQCTRLM, p - 4);
- }
- else
- bfd_put_32 (obfd, BCTRL, p - 4);
+ bfd_put_32 (obfd, BCTRL, p - 4);
bfd_put_32 (obfd, LD_R2_0R1 + STK_TOC (htab), p), p += 4;
bfd_put_32 (obfd, LD_R11_0R1 + STK_LINKER (htab), p), p += 4;
if (strcmp (opd->name, ".opd") != 0
|| opd->reloc_count != 0)
{
- info->callbacks->einfo (_("%P: cannot find opd entry toc for `%T'\n"),
+ info->callbacks->einfo (_("%P: cannot find opd entry toc for `%pT'\n"),
stub_entry->h->elf.root.root.string);
bfd_set_error (bfd_error_bad_value);
return (bfd_vma) -1;
if (off + (1 << 25) >= (bfd_vma) (1 << 26))
{
- info->callbacks->einfo
- (_("%P: long branch stub `%s' offset overflow\n"),
+ _bfd_error_handler
+ (_("long branch stub `%s' offset overflow"),
stub_entry->root.string);
htab->stub_error = TRUE;
return FALSE;
FALSE, FALSE);
if (br_entry == NULL)
{
- info->callbacks->einfo (_("%P: can't find branch stub `%s'\n"),
- stub_entry->root.string);
+ _bfd_error_handler (_("can't find branch stub `%s'"),
+ stub_entry->root.string);
htab->stub_error = TRUE;
return FALSE;
}
if (off + 0x80008000 > 0xffffffff || (off & 7) != 0)
{
info->callbacks->einfo
- (_("%P: linkage table error against `%T'\n"),
+ (_("%P: linkage table error against `%pT'\n"),
stub_entry->root.string);
bfd_set_error (bfd_error_bad_value);
htab->stub_error = TRUE;
p += 4;
bfd_put_32 (htab->params->stub_bfd, MTCTR_R12, p);
p += 4;
- p = output_bctr (htab, htab->params->stub_bfd, p);
+ bfd_put_32 (htab->params->stub_bfd, BCTR, p);
+ p += 4;
break;
case ppc_stub_plt_call:
{
info->callbacks->einfo
/* xgettext:c-format */
- (_("%P: linkage table error against `%T'\n"),
+ (_("%P: linkage table error against `%pT'\n"),
stub_entry->h != NULL
? stub_entry->h->elf.root.root.string
: "<local sym>");
local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
- /* If the branch offset if too big, use a ppc_stub_plt_branch.
+ /* If the branch offset is too big, use a ppc_stub_plt_branch.
Do the same for -R objects without function descriptors. */
if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off
|| (stub_entry->stub_type == ppc_stub_long_branch_r2off
TRUE, FALSE);
if (br_entry == NULL)
{
- info->callbacks->einfo (_("%P: can't build branch stub `%s'\n"),
- stub_entry->root.string);
+ _bfd_error_handler (_("can't build branch stub `%s'"),
+ stub_entry->root.string);
htab->stub_error = TRUE;
return FALSE;
}
if (PPC_LO (r2off) != 0)
size += 4;
}
- if (!htab->params->speculate_indirect_jumps)
- size += 8;
}
else if (info->emitrelocations)
{
htab->elf.irelplt->size += rel_size;
htab->got_reli_size += rel_size;
}
- else if (bfd_link_pic (info))
+ else if (bfd_link_pic (info)
+ && !((ent->tls_type & TLS_TPREL) != 0
+ && bfd_link_executable (info)))
{
asection *srel = ppc64_elf_tdata (ibfd)->relgot;
srel->size += rel_size;
big_sec = total > group_size;
if (big_sec && !suppress_size_errors)
/* xgettext:c-format */
- _bfd_error_handler (_("%B section %A exceeds stub group size"),
+ _bfd_error_handler (_("%pB section %pA exceeds stub group size"),
tail->owner, tail);
curr_toc = htab->sec_info[tail->id].toc_off;
if (off + 0x80008000 > 0xffffffff || (off & 3) != 0)
{
info->callbacks->einfo
- (_("%P: linkage table error against `%T'\n"),
+ (_("%P: linkage table error against `%pT'\n"),
h->root.root.string);
bfd_set_error (bfd_error_bad_value);
htab->stub_error = TRUE;
p += 4;
bfd_put_32 (s->owner, MTCTR_R12, p);
p += 4;
- output_bctr (htab, s->owner, p);
+ bfd_put_32 (s->owner, BCTR, p);
break;
}
return TRUE;
bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 8, p);
p += 4;
}
- p = output_bctr (htab, htab->glink->owner, p);
+ bfd_put_32 (htab->glink->owner, BCTR, p);
+ p += 4;
BFD_ASSERT (p == htab->glink->contents + GLINK_PLTRESOLVE_SIZE (htab));
/* Build the .glink lazy link call stubs. */
for (group = htab->group; group != NULL; group = group->next)
if (group->needs_save_res)
- {
- stub_sec = group->stub_sec;
- memcpy (stub_sec->contents + stub_sec->size, htab->sfpr->contents,
- htab->sfpr->size);
- if (htab->params->emit_stub_syms)
- {
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
- if (!sfpr_define (info, &save_res_funcs[i], stub_sec))
- return FALSE;
- }
- stub_sec->size += htab->sfpr->size;
- }
+ group->stub_sec->size += htab->sfpr->size;
if (htab->relbrlt != NULL)
htab->relbrlt->reloc_count = 0;
stub_sec->size = (stub_sec->size + (1 << align) - 1) & -(1 << align);
}
+ for (group = htab->group; group != NULL; group = group->next)
+ if (group->needs_save_res)
+ {
+ stub_sec = group->stub_sec;
+ memcpy (stub_sec->contents + stub_sec->size - htab->sfpr->size,
+ htab->sfpr->contents, htab->sfpr->size);
+ if (htab->params->emit_stub_syms)
+ {
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
+ if (!sfpr_define (info, &save_res_funcs[i], stub_sec))
+ return FALSE;
+ }
+ }
+
for (group = htab->group; group != NULL; group = group->next)
if ((stub_sec = group->stub_sec) != NULL)
{
if (group != NULL)
{
htab->stub_error = TRUE;
- info->callbacks->einfo (_("%P: stubs don't match calculated size\n"));
+ _bfd_error_handler (_("stubs don't match calculated size"));
}
if (htab->stub_error)
info->callbacks->einfo
(!IS_PPC64_TLS_RELOC (r_type)
/* xgettext:c-format */
- ? _("%H: %s used with TLS symbol `%T'\n")
+ ? _("%H: %s used with TLS symbol `%pT'\n")
/* xgettext:c-format */
- : _("%H: %s used with non-TLS symbol `%T'\n"),
+ : _("%H: %s used with non-TLS symbol `%pT'\n"),
input_bfd, input_section, rel->r_offset,
ppc64_elf_howto_table[r_type]->name,
sym_name);
break;
case R_PPC64_TLSGD:
- if (tls_mask != 0 && (tls_mask & TLS_GD) == 0)
+ if (tls_mask != 0 && (tls_mask & TLS_GD) == 0
+ && rel + 1 < relend)
{
unsigned int insn2;
bfd_vma offset = rel->r_offset;
break;
case R_PPC64_TLSLD:
- if (tls_mask != 0 && (tls_mask & TLS_LD) == 0)
+ if (tls_mask != 0 && (tls_mask & TLS_LD) == 0
+ && rel + 1 < relend)
{
unsigned int insn2;
bfd_vma offset = rel->r_offset;
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
info->callbacks->einfo
/* xgettext:c-format */
- (_("%H: call to `%T' lacks nop, can't restore toc; "
+ (_("%H: call to `%pT' lacks nop, can't restore toc; "
"recompile with -fPIC\n"),
input_bfd, input_section, rel->r_offset, sym_name);
else
info->callbacks->einfo
/* xgettext:c-format */
- (_("%H: call to `%T' lacks nop, can't restore toc; "
+ (_("%H: call to `%pT' lacks nop, can't restore toc; "
"(-mcmodel=small toc adjust stub)\n"),
input_bfd, input_section, rel->r_offset, sym_name);
switch (r_type)
{
default:
- info->callbacks->einfo
- /* xgettext:c-format */
- (_("%P: %B: unknown relocation type %d for `%T'\n"),
- input_bfd, (int) r_type, sym_name);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: %s unsupported"),
+ input_bfd, ppc64_elf_howto_table[r_type]->name);
bfd_set_error (bfd_error_bad_value);
ret = FALSE;
info->callbacks->einfo
/* xgettext:c-format */
(_("%H: %s for indirect "
- "function `%T' unsupported\n"),
+ "function `%pT' unsupported\n"),
input_bfd, input_section, rel->r_offset,
ppc64_elf_howto_table[r_type]->name,
sym_name);
info->callbacks->einfo
/* xgettext:c-format */
- (_("%P: %B: %s is not supported for `%T'\n"),
+ (_("%P: %pB: %s is not supported for `%pT'\n"),
input_bfd,
ppc64_elf_howto_table[r_type]->name, sym_name);
{
info->callbacks->einfo
/* xgettext:c-format */
- (_("%H: unresolvable %s against `%T'\n"),
+ (_("%H: unresolvable %s against `%pT'\n"),
input_bfd, input_section, rel->r_offset,
howto->name,
h->elf.root.root.string);
{
info->callbacks->einfo
/* xgettext:c-format */
- (_("%H: %s against `%T': error %d\n"),
+ (_("%H: %s against `%pT': error %d\n"),
input_bfd, input_section, rel->r_offset,
reloc_name, sym_name, (int) r);
ret = FALSE;
+ (p + 8 - htab->glink_eh_frame->contents));
if (val + 0x80000000 > 0xffffffff)
{
- info->callbacks->einfo
- (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+ _bfd_error_handler
+ (_("%s offset too large for .eh_frame sdata4 encoding"),
group->stub_sec->name);
return FALSE;
}
+ (p + 8 - htab->glink_eh_frame->contents));
if (val + 0x80000000 > 0xffffffff)
{
- info->callbacks->einfo
- (_("%P: %s offset too large for .eh_frame sdata4 encoding"),
+ _bfd_error_handler
+ (_("%s offset too large for .eh_frame sdata4 encoding"),
htab->glink->name);
return FALSE;
}