bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Sat, 6 Jun 2009 22:39:25 +0000 (22:39 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Sat, 6 Jun 2009 22:39:25 +0000 (22:39 +0000)
2009-06-06  H.J. Lu  <hongjiu.lu@intel.com>

* elf32-i386.c (elf_i386_link_hash_table): Add irelifunc.
(elf_i386_link_hash_table_create): Initialize irelifunc.
(elf_i386_check_relocs): Updated.  Set up irelifunc for
shared objects.
(elf_i386_allocate_dynrelocs): Use irelifunc for dynamic
relocation for non-GOT reference of STT_GNU_IFUNC symbol in
shared objects.
(elf_i386_relocate_section): Likewise.

* elf64-x86-64.c (elf64_x86_64_link_hash_table): Add irelifunc.
(elf64_x86_64_link_hash_table_create): Initialize irelifunc.
(elf64_x86_64_check_relocs): Updated.  Set up irelifunc for
shared objects.
(elf64_x86_64_allocate_dynrelocs): Use irelifunc for dynamic
relocation for non-GOT reference of STT_GNU_IFUNC symbol in
shared objects.
(elf64_x86_64_relocate_section): Likewise.

* elf-bfd.h (_bfd_elf_create_static_ifunc_sections): Renamed to
...
(_bfd_elf_create_ifunc_sections): This.

* elflink.c (_bfd_elf_create_static_ifunc_sections): Renamd to
...
(_bfd_elf_create_ifunc_sections): This.  Create .rel[a].ifunc
for shared objects.

ld/

2009-06-06  H.J. Lu  <hongjiu.lu@intel.com>

* scripttempl/elf.sc: Add .rel.ifunc and .rela.ifunc.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf32-i386.c
bfd/elf64-x86-64.c
bfd/elflink.c
ld/ChangeLog
ld/scripttempl/elf.sc

index 8948973..c306b52 100644 (file)
@@ -1,5 +1,34 @@
 2009-06-06  H.J. Lu  <hongjiu.lu@intel.com>
 
+       * elf32-i386.c (elf_i386_link_hash_table): Add irelifunc.
+       (elf_i386_link_hash_table_create): Initialize irelifunc.
+       (elf_i386_check_relocs): Updated.  Set up irelifunc for
+       shared objects.
+       (elf_i386_allocate_dynrelocs): Use irelifunc for dynamic
+       relocation for non-GOT reference of STT_GNU_IFUNC symbol in
+       shared objects.
+       (elf_i386_relocate_section): Likewise.
+
+       * elf64-x86-64.c (elf64_x86_64_link_hash_table): Add irelifunc.
+       (elf64_x86_64_link_hash_table_create): Initialize irelifunc.
+       (elf64_x86_64_check_relocs): Updated.  Set up irelifunc for
+       shared objects.
+       (elf64_x86_64_allocate_dynrelocs): Use irelifunc for dynamic
+       relocation for non-GOT reference of STT_GNU_IFUNC symbol in
+       shared objects.
+       (elf64_x86_64_relocate_section): Likewise.
+
+       * elf-bfd.h (_bfd_elf_create_static_ifunc_sections): Renamed to
+       ...
+       (_bfd_elf_create_ifunc_sections): This.
+
+       * elflink.c (_bfd_elf_create_static_ifunc_sections): Renamd to
+       ...
+       (_bfd_elf_create_ifunc_sections): This.  Create .rel[a].ifunc
+       for shared objects.
+
+2009-06-06  H.J. Lu  <hongjiu.lu@intel.com>
+
        * elf32-i386.c (elf_i386_check_relocs): Make room for dynamic
        relocation for R_386_32 against STT_GNU_IFUNC symbol when
        building shared object.  Check info->executable instead of
index 258d11c..610aafc 100644 (file)
@@ -2146,7 +2146,7 @@ extern int _bfd_elf_obj_attrs_arg_type (bfd *, int, int);
 extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *);
 extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *);
 
-extern bfd_boolean _bfd_elf_create_static_ifunc_sections
+extern bfd_boolean _bfd_elf_create_ifunc_sections
   (bfd *, struct bfd_link_info *);
 
 /* Large common section.  */
index 8fb8742..b2918cf 100644 (file)
@@ -678,6 +678,7 @@ struct elf_i386_link_hash_table
   asection *igotplt;
   asection *iplt;
   asection *irelplt;
+  asection *irelifunc;
 
   /* The (unloaded but important) .rel.plt.unloaded section on VxWorks.  */
   asection *srelplt2;
@@ -777,6 +778,7 @@ elf_i386_link_hash_table_create (bfd *abfd)
   ret->igotplt= NULL;
   ret->iplt = NULL;
   ret->irelplt= NULL;
+  ret->irelifunc = NULL;
   ret->tls_ldm_got.refcount = 0;
   ret->next_tls_desc_index = 0;
   ret->sgotplt_jump_table_size = 0;
@@ -1279,21 +1281,30 @@ elf_i386_check_relocs (bfd *abfd,
            case R_386_PLT32:
            case R_386_GOT32:
            case R_386_GOTOFF:
-             if (!info->shared && htab->iplt == NULL)
+             if (htab->irelifunc == NULL && htab->iplt == NULL)
                {
-                 if (!_bfd_elf_create_static_ifunc_sections (abfd,
-                                                             info))
+                 if (!_bfd_elf_create_ifunc_sections (abfd, info))
                    return FALSE;
 
-                 htab->iplt = bfd_get_section_by_name (abfd, ".iplt");
-                 htab->irelplt = bfd_get_section_by_name (abfd,
-                                                          ".rel.iplt");
-                 htab->igotplt = bfd_get_section_by_name (abfd,
-                                                          ".igot.plt");
-                 if (!htab->iplt
-                     || !htab->irelplt
-                     || !htab->igotplt)
-                   abort ();
+                 if (info->shared)
+                   {
+                     htab->irelifunc = bfd_get_section_by_name (abfd,
+                                                                ".rel.ifunc");
+                     if (!htab->irelifunc)
+                       abort ();
+                   }
+                 else
+                   {
+                     htab->iplt = bfd_get_section_by_name (abfd, ".iplt");
+                     htab->irelplt = bfd_get_section_by_name (abfd,
+                                                              ".rel.iplt");
+                     htab->igotplt = bfd_get_section_by_name (abfd,
+                                                              ".igot.plt");
+                     if (!htab->iplt
+                         || !htab->irelplt
+                         || !htab->igotplt)
+                       abort ();
+                   }
                }
              break;
            }
@@ -2038,10 +2049,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       /* Finally, allocate space.  */
       for (p = eh->dyn_relocs; p != NULL; p = p->next)
-       {
-         asection * sreloc = elf_section_data (p->sec)->sreloc;
-         sreloc->size += p->count * sizeof (Elf32_External_Rel);
-       }
+       htab->irelifunc->size += p->count * sizeof (Elf32_External_Rel);
 
       /* For STT_GNU_IFUNC symbol, .got.plt has the real function
         addres and .got has the PLT entry adddress.  We will load
@@ -3010,7 +3018,7 @@ elf_i386_relocate_section (bfd *output_bfd,
                  else
                    outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
 
-                 sreloc = elf_section_data (input_section)->sreloc;
+                 sreloc = htab->irelifunc;
                  loc = sreloc->contents;
                  loc += (sreloc->reloc_count++
                          * sizeof (Elf32_External_Rel));
index 0ba5759..6819b34 100644 (file)
@@ -496,6 +496,7 @@ struct elf64_x86_64_link_hash_table
   asection *igotplt;
   asection *iplt;
   asection *irelplt;
+  asection *irelifunc;
 
   /* The offset into splt of the PLT entry for the TLS descriptor
      resolver.  Special values are 0, if not necessary (or not found
@@ -591,6 +592,7 @@ elf64_x86_64_link_hash_table_create (bfd *abfd)
   ret->igotplt= NULL;
   ret->iplt = NULL;
   ret->irelplt= NULL;
+  ret->irelifunc = NULL;
   ret->sym_sec.abfd = NULL;
   ret->tlsdesc_plt = 0;
   ret->tlsdesc_got = 0;
@@ -1065,21 +1067,30 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            case R_X86_64_PLT32:
            case R_X86_64_GOTPCREL:
            case R_X86_64_GOTPCREL64:
-             if (!info->shared && htab->iplt == NULL)
+             if (htab->irelifunc == NULL && htab->iplt == NULL)
                {
-                 if (!_bfd_elf_create_static_ifunc_sections (abfd,
-                                                             info))
+                 if (!_bfd_elf_create_ifunc_sections (abfd, info))
                    return FALSE;
 
-                 htab->iplt = bfd_get_section_by_name (abfd, ".iplt");
-                 htab->irelplt = bfd_get_section_by_name (abfd,
-                                                          ".rela.iplt");
-                 htab->igotplt = bfd_get_section_by_name (abfd,
-                                                          ".igot.plt");
-                 if (!htab->iplt
-                     || !htab->irelplt
-                     || !htab->igotplt)
-                   abort ();
+                 if (info->shared)
+                   {
+                     htab->irelifunc = bfd_get_section_by_name (abfd,
+                                                                ".rela.ifunc");
+                     if (!htab->irelifunc)
+                       abort ();
+                   }
+                 else
+                   {
+                     htab->iplt = bfd_get_section_by_name (abfd, ".iplt");
+                     htab->irelplt = bfd_get_section_by_name (abfd,
+                                                              ".rela.iplt");
+                     htab->igotplt = bfd_get_section_by_name (abfd,
+                                                              ".igot.plt");
+                     if (!htab->iplt
+                         || !htab->irelplt
+                         || !htab->igotplt)
+                       abort ();
+                   }
                }
              break;
            }
@@ -1880,10 +1891,7 @@ elf64_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 
       /* Finally, allocate space.  */
       for (p = eh->dyn_relocs; p != NULL; p = p->next)
-       {
-         asection * sreloc = elf_section_data (p->sec)->sreloc;
-         sreloc->size += p->count * sizeof (Elf64_External_Rela);
-       }
+       htab->irelifunc->size += p->count * sizeof (Elf64_External_Rela);
 
       /* For STT_GNU_IFUNC symbol, .got.plt has the real function
         addres and .got has the PLT entry adddress.  We will load
@@ -2730,7 +2738,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                      outrel.r_addend = 0;
                    }
 
-                 sreloc = elf_section_data (input_section)->sreloc;
+                 sreloc = htab->irelifunc;
                  loc = sreloc->contents;
                  loc += (sreloc->reloc_count++
                          * sizeof (Elf64_External_Rela));
index d182807..e3a1670 100644 (file)
@@ -12492,31 +12492,17 @@ _bfd_elf_make_dynamic_reloc_section (asection *         sec,
   return reloc_sec;
 }
 
-/* Create sections needed by STT_GNU_IFUNC symbol for static
-   executables.  */
+/* Create sections needed by STT_GNU_IFUNC symbol.  */
 
 bfd_boolean
-_bfd_elf_create_static_ifunc_sections (bfd *abfd,
-                                      struct bfd_link_info *info)
+_bfd_elf_create_ifunc_sections (bfd *abfd, struct bfd_link_info *info)
 {
   flagword flags, pltflags;
   int ptralign;
   asection *s;
-  const struct elf_backend_data *bed;
-
-  /* Should never be called for shared library.  */
-  BFD_ASSERT (!info->shared);
-
-  /* This function may be called more than once.  */
-  s = bfd_get_section_by_name (abfd, ".iplt");
-  if (s != NULL)
-    return TRUE;
-
-  bed = get_elf_backend_data (abfd);
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
-  /* We need to create .iplt, .rel[a].iplt, .igot, .igot.plt,  */
   flags = bed->dynamic_sec_flags;
-
   pltflags = flags;
   if (bed->plt_not_loaded)
     /* We do not clear SEC_ALLOC here because we still want the OS to
@@ -12528,47 +12514,68 @@ _bfd_elf_create_static_ifunc_sections (bfd *abfd,
   if (bed->plt_readonly)
     pltflags |= SEC_READONLY;
 
-  s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
-  if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
-    return FALSE;
-
-  s = bfd_make_section_with_flags (abfd,
-                                  (bed->rela_plts_and_copies_p
-                                   ? ".rela.iplt" : ".rel.iplt"),
-                                  flags | SEC_READONLY);
-  if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
-    return FALSE;
-
-  switch (bed->s->arch_size)
+  if (info->shared)
     {
-    case 32:
-      ptralign = 2;
-      break;
+      /* We need to create .rel[a].ifunc for shared objects.  */
+      const char *rel_sec = (bed->rela_plts_and_copies_p
+                            ? ".rela.ifunc" : ".rel.ifunc");
 
-    case 64:
-      ptralign = 3;
-      break;
-
-    default:
-      bfd_set_error (bfd_error_bad_value);
-      return FALSE;
-    }
-
-  /* We don't need the .igot section if we have the .igot.plt
-     section.  */
+      /* This function should be called only once.  */
+      s = bfd_get_section_by_name (abfd, rel_sec);
+      if (s != NULL)
+       abort ();
 
-  if (bed->want_got_plt)
-    {
-      s = bfd_make_section_with_flags (abfd, ".igot.plt", flags);
+      s = bfd_make_section_with_flags (abfd, rel_sec,
+                                      flags | SEC_READONLY);
       if (s == NULL
-         || !bfd_set_section_alignment (abfd, s, ptralign))
+         || ! bfd_set_section_alignment (abfd, s,
+                                         bed->s->log_file_align))
        return FALSE;
     }
   else
     {
-      s = bfd_make_section_with_flags (abfd, ".igot", flags);
+      /* This function should be called only once.  */
+      s = bfd_get_section_by_name (abfd, ".iplt");
+      if (s != NULL)
+       abort ();
+
+      /* We need to create .iplt, .rel[a].iplt, .igot and .igot.plt
+        for static executables.   */
+      s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
+      if (s == NULL
+         || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
+       return FALSE;
+
+      s = bfd_make_section_with_flags (abfd,
+                                      (bed->rela_plts_and_copies_p
+                                       ? ".rela.iplt" : ".rel.iplt"),
+                                      flags | SEC_READONLY);
+      if (s == NULL
+         || ! bfd_set_section_alignment (abfd, s,
+                                         bed->s->log_file_align))
+       return FALSE;
+
+      switch (bed->s->arch_size)
+       { 
+       case 32:
+         ptralign = 2;
+         break;
+
+       case 64:
+         ptralign = 3;
+         break;
+
+       default:
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+
+      /* We don't need the .igot section if we have the .igot.plt
+        section.  */
+      if (bed->want_got_plt)
+       s = bfd_make_section_with_flags (abfd, ".igot.plt", flags);
+      else
+       s = bfd_make_section_with_flags (abfd, ".igot", flags);
       if (s == NULL
          || !bfd_set_section_alignment (abfd, s, ptralign))
        return FALSE;
index cd05d9d..89016cc 100644 (file)
@@ -1,3 +1,7 @@
+2009-06-06  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * scripttempl/elf.sc: Add .rel.ifunc and .rela.ifunc.
+
 2009-06-05  H.J. Lu  <hongjiu.lu@intel.com>
 
        * scripttempl/elf.sc: Remove .rel.ifunc.dyn and .rela.ifunc.dyn.
index 6d7652b..0d6cae9 100644 (file)
@@ -326,6 +326,8 @@ eval $COMBRELOCCAT <<EOF
   .rel.bss      ${RELOCATING-0} : { *(.rel.bss${RELOCATING+ .rel.bss.* .rel.gnu.linkonce.b.*}) }
   .rela.bss     ${RELOCATING-0} : { *(.rela.bss${RELOCATING+ .rela.bss.* .rela.gnu.linkonce.b.*}) }
   ${REL_LARGE}
+  .rel.ifunc      ${RELOCATING-0} : { *(.rel.ifunc) }
+  .rela.ifunc     ${RELOCATING-0} : { *(.rela.ifunc) }
 EOF
 
 if [ -n "$COMBRELOC" ]; then