OSDN Git Service

* elf32-ppc.c (allocate_dynrelocs): Correct plt offset assigned
authorAlan Modra <amodra@bigpond.net.au>
Fri, 20 May 2005 02:37:21 +0000 (02:37 +0000)
committerAlan Modra <amodra@bigpond.net.au>
Fri, 20 May 2005 02:37:21 +0000 (02:37 +0000)
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.

bfd/ChangeLog
bfd/elf32-ppc.c

index c01b8de..1212176 100644 (file)
@@ -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'.
index 2a6a163..a70255a 100644 (file)
@@ -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