* elflink.c (_bfd_elf_adjust_dynamic_symbol): Don't clear plt
authorAlan Modra <amodra@gmail.com>
Mon, 10 Aug 2009 06:14:04 +0000 (06:14 +0000)
committerAlan Modra <amodra@gmail.com>
Mon, 10 Aug 2009 06:14:04 +0000 (06:14 +0000)
info for STT_GNU_IFUNC.
* elf32-ppc.c (ppc_elf_check_relocs): Count a needed plt entry
on got refs in case the symbol turns out to be ifunc.
(ppc_elf_gc_sweep_hook): Similarly.
(ppc_elf_adjust_dynamic_symbol): Adjust assertion.
(allocate_dynrelocs): Don't specially allocate got relocs for ifunc.
(ppc_elf_size_dynamic_sections): Likewise.
(ppc_elf_relocate_section): Likewise.

bfd/ChangeLog
bfd/elf32-ppc.c
bfd/elflink.c

index 9ba413ccd7f848b7cc6ed19843624349c50ef787..8d103cd945878b108d9644a713d1eb73744d73fe 100644 (file)
@@ -1,3 +1,15 @@
+2009-08-10  Alan Modra  <amodra@bigpond.net.au>
+
+       * elflink.c (_bfd_elf_adjust_dynamic_symbol): Don't clear plt
+       info for STT_GNU_IFUNC.
+       * elf32-ppc.c (ppc_elf_check_relocs): Count a needed plt entry
+       on got refs in case the symbol turns out to be ifunc.
+       (ppc_elf_gc_sweep_hook): Similarly.
+       (ppc_elf_adjust_dynamic_symbol): Adjust assertion.
+       (allocate_dynrelocs): Don't specially allocate got relocs for ifunc.
+       (ppc_elf_size_dynamic_sections): Likewise.
+       (ppc_elf_relocate_section): Likewise.
+
 2006-08-09  Bernd Schmidt  <bernd.schmidt@analog.com>
 
        From Mike Frysinger <michael.frysinger@analog.com>
index 215b4b348925ab1373dea4a4cda6c218b057b1eb..542928d4d4254862c2c0caac443a35f4b0371a2a 100644 (file)
@@ -3580,6 +3580,14 @@ ppc_elf_check_relocs (bfd *abfd,
            /* This is a global offset table entry for a local symbol.  */
            if (!update_local_sym_info (abfd, symtab_hdr, r_symndx, tls_type))
              return FALSE;
+
+         /* We may also need a plt entry if the symbol turns out to be
+            an ifunc.  */
+         if (h != NULL && !info->shared)
+           {
+             if (!update_plt_info (abfd, &h->plt.plist, NULL, 0))
+               return FALSE;
+           }
          break;
 
          /* Indirect .sdata relocation.  */
@@ -4465,6 +4473,14 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
            {
              if (h->got.refcount > 0)
                h->got.refcount--;
+             if (!info->shared)
+               {
+                 struct plt_entry *ent;
+
+                 ent = find_plt_ent (&h->plt.plist, NULL, 0);
+                 if (ent->plt.refcount > 0)
+                   ent->plt.refcount -= 1;
+               }
            }
          else if (local_got_refcounts != NULL)
            {
@@ -4827,6 +4843,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   htab = ppc_elf_hash_table (info);
   BFD_ASSERT (htab->elf.dynobj != NULL
              && (h->needs_plt
+                 || h->type == STT_GNU_IFUNC
                  || h->u.weakdef != NULL
                  || (h->def_dynamic
                      && h->ref_regular
@@ -5289,18 +5306,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
        eh->elf.got.offset = (bfd_vma) -1;
       else
        {
-         asection *rsec = NULL;
          eh->elf.got.offset = allocate_got (htab, need);
          dyn = htab->elf.dynamic_sections_created;
          if ((info->shared
               || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf))
              && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
                  || eh->elf.root.type != bfd_link_hash_undefweak))
-           rsec = htab->relgot;
-         else if (h->type == STT_GNU_IFUNC)
-           rsec = htab->reliplt;
-         if (rsec != NULL)
            {
+             asection *rsec = htab->relgot;
              /* All the entries we allocated need relocs.
                 Except LD only needs one.  */
              if ((eh->tls_mask & TLS_LD) != 0
@@ -5571,9 +5584,6 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                if (info->shared)
                  htab->relgot->size += (need
                                         * (sizeof (Elf32_External_Rela) / 4));
-               else if ((*lgot_masks & PLT_IFUNC) != 0)
-                 htab->reliplt->size += (need
-                                         * (sizeof (Elf32_External_Rela) / 4));
              }
          }
        else
@@ -7137,7 +7147,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
              off &= ~1;
            else
              {
-               asection *rsec;
                unsigned int tls_m = (tls_mask
                                      & (TLS_LD | TLS_GD | TLS_DTPREL
                                         | TLS_TPREL | TLS_TPRELGD));
@@ -7176,17 +7185,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
                      }
 
                    /* Generate relocs for the dynamic linker.  */
-                   rsec = NULL;
                    if ((info->shared || indx != 0)
                        && (offp == &htab->tlsld_got.offset
                            || h == NULL
                            || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                            || h->root.type != bfd_link_hash_undefweak))
-                     rsec = htab->relgot;
-                   else if (ifunc != NULL)
-                     rsec = htab->reliplt;
-                   if (rsec != NULL)
                      {
+                       asection *rsec = htab->relgot;
+
                        outrel.r_offset = (htab->got->output_section->vma
                                           + htab->got->output_offset
                                           + off);
index a11706383f73dae48bedba0438739e0ca0d783d1..5818912873b1c37fc1559031941b4f3fc74c5fa1 100644 (file)
@@ -2605,6 +2605,7 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
      about symbols which are defined by one dynamic object and
      referenced by another one?  */
   if (!h->needs_plt
+      && h->type != STT_GNU_IFUNC
       && (h->def_regular
          || !h->def_dynamic
          || (!h->ref_regular