aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elf32-ppc.c82
2 files changed, 57 insertions, 33 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index c01b8de..1212176 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2005-05-20 Alan Modra <amodra@bigpond.net.au>
+
+ * elf32-ppc.c (allocate_dynrelocs): Correct plt offset assigned
+ for second and subsequent list entries. Only allocate multiple
+ glink stubs when shared or pie.
+ (ppc_elf_finish_dynamic_symbol): Break out early when only one
+ glink stub is needed.
+
2005-05-19 Zack Weinberg <zack@codesourcery.com>
* Makefile.am: Have 'all' depend on 'info'.
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 2a6a163..a70255a 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -4058,6 +4058,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
{
struct plt_entry *ent;
bfd_boolean doneone = FALSE;
+ bfd_vma plt_offset = 0, glink_offset = 0;
+
for (ent = h->plt.plist; ent != NULL; ent = ent->next)
if (ent->plt.refcount > 0)
{
@@ -4076,56 +4078,67 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
if (!htab->old_plt)
{
- ent->plt.offset = s->size;
if (!doneone)
- s->size += 4;
+ {
+ plt_offset = s->size;
+ s->size += 4;
+ }
+ ent->plt.offset = plt_offset;
s = htab->glink;
- if (!info->shared
+ if (!doneone || info->shared || info->pie)
+ {
+ glink_offset = s->size;
+ s->size += GLINK_ENTRY_SIZE;
+ }
+ if (!doneone
+ && !info->shared
&& !h->def_regular)
{
h->root.u.def.section = s;
- h->root.u.def.value = s->size;
+ h->root.u.def.value = glink_offset;
}
- ent->glink_offset = s->size;
- s->size += GLINK_ENTRY_SIZE;
+ ent->glink_offset = glink_offset;
}
else
{
- /* If this is the first .plt entry, make room for the
- special first entry. */
- if (s->size == 0)
- s->size += PLT_INITIAL_ENTRY_SIZE;
-
- /* The PowerPC PLT is actually composed of two parts, the
- first part is 2 words (for a load and a jump), and then
- there is a remaining word available at the end. */
- ent->plt.offset = (PLT_INITIAL_ENTRY_SIZE
- + (PLT_SLOT_SIZE
- * ((s->size - PLT_INITIAL_ENTRY_SIZE)
- / PLT_ENTRY_SIZE)));
-
- /* If this symbol is not defined in a regular file, and we
- are not generating a shared library, then set the symbol
- to this location in the .plt. This is required to make
- function pointers compare as equal between the normal
- executable and the shared library. */
- if (! info->shared
- && !h->def_regular)
- {
- h->root.u.def.section = s;
- h->root.u.def.value = ent->plt.offset;
- }
-
- /* Make room for this entry. After the 8192nd entry, room
- for two entries is allocated. */
if (!doneone)
{
+ /* If this is the first .plt entry, make room
+ for the special first entry. */
+ if (s->size == 0)
+ s->size += PLT_INITIAL_ENTRY_SIZE;
+
+ /* The PowerPC PLT is actually composed of two
+ parts, the first part is 2 words (for a load
+ and a jump), and then there is a remaining
+ word available at the end. */
+ plt_offset = (PLT_INITIAL_ENTRY_SIZE
+ + (PLT_SLOT_SIZE
+ * ((s->size - PLT_INITIAL_ENTRY_SIZE)
+ / PLT_ENTRY_SIZE)));
+
+ /* If this symbol is not defined in a regular
+ file, and we are not generating a shared
+ library, then set the symbol to this location
+ in the .plt. This is required to make
+ function pointers compare as equal between
+ the normal executable and the shared library. */
+ if (! info->shared
+ && !h->def_regular)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = plt_offset;
+ }
+
+ /* Make room for this entry. After the 8192nd
+ entry, room for two entries is allocated. */
s->size += PLT_ENTRY_SIZE;
if ((s->size - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE
> PLT_NUM_SINGLE_ENTRIES)
s->size += PLT_ENTRY_SIZE;
}
+ ent->plt.offset = plt_offset;
}
/* We also need to make an entry in the .rela.plt section. */
@@ -6508,6 +6521,9 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
p += 4;
bfd_put_32 (output_bfd, BCTR, p);
p += 4;
+
+ /* We only need one non-PIC glink stub. */
+ break;
}
}
else