#include "elf/ppc.h"
#include "elf32-ppc.h"
#include "elf-vxworks.h"
+#include "dwarf2.h"
/* RELA relocations are used here. */
asection *relsbss;
elf_linker_section_t sdata[2];
asection *sbss;
+ asection *glink_eh_frame;
/* The (unloaded but important) .rela.plt.unloaded on VxWorks. */
asection *srelplt2;
|| !bfd_set_section_alignment (abfd, s, 4))
return FALSE;
+ if (!info->no_ld_generated_unwind_info)
+ {
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ s = bfd_make_section_anyway_with_flags (abfd, ".eh_frame", flags);
+ htab->glink_eh_frame = s;
+ if (s == NULL
+ || !bfd_set_section_alignment (abfd, s, 2))
+ return FALSE;
+ }
+
flags = SEC_ALLOC | SEC_LINKER_CREATED;
s = bfd_make_section_anyway_with_flags (abfd, ".iplt", flags);
htab->iplt = s;
edir = (struct ppc_elf_link_hash_entry *) dir;
eind = (struct ppc_elf_link_hash_entry *) ind;
+ 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;
+
+ 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.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;
}
- 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;
-
- 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.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;
-
/* 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;
{
/* It does not make sense to have a procedure linkage
table entry for a local symbol. */
- info->callbacks->einfo (_("%H: %s reloc against local symbol\n"),
+ info->callbacks->einfo (_("%P: %H: %s reloc against local symbol\n"),
abfd, sec, rel->r_offset,
ppc_elf_howto_table[r_type]->name);
bfd_set_error (bfd_error_bad_value);
if (htab->plt_type == PLT_UNSET)
{
+ struct elf_link_hash_entry *h;
+
if (plt_style == PLT_OLD)
htab->plt_type = PLT_OLD;
+ else if (info->shared
+ && htab->elf.dynamic_sections_created
+ && (h = elf_link_hash_lookup (&htab->elf, "_mcount",
+ FALSE, FALSE, TRUE)) != NULL
+ && (h->type == STT_FUNC
+ || 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)))
+ {
+ /* Profiling of shared libs (and pies) is not supported with
+ secure plt, because ppc32 does profiling before a
+ function prologue and a secure plt pic call stubs needs
+ r30 to be set up. */
+ htab->plt_type = PLT_OLD;
+ }
else
{
bfd *ibfd;
}
}
if (htab->plt_type == PLT_OLD && plt_style == PLT_NEW)
- info->callbacks->info (_("Using bss-plt due to %B"), htab->old_bfd);
+ {
+ if (htab->old_bfd != NULL)
+ info->callbacks->einfo (_("%P: bss-plt forced due to %B\n"),
+ htab->old_bfd);
+ else
+ info->callbacks->einfo (_("%P: bss-plt forced by profiling\n"));
+ }
BFD_ASSERT (htab->plt_type != PLT_VXWORKS);
if (h->size == 0)
{
- info->callbacks->einfo (_("dynamic variable `%s' is zero size\n"),
+ info->callbacks->einfo (_("%P: dynamic variable `%s' is zero size\n"),
h->root.root.string);
return TRUE;
}
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- if (h->root.type == bfd_link_hash_warning)
- /* When warning symbols are created, they **replace** the "real"
- entry in the hash table, thus we never get to see the real
- symbol in a hash traversal. So look at it now. */
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
htab = ppc_elf_hash_table (info);
if (htab->elf.dynamic_sections_created
|| h->type == STT_GNU_IFUNC)
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
if (readonly_dynrelocs (h))
{
((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
return TRUE;
}
+static const unsigned char glink_eh_frame_cie[] =
+{
+ 0, 0, 0, 16, /* length. */
+ 0, 0, 0, 0, /* id. */
+ 1, /* CIE version. */
+ 'z', 'R', 0, /* Augmentation string. */
+ 4, /* Code alignment. */
+ 0x7c, /* Data alignment. */
+ 65, /* RA reg. */
+ 1, /* Augmentation size. */
+ DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding. */
+ DW_CFA_def_cfa, 1, 0 /* def_cfa: r1 offset 0. */
+};
+
/* Set the sizes of the dynamic sections. */
static bfd_boolean
}
}
+ if (htab->glink != NULL
+ && htab->glink->size != 0
+ && htab->glink_eh_frame != NULL
+ && !bfd_is_abs_section (htab->glink_eh_frame->output_section))
+ {
+ s = htab->glink_eh_frame;
+ s->size = sizeof (glink_eh_frame_cie) + 20;
+ if (info->shared)
+ {
+ s->size += 4;
+ if (htab->glink->size - GLINK_PLTRESOLVE + 8 >= 256)
+ s->size += 4;
+ }
+ }
+
/* We've now determined the sizes of the various dynamic sections.
Allocate memory for them. */
relocs = FALSE;
}
else if (s == htab->iplt
|| s == htab->glink
+ || s == htab->glink_eh_frame
|| s == htab->sgotplt
|| s == htab->sbss
|| s == htab->dynbss
{
default:
info->callbacks->einfo
- (_("%B: unknown relocation type %d for symbol %s\n"),
+ (_("%P: %B: unknown relocation type %d for symbol %s\n"),
input_bfd, (int) r_type, sym_name);
bfd_set_error (bfd_error_bad_value);
got at entry m+n bears little relation to the entry m. */
if (addend != 0)
info->callbacks->einfo
- (_("%H: non-zero addend on %s reloc against `%s'\n"),
+ (_("%P: %H: non-zero addend on %s reloc against `%s'\n"),
input_bfd, input_section, rel->r_offset,
howto->name,
sym_name);
So we'll segfault when trying to run the
indirection function to resolve the reloc. */
info->callbacks->einfo
- (_("%H: relocation %s for indirect "
+ (_("%P: %H: relocation %s for indirect "
"function %s unsupported\n"),
input_bfd, input_section, rel->r_offset,
howto->name,
&& (name[5] == 0 || name[5] == '.'))))
{
info->callbacks->einfo
- (_("%B: the target (%s) of a %s relocation is "
+ (_("%P: %B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)\n"),
input_bfd,
sym_name,
|| CONST_STRNEQ (name, ".sbss2")))
{
info->callbacks->einfo
- (_("%B: the target (%s) of a %s relocation is "
+ (_("%P: %B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)\n"),
input_bfd,
sym_name,
else
{
info->callbacks->einfo
- (_("%B: the target (%s) of a %s relocation is "
+ (_("%P: %B: the target (%s) of a %s relocation is "
"in the wrong output section (%s)\n"),
input_bfd,
sym_name,
case R_PPC_EMB_RELST_HA:
case R_PPC_EMB_BIT_FLD:
info->callbacks->einfo
- (_("%B: relocation %s is not yet supported for symbol %s\n"),
+ (_("%P: %B: relocation %s is not yet supported for symbol %s\n"),
input_bfd,
howto->name,
sym_name);
&& h->def_dynamic))
{
info->callbacks->einfo
- (_("%H: unresolvable %s relocation against symbol `%s'\n"),
+ (_("%P: %H: unresolvable %s relocation against symbol `%s'\n"),
input_bfd, input_section, rel->r_offset,
howto->name,
sym_name);
else
{
info->callbacks->einfo
- (_("%H: %s reloc against `%s': error %d\n"),
+ (_("%P: %H: %s reloc against `%s': error %d\n"),
input_bfd, input_section, rel->r_offset,
howto->name, sym_name, (int) r);
ret = FALSE;
}
else
{
- info->callbacks->einfo (_("%s not defined in linker created %s\n"),
+ info->callbacks->einfo (_("%P: %s not defined in linker created %s\n"),
htab->elf.hgot->root.root.string,
(htab->sgotplt != NULL
? htab->sgotplt->name : htab->got->name));
}
}
+ if (htab->glink_eh_frame != NULL
+ && htab->glink_eh_frame->contents != NULL)
+ {
+ unsigned char *p = htab->glink_eh_frame->contents;
+ bfd_vma val;
+
+ memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
+ /* CIE length (rewrite in case little-endian). */
+ bfd_put_32 (htab->elf.dynobj, sizeof (glink_eh_frame_cie) - 4, p);
+ p += sizeof (glink_eh_frame_cie);
+ /* FDE length. */
+ val = htab->glink_eh_frame->size - 4 - sizeof (glink_eh_frame_cie);
+ bfd_put_32 (htab->elf.dynobj, val, p);
+ p += 4;
+ /* CIE pointer. */
+ val = p - htab->glink_eh_frame->contents;
+ bfd_put_32 (htab->elf.dynobj, val, p);
+ p += 4;
+ /* Offset to .glink. */
+ val = (htab->glink->output_section->vma
+ + htab->glink->output_offset);
+ val -= (htab->glink_eh_frame->output_section->vma
+ + htab->glink_eh_frame->output_offset);
+ val -= p - htab->glink_eh_frame->contents;
+ bfd_put_32 (htab->elf.dynobj, val, p);
+ p += 4;
+ /* .glink size. */
+ bfd_put_32 (htab->elf.dynobj, htab->glink->size, p);
+ p += 4;
+ /* Augmentation. */
+ p += 1;
+
+ if (info->shared
+ && htab->elf.dynamic_sections_created)
+ {
+ bfd_vma adv = (htab->glink->size - GLINK_PLTRESOLVE + 8) >> 2;
+ if (adv < 64)
+ *p++ = DW_CFA_advance_loc + adv;
+ else if (adv < 256)
+ {
+ *p++ = DW_CFA_advance_loc1;
+ *p++ = adv;
+ }
+ else if (adv < 65536)
+ {
+ *p++ = DW_CFA_advance_loc2;
+ bfd_put_16 (htab->elf.dynobj, adv, p);
+ p += 2;
+ }
+ else
+ {
+ *p++ = DW_CFA_advance_loc4;
+ bfd_put_32 (htab->elf.dynobj, adv, p);
+ p += 4;
+ }
+ *p++ = DW_CFA_register;
+ *p++ = 65;
+ p++;
+ *p++ = DW_CFA_advance_loc + 4;
+ *p++ = DW_CFA_restore_extended;
+ *p++ = 65;
+ }
+ BFD_ASSERT ((bfd_vma) ((p + 3 - htab->glink_eh_frame->contents) & -4)
+ == htab->glink_eh_frame->size);
+
+ if (htab->glink_eh_frame->sec_info_type == ELF_INFO_TYPE_EH_FRAME
+ && !_bfd_elf_write_section_eh_frame (output_bfd, info,
+ htab->glink_eh_frame,
+ htab->glink_eh_frame->contents))
+ return FALSE;
+ }
+
return ret;
}
\f