* elf32-hppa.c (elf32_hppa_check_relocs): Don't NEED_PLT for
authorAlan Modra <amodra@gmail.com>
Wed, 30 May 2001 14:30:33 +0000 (14:30 +0000)
committerAlan Modra <amodra@gmail.com>
Wed, 30 May 2001 14:30:33 +0000 (14:30 +0000)
millicode.  Don't allocate .got and .rela.got space here..
(elf32_hppa_gc_sweep_hook): ..and no need to deallocate here..
(elf32_hppa_adjust_dynamic_symbol): ..and don't allocate .plt and
.rela.plt here..
(hppa_handle_PIC_calls): ..nor here..
(allocate_plt_and_got): ..instead do it all here.  New function.
(elf32_hppa_size_dynamic_sections): Allocate local .got space and
call allocate_plt_and_got.  No need to zap .got if not dynamic.
(elf32_hppa_final_link): Call regular bfd_final_link instead of
gc_common_final_link.
(WILL_CALL_FINISH_DYNAMIC_SYMBOL): Define.
(elf32_hppa_relocate_section): Use it here.
(elf32_hppa_finish_dynamic_symbol): Remove superfluous test of
dynamic_sections_created.
(hppa_type_of_stub): Don't LONG_BRANCH_VIA_PLT if millicode sym.

bfd/ChangeLog
bfd/elf32-hppa.c

index 0bbc7d2..7079dc4 100644 (file)
@@ -1,3 +1,22 @@
+2001-05-30  Alan Modra  <amodra@one.net.au>
+
+       * elf32-hppa.c (elf32_hppa_check_relocs): Don't NEED_PLT for
+       millicode.  Don't allocate .got and .rela.got space here..
+       (elf32_hppa_gc_sweep_hook): ..and no need to deallocate here..
+       (elf32_hppa_adjust_dynamic_symbol): ..and don't allocate .plt and
+       .rela.plt here..
+       (hppa_handle_PIC_calls): ..nor here..
+       (allocate_plt_and_got): ..instead do it all here.  New function.
+       (elf32_hppa_size_dynamic_sections): Allocate local .got space and
+       call allocate_plt_and_got.  No need to zap .got if not dynamic.
+       (elf32_hppa_final_link): Call regular bfd_final_link instead of
+       gc_common_final_link.
+       (WILL_CALL_FINISH_DYNAMIC_SYMBOL): Define.
+       (elf32_hppa_relocate_section): Use it here.
+       (elf32_hppa_finish_dynamic_symbol): Remove superfluous test of
+       dynamic_sections_created.
+       (hppa_type_of_stub): Don't LONG_BRANCH_VIA_PLT if millicode sym.
+
 2001-05-28  Andreas Jaeger  <aj@suse.de>
 
        * elf64-x86-64.c (elf64_86_64_size_info): Remove, we can use the
@@ -6,7 +25,6 @@
 
 2001-05-28  Thiemo Seufer  <seufer@csv.ica.uni-stuttgart.de>
 
-       src/bfd/ChangeLog
        * elflink.h (elf_link_size_reloc_section): Use bfd_zmalloc instead of
        a zeroing loop.
        (elf_link_output_relocs): Handle MIPS ELF64 relocations correctly.
index cda7110..9f46a3d 100644 (file)
@@ -366,6 +366,9 @@ static boolean elf32_hppa_adjust_dynamic_symbol
 static boolean hppa_handle_PIC_calls
   PARAMS ((struct elf_link_hash_entry *, PTR));
 
+static boolean allocate_plt_and_got
+  PARAMS ((struct elf_link_hash_entry *, PTR));
+
 #if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \
      || RELATIVE_DYNAMIC_RELOCS)
 static boolean hppa_discard_copies
@@ -766,7 +769,8 @@ hppa_type_of_stub (input_sec, rel, hash, destination)
 #if LONG_BRANCH_VIA_PLT
       if (hash != NULL
          && hash->elf.dynindx != -1
-         && hash->elf.plt.offset != (bfd_vma) -1)
+         && hash->elf.plt.offset != (bfd_vma) -1
+         && hash->elf.type != STT_PARISC_MILLI)
        {
          /* If we are doing a shared link and find we need a long
             branch stub, then go via the .plt if possible.  */
@@ -1302,7 +1306,18 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
             create a PLT entry for all PLABELs, because PLABELs with
             local symbols may be passed via a pointer to another
             object.  Additionally, output a dynamic relocation
-            pointing to the PLT entry.  */
+            pointing to the PLT entry.
+            For executables, the original 32-bit ABI allowed two
+            different styles of PLABELs (function pointers):  For
+            global functions, the PLABEL word points into the .plt
+            two bytes past a (function address, gp) pair, and for
+            local functions the PLABEL points directly at the
+            function.  The magic +2 for the first type allows us to
+            differentiate between the two.  As you can imagine, this
+            is a real pain when it comes to generating code to call
+            functions indirectly or to compare function pointers.
+            We avoid the mess by always pointing a PLABEL into the
+            .plt, even for local functions.  */
          need_entry = PLT_PLABEL | NEED_PLT | NEED_DYNREL;
          break;
 
@@ -1333,6 +1348,8 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                 where a symbol is forced local by versioning, or due
                 to symbolic linking, and we lose the .plt entry.  */
              need_entry = NEED_PLT | NEED_STUBREL;
+             if (h->elf.type == STT_PARISC_MILLI)
+               need_entry = NEED_STUBREL;
            }
          break;
 
@@ -1431,9 +1448,6 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                                                                  &h->elf))
                        return false;
                    }
-
-                 hplink->sgot->_raw_size += GOT_ENTRY_SIZE;
-                 hplink->srelgot->_raw_size += sizeof (Elf32_External_Rela);
                }
              else
                h->elf.got.refcount += 1;
@@ -1458,20 +1472,7 @@ elf32_hppa_check_relocs (abfd, info, sec, relocs)
                  memset (local_got_refcounts, -1, size);
                }
              if (local_got_refcounts[r_symndx] == -1)
-               {
-                 local_got_refcounts[r_symndx] = 1;
-
-                 hplink->sgot->_raw_size += GOT_ENTRY_SIZE;
-                 if (info->shared)
-                   {
-                     /* If we are generating a shared object, we need to
-                        output a reloc so that the dynamic linker can
-                        adjust this GOT entry (because the address
-                        the shared library is loaded at is not fixed).  */
-                     hplink->srelgot->_raw_size +=
-                       sizeof (Elf32_External_Rela);
-                   }
-               }
+               local_got_refcounts[r_symndx] = 1;
              else
                local_got_refcounts[r_symndx] += 1;
            }
@@ -1773,8 +1774,6 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs)
   struct elf_link_hash_entry *h;
   struct elf32_hppa_link_hash_table *hplink;
   bfd *dynobj;
-  asection *sgot;
-  asection *srelgot;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
@@ -1787,9 +1786,6 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs)
   if (dynobj == NULL)
     return true;
 
-  sgot = hplink->sgot;
-  srelgot = hplink->srelgot;
-
   relend = relocs + sec->reloc_count;
   for (rel = relocs; rel < relend; rel++)
     switch ((unsigned int) ELF32_R_TYPE (rel->r_info))
@@ -1802,27 +1798,12 @@ elf32_hppa_gc_sweep_hook (abfd, info, sec, relocs)
          {
            h = sym_hashes[r_symndx - symtab_hdr->sh_info];
            if (h->got.refcount > 0)
-             {
-               h->got.refcount -= 1;
-               if (h->got.refcount == 0)
-                 {
-                   sgot->_raw_size -= GOT_ENTRY_SIZE;
-                   srelgot->_raw_size -= sizeof (Elf32_External_Rela);
-                 }
-             }
+             h->got.refcount -= 1;
          }
        else if (local_got_refcounts != NULL)
          {
            if (local_got_refcounts[r_symndx] > 0)
-             {
-               local_got_refcounts[r_symndx] -= 1;
-               if (local_got_refcounts[r_symndx] == 0)
-                 {
-                   sgot->_raw_size -= GOT_ENTRY_SIZE;
-                   if (info->shared)
-                     srelgot->_raw_size -= sizeof (Elf32_External_Rela);
-                 }
-             }
+             local_got_refcounts[r_symndx] -= 1;
          }
        break;
 
@@ -1880,6 +1861,17 @@ elf32_hppa_hide_symbol (info, h)
     }
 }
 
+/* This is the condition under which elf32_hppa_finish_dynamic_symbol
+   will be called from elflink.h.  If elflink.h doesn't call our
+   finish_dynamic_symbol routine, we'll need to do something about
+   initializing any .plt and .got entries in elf32_hppa_relocate_section.  */
+#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
+  ((DYN)                                                               \
+   && ((INFO)->shared                                                  \
+       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)     \
+   && ((H)->dynindx != -1                                              \
+       || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
 /* Adjust a symbol defined by a dynamic object and referenced by a
    regular object.  The current definition is in some section of the
    dynamic object, but we're not including those sections.  We have to
@@ -1938,19 +1930,6 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
            }
        }
 
-      /* Make an entry in the .plt section.  */
-      s = hplink->splt;
-      h->plt.offset = s->_raw_size;
-      if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
-         && ((struct elf32_hppa_link_hash_entry *) h)->plabel
-         && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
-       {
-         /* Add some extra space for the dynamic linker to use.  */
-         s->_raw_size += PLABEL_PLT_ENTRY_SIZE;
-       }
-      else
-       s->_raw_size += PLT_ENTRY_SIZE;
-
       if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
        {
          /* Make sure this symbol is output as a dynamic symbol.  */
@@ -1960,16 +1939,8 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
              if (! bfd_elf32_link_record_dynamic_symbol (info, h))
                return false;
            }
-
-         if (h->dynindx != -1 || info->shared)
-           {
-             /* We also need to make an entry in the .rela.plt section.  */
-             s = hplink->srelplt;
-             s->_raw_size += sizeof (Elf32_External_Rela);
-
-             hplink->need_plt_stub = 1;
-           }
        }
+
       return true;
     }
 
@@ -2061,13 +2032,8 @@ elf32_hppa_adjust_dynamic_symbol (info, h)
 static boolean
 hppa_handle_PIC_calls (h, inf)
      struct elf_link_hash_entry *h;
-     PTR inf;
+     PTR inf ATTRIBUTE_UNUSED;
 {
-  struct bfd_link_info *info;
-  bfd *dynobj;
-  struct elf32_hppa_link_hash_table *hplink;
-  asection *s;
-
   if (! (h->plt.refcount > 0
         && (h->root.type == bfd_link_hash_defined
             || h->root.type == bfd_link_hash_defweak)
@@ -2082,14 +2048,67 @@ hppa_handle_PIC_calls (h, inf)
   ((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call = 1;
   ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;
 
+  return true;
+}
+
+/* Allocate space in .plt, .got and associated reloc sections for
+   global syms.  */
+
+static boolean
+allocate_plt_and_got (h, inf)
+     struct elf_link_hash_entry *h;
+     PTR inf;
+{
+  struct bfd_link_info *info;
+  struct elf32_hppa_link_hash_table *hplink;
+  asection *s;
+
   info = (struct bfd_link_info *) inf;
   hplink = hppa_link_hash_table (info);
-  dynobj = hplink->root.dynobj;
+  if ((hplink->root.dynamic_sections_created
+       && h->plt.refcount > 0)
+      || ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
+    {
+      /* Make an entry in the .plt section.  */
+      s = hplink->splt;
+      h->plt.offset = s->_raw_size;
+      if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
+         && ((struct elf32_hppa_link_hash_entry *) h)->plabel
+         && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+       {
+         /* Add some extra space for the dynamic linker to use.  */
+         s->_raw_size += PLABEL_PLT_ENTRY_SIZE;
+       }
+      else
+       s->_raw_size += PLT_ENTRY_SIZE;
+
+      if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call
+         && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+       {
+         /* We also need to make an entry in the .rela.plt section.  */
+         hplink->srelplt->_raw_size += sizeof (Elf32_External_Rela);
+         hplink->need_plt_stub = 1;
+       }
+    }
+  else
+    {
+      h->plt.offset = (bfd_vma) -1;
+      h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+    }
 
-  /* Make an entry in the .plt section.  */
-  s = hplink->splt;
-  h->plt.offset = s->_raw_size;
-  s->_raw_size += PLT_ENTRY_SIZE;
+  if (h->got.refcount > 0)
+    {
+      boolean dyn;
+
+      s = hplink->sgot;
+      h->got.offset = s->_raw_size;
+      s->_raw_size += GOT_ENTRY_SIZE;
+      dyn = hplink->root.dynamic_sections_created;
+      if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+       hplink->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+    }
+  else
+    h->got.offset = (bfd_vma) -1;
 
   return true;
 }
@@ -2206,32 +2225,54 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
                              clobber_millicode_symbols,
                              info);
 
-      /* Set up .plt offsets for local plabels.  */
+      /* Set up .got and .plt offsets for local syms.  */
       for (i = info->input_bfds; i; i = i->link_next)
        {
+         bfd_signed_vma *local_got;
+         bfd_signed_vma *end_local_got;
          bfd_signed_vma *local_plt;
          bfd_signed_vma *end_local_plt;
          bfd_size_type locsymcount;
          Elf_Internal_Shdr *symtab_hdr;
+         asection *srel;
 
-         local_plt = elf_local_got_refcounts (i);
-         if (!local_plt)
+         if (bfd_get_flavour (i) != bfd_target_elf_flavour)
+           continue;
+
+         local_got = elf_local_got_refcounts (i);
+         if (!local_got)
            continue;
 
          symtab_hdr = &elf_tdata (i)->symtab_hdr;
          locsymcount = symtab_hdr->sh_info;
-         local_plt += locsymcount;
-         end_local_plt = local_plt + locsymcount;
+         end_local_got = local_got + locsymcount;
+         s = hplink->sgot;
+         srel = hplink->srelgot;
+         for (; local_got < end_local_got; ++local_got)
+           {
+             if (*local_got > 0)
+               {
+                 *local_got = s->_raw_size;
+                 s->_raw_size += GOT_ENTRY_SIZE;
+                 if (info->shared)
+                   srel->_raw_size += sizeof (Elf32_External_Rela);
+               }
+             else
+               *local_got = (bfd_vma) -1;
+           }
 
+         local_plt = end_local_got;
+         end_local_plt = local_plt + locsymcount;
+         s = hplink->splt;
+         srel = hplink->srelplt;
          for (; local_plt < end_local_plt; ++local_plt)
            {
              if (*local_plt > 0)
                {
-                 s = hplink->splt;
                  *local_plt = s->_raw_size;
                  s->_raw_size += PLT_ENTRY_SIZE;
                  if (info->shared)
-                   hplink->srelplt->_raw_size += sizeof (Elf32_External_Rela);
+                   srel->_raw_size += sizeof (Elf32_External_Rela);
                }
              else
                *local_plt = (bfd_vma) -1;
@@ -2247,15 +2288,13 @@ elf32_hppa_size_dynamic_sections (output_bfd, info)
        elf_link_hash_traverse (&hplink->root,
                                hppa_handle_PIC_calls,
                                info);
-
-      /* We may have created entries in the .rela.got section.
-        However, if we are not creating the dynamic sections, we will
-        not actually use these entries.  Reset the size of .rela.got,
-        which will cause it to get stripped from the output file
-        below.  */
-      hplink->srelgot->_raw_size = 0;
     }
 
+  /* Allocate global sym .plt and .got entries.  */
+  elf_link_hash_traverse (&hplink->root,
+                         allocate_plt_and_got,
+                         info);
+
 #if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \
      || RELATIVE_DYNAMIC_RELOCS)
   /* If this is a -Bsymbolic shared link, then we need to discard all
@@ -3164,9 +3203,8 @@ elf32_hppa_final_link (abfd, info)
 {
   asection *s;
 
-  /* Invoke the regular ELF garbage collecting linker to do all the
-     work.  */
-  if (!_bfd_elf32_gc_common_final_link (abfd, info))
+  /* Invoke the regular ELF linker to do all the work.  */
+  if (!bfd_elf32_bfd_final_link (abfd, info))
     return false;
 
   /* If we're producing a final executable, sort the contents of the
@@ -3635,16 +3673,14 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
          if (h != NULL)
            {
              bfd_vma off;
+             boolean dyn;
 
              off = h->elf.got.offset;
              if (off == (bfd_vma) -1)
                abort ();
 
-             if (! hplink->root.dynamic_sections_created
-                 || (info->shared
-                     && (info->symbolic || h->elf.dynindx == -1)
-                     && (h->elf.elf_link_hash_flags
-                         & ELF_LINK_HASH_DEF_REGULAR) != 0))
+             dyn = hplink->root.dynamic_sections_created;
+             if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf))
                {
                  /* This is actually a static link, or it is a
                     -Bsymbolic link and the symbol is defined
@@ -3742,8 +3778,7 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
              if (h != NULL)
                {
                  off = h->elf.plt.offset;
-                 if (!info->shared
-                     && (h->elf.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL))
+                 if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, &h->elf))
                    {
                      /* In a non-shared link, adjust_dynamic_symbols
                         isn't called for symbols forced local.  We
@@ -4133,15 +4168,14 @@ elf32_hppa_finish_dynamic_symbol (output_bfd, info, h, sym)
                      + hplink->sgot->output_offset
                      + hplink->sgot->output_section->vma);
 
-      /* If this is a static link, or it is a -Bsymbolic link and the
-        symbol is defined locally or was forced to be local because
-        of a version file, we just want to emit a RELATIVE reloc.
-        The entry in the global offset table will already have been
-        initialized in the relocate_section function.  */
-      if (! hplink->root.dynamic_sections_created
-         || (info->shared
-             && (info->symbolic || h->dynindx == -1)
-             && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+      /* If this is a -Bsymbolic link and the symbol is defined
+        locally or was forced to be local because of a version file,
+        we just want to emit a RELATIVE reloc.  The entry in the
+        global offset table will already have been initialized in the
+        relocate_section function.  */
+      if (info->shared
+         && (info->symbolic || h->dynindx == -1)
+         && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
        {
          rel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
          rel.r_addend = (h->root.u.def.value