aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf32-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2005-05-20 02:37:21 +0000
committerAlan Modra <amodra@gmail.com>2005-05-20 02:37:21 +0000
commit28e99bb61902d140e87c81f1d030653178616e9c (patch)
treed7fc66edb2f7d5abbd443a08881de0d61a9d07ee /bfd/elf32-ppc.c
parentf53fee919687927c26206e312c4b9f3e766ec422 (diff)
downloadgdb-28e99bb61902d140e87c81f1d030653178616e9c.zip
gdb-28e99bb61902d140e87c81f1d030653178616e9c.tar.gz
gdb-28e99bb61902d140e87c81f1d030653178616e9c.tar.bz2
* 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.
Diffstat (limited to 'bfd/elf32-ppc.c')
-rw-r--r--bfd/elf32-ppc.c82
1 files changed, 49 insertions, 33 deletions
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