unsigned int new_plt:1;
unsigned int old_plt:1;
+ /* Set if we should emit symbols for stubs. */
+ unsigned int emit_stub_syms:1;
+
/* Small local sym to section mapping cache. */
struct sym_sec_cache sym_sec;
int
ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
struct bfd_link_info *info,
- int force_old_plt)
+ int force_old_plt,
+ int emit_stub_syms)
{
struct ppc_elf_link_hash_table *htab;
flagword flags;
if (force_old_plt || !htab->new_plt)
htab->old_plt = 1;
+ htab->emit_stub_syms = emit_stub_syms;
+
if (htab->is_vxworks)
{
/* The VxWorks PLT is a loaded section with contents. */
return TRUE;
}
\f
+/* Generate a symbol to mark plt call stubs. For non-PIC code the sym is
+ xxxxxxxx.plt_call32.<callee> where xxxxxxxx is a hex number, usually 0,
+ specifying the addend on the plt relocation. For -fpic code, the sym
+ is xxxxxxxx.plt_pic32.<callee>, and for -fPIC
+ xxxxxxxx.got2.plt_pic32.<callee>. */
+
+static bfd_boolean
+add_stub_sym (struct plt_entry *ent,
+ struct elf_link_hash_entry *h,
+ struct bfd_link_info *info)
+{
+ struct elf_link_hash_entry *sh;
+ size_t len1, len2, len3;
+ char *name;
+ const char *stub;
+ struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
+
+ if (info->shared || info->pie)
+ stub = ".plt_pic32.";
+ else
+ stub = ".plt_call32.";
+
+ len1 = strlen (h->root.root.string);
+ len2 = strlen (stub);
+ len3 = 0;
+ if (ent->sec)
+ len3 = strlen (ent->sec->name);
+ name = bfd_malloc (len1 + len2 + len3 + 9);
+ if (name == NULL)
+ return FALSE;
+ sprintf (name, "%08x", (unsigned) ent->addend & 0xffffffff);
+ if (ent->sec)
+ memcpy (name + 8, ent->sec->name, len3);
+ memcpy (name + 8 + len3, stub, len2);
+ memcpy (name + 8 + len3 + len2, h->root.root.string, len1 + 1);
+ sh = elf_link_hash_lookup (&htab->elf, name, TRUE, FALSE, FALSE);
+ if (sh == NULL)
+ return FALSE;
+ if (sh->root.type == bfd_link_hash_new)
+ {
+ sh->root.type = bfd_link_hash_defined;
+ sh->root.u.def.section = htab->glink;
+ sh->root.u.def.value = ent->glink_offset;
+ sh->ref_regular = 1;
+ sh->def_regular = 1;
+ sh->ref_regular_nonweak = 1;
+ sh->forced_local = 1;
+ sh->non_elf = 0;
+ }
+ return TRUE;
+}
+
/* Allocate NEED contiguous space in .got, and return the offset.
Handles allocation of the got header when crossing 32k. */
h->root.u.def.value = glink_offset;
}
ent->glink_offset = glink_offset;
+
+ if (htab->emit_stub_syms
+ && !add_stub_sym (ent, h, info))
+ return FALSE;
}
else
{
/* Pad out to align the start of PLTresolve. */
htab->glink->size += -htab->glink->size & 15;
htab->glink->size += GLINK_PLTRESOLVE;
+
+ if (htab->emit_stub_syms)
+ {
+ struct elf_link_hash_entry *sh;
+ sh = elf_link_hash_lookup (&htab->elf, "__glink",
+ TRUE, FALSE, FALSE);
+ if (sh == NULL)
+ return FALSE;
+ if (sh->root.type == bfd_link_hash_new)
+ {
+ sh->root.type = bfd_link_hash_defined;
+ sh->root.u.def.section = htab->glink;
+ sh->root.u.def.value = htab->glink_pltresolve;
+ sh->ref_regular = 1;
+ sh->def_regular = 1;
+ sh->ref_regular_nonweak = 1;
+ sh->forced_local = 1;
+ sh->non_elf = 0;
+ }
+ sh = elf_link_hash_lookup (&htab->elf, "__glink_PLTresolve",
+ TRUE, FALSE, FALSE);
+ if (sh == NULL)
+ return FALSE;
+ if (sh->root.type == bfd_link_hash_new)
+ {
+ sh->root.type = bfd_link_hash_defined;
+ sh->root.u.def.section = htab->glink;
+ sh->root.u.def.value = htab->glink->size - GLINK_PLTRESOLVE;
+ sh->ref_regular = 1;
+ sh->def_regular = 1;
+ sh->ref_regular_nonweak = 1;
+ sh->forced_local = 1;
+ sh->non_elf = 0;
+ }
+ }
}
/* We've now determined the sizes of the various dynamic sections.