aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/elf32-ppc.c92
-rw-r--r--bfd/elf32-ppc.h2
3 files changed, 102 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1db9170..8d89bc1 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,15 @@
2005-12-08 Alan Modra <amodra@bigpond.net.au>
+ * elf32-ppc.c (struct ppc_elf_link_hash_table): Add emit_stub_syms.
+ (ppc_elf_select_plt_layout): Add emit_stub_syms param, save to htab.
+ (add_stub_sym): New function.
+ (allocate_dynrelocs): Call add_stub_sym.
+ (ppc_elf_size_dynamic_sections): Emit __glink and __glink_PLTresolve
+ when emit_stub_syms.
+ * elf32-ppc.h (ppc_elf_select_plt_layout): Update prototype.
+
+2005-12-08 Alan Modra <amodra@bigpond.net.au>
+
* reloc.c (enum complain_overflow): Correct comments.
(bfd_check_overflow): Combine complain_overflow_bitfield and
complain_overflow_signed code.
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 70d03a3..5b8c955 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -2353,6 +2353,9 @@ struct ppc_elf_link_hash_table
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;
@@ -3593,7 +3596,8 @@ ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
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;
@@ -3602,6 +3606,8 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
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. */
@@ -4207,6 +4213,51 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
return TRUE;
}
+/* Generate a symbol to mark plt call stubs, of the form
+ xxxxxxxx_plt_call_<callee> where xxxxxxxx is a hex number, usually 0,
+ specifying the addend on the plt relocation, or for -fPIC,
+ xxxxxxxx.got2_plt_call_<callee>. */
+
+static bfd_boolean
+add_stub_sym (struct plt_entry *ent,
+ struct elf_link_hash_entry *h,
+ struct ppc_elf_link_hash_table *htab)
+{
+ struct elf_link_hash_entry *sh;
+ size_t len1, len2, len3;
+ char *name;
+
+ len1 = strlen (h->root.root.string);
+ len2 = sizeof ("plt_call_") - 1;
+ len3 = 0;
+ if (ent->sec)
+ len3 = strlen (ent->sec->name);
+ name = bfd_malloc (len1 + len2 + len3 + 10);
+ if (name == NULL)
+ return FALSE;
+ sprintf (name, "%08x", (unsigned) ent->addend & 0xffffffff);
+ if (ent->sec)
+ memcpy (name + 8, ent->sec->name, len3);
+ name[len3 + 8] = '_';
+ memcpy (name + len3 + 9, "plt_call_", len2);
+ memcpy (name + len3 + 9 + 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. */
@@ -4308,6 +4359,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
h->root.u.def.value = glink_offset;
}
ent->glink_offset = glink_offset;
+
+ if (htab->emit_stub_syms
+ && !add_stub_sym (ent, h, htab))
+ return FALSE;
}
else
{
@@ -4747,6 +4802,41 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
/* 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.
diff --git a/bfd/elf32-ppc.h b/bfd/elf32-ppc.h
index 2bec595..5f8f63a 100644
--- a/bfd/elf32-ppc.h
+++ b/bfd/elf32-ppc.h
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
-int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int);
+int ppc_elf_select_plt_layout (bfd *, struct bfd_link_info *, int, int);
asection *ppc_elf_tls_setup (bfd *, struct bfd_link_info *);
bfd_boolean ppc_elf_tls_optimize (bfd *, struct bfd_link_info *);
void ppc_elf_set_sdata_syms (bfd *, struct bfd_link_info *);