bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 1 Jun 2009 12:53:00 +0000 (12:53 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 1 Jun 2009 12:53:00 +0000 (12:53 +0000)
2009-06-01  H.J. Lu  <hongjiu.lu@intel.com>

* elf-bfd.h (struct bfd_elf_section_data): Remove indirect_relocs.
(_bfd_elf_make_ifunc_reloc_section): Removed.
(_bfd_elf_is_ifunc_symbol): Likewise.
(_bfd_elf_create_static_ifunc_sections): New.

* elflink.c (_bfd_elf_adjust_dynamic_symbol): Move STT_GNU_IFUNC
symbol check to ...
(elf_link_add_object_symbols): Here.
(_bfd_elf_link_hash_hide_symbol): Don't clean plt on
STT_GNU_IFUNC symbol.
(elf_link_output_extsym): Call elf_backend_finish_dynamic_symbol
if a STT_GNU_IFUNC symbol is referenced in a non-shared object.
(IFUNC_INFIX): Removed.
(get_ifunc_reloc_section_name): Likewise.
(_bfd_elf_make_ifunc_reloc_section): Likewise.
(_bfd_elf_is_ifunc_symbol): Likewise.
(_bfd_elf_create_static_ifunc_sections): New.

ld/

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

* scripttempl/elf.sc (PLT): Add "*(.iplt)".
(GOT): Add "*(.igot.plt)a" and "*(.igot)".
(GOTPLT): Add "*(.igot)".
(__rel_iplt_start): New.
(__rel_iplt_end): Likewise.
(__rela_iplt_start): Likewise.
(__rela_iplt_end): Likewise.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elflink.c
ld/ChangeLog
ld/scripttempl/elf.sc

index 24800c5..615530b 100644 (file)
@@ -1,3 +1,23 @@
+2009-06-01  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * elf-bfd.h (struct bfd_elf_section_data): Remove indirect_relocs.
+       (_bfd_elf_make_ifunc_reloc_section): Removed.
+       (_bfd_elf_is_ifunc_symbol): Likewise.
+       (_bfd_elf_create_static_ifunc_sections): New.
+
+       * elflink.c (_bfd_elf_adjust_dynamic_symbol): Move STT_GNU_IFUNC
+       symbol check to ...
+       (elf_link_add_object_symbols): Here.
+       (_bfd_elf_link_hash_hide_symbol): Don't clean plt on
+       STT_GNU_IFUNC symbol.
+       (elf_link_output_extsym): Call elf_backend_finish_dynamic_symbol
+       if a STT_GNU_IFUNC symbol is referenced in a non-shared object.
+       (IFUNC_INFIX): Removed.
+       (get_ifunc_reloc_section_name): Likewise.
+       (_bfd_elf_make_ifunc_reloc_section): Likewise.
+       (_bfd_elf_is_ifunc_symbol): Likewise.
+       (_bfd_elf_create_static_ifunc_sections): New.
+
 2009-05-29  H.J. Lu  <hongjiu.lu@intel.com>
 
        * elf32-i386.c (link_hash_newfunc): Add elf_i386_ prefix.
index adac206..258d11c 100644 (file)
@@ -1299,9 +1299,6 @@ struct bfd_elf_section_data
   /* A pointer to the bfd section used for dynamic relocs.  */
   asection *sreloc;
 
-  /* A pointer to the bfd section used for dynamic relocs against ifunc symbols.  */
-  asection *indirect_relocs;
-
   union {
     /* Group name, if this section is a member of a group.  */
     const char *name;
@@ -2149,15 +2146,12 @@ 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 asection * _bfd_elf_make_ifunc_reloc_section
-  (bfd *, asection *, bfd *, unsigned int);
+extern bfd_boolean _bfd_elf_create_static_ifunc_sections
+  (bfd *, struct bfd_link_info *);
 
 /* Large common section.  */
 extern asection _bfd_elf_large_com_section;
 
-extern bfd_boolean _bfd_elf_is_ifunc_symbol
-  (bfd *, struct elf_link_hash_entry *);
-
 /* This is the condition under which finish_dynamic_symbol will be called.
    If our finish_dynamic_symbol isn't called, we'll need to do something
    about initializing any .plt and .got entries in relocate_section.  */
index cb5ca09..d182807 100644 (file)
@@ -2675,13 +2675,6 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data)
   dynobj = elf_hash_table (eif->info)->dynobj;
   bed = get_elf_backend_data (dynobj);
 
-
-  if (h->type == STT_GNU_IFUNC
-      && (bed->elf_osabi == ELFOSABI_LINUX
-         /* GNU/Linux is still using the default value 0.  */
-         || bed->elf_osabi == ELFOSABI_NONE))
-    h->needs_plt = 1;
-
   if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
     {
       eif->failed = TRUE;
@@ -4295,6 +4288,10 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              h->type = ELF_ST_TYPE (isym->st_info);
            }
 
+         /* STT_GNU_IFUNC symbol must go through PLT.  */
+         if (h->type == STT_GNU_IFUNC)
+           h->needs_plt = 1;
+
          /* Merge st_other field.  */
          elf_merge_st_other (abfd, h, isym, definition, dynamic);
 
@@ -6669,8 +6666,12 @@ _bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
                                struct elf_link_hash_entry *h,
                                bfd_boolean force_local)
 {
-  h->plt = elf_hash_table (info)->init_plt_offset;
-  h->needs_plt = 0;
+  /* STT_GNU_IFUNC symbol must go through PLT.  */
+  if (h->type != STT_GNU_IFUNC)
+    {
+      h->plt = elf_hash_table (info)->init_plt_offset;
+      h->needs_plt = 0;
+    }
   if (force_local)
     {
       h->forced_local = 1;
@@ -8649,14 +8650,18 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data)
   /* Give the processor backend a chance to tweak the symbol value,
      and also to finish up anything that needs to be done for this
      symbol.  FIXME: Not calling elf_backend_finish_dynamic_symbol for
-     forced local syms when non-shared is due to a historical quirk.  */
-  if ((h->dynindx != -1
-       || h->forced_local)
-      && ((finfo->info->shared
-          && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-              || h->root.type != bfd_link_hash_undefweak))
-         || !h->forced_local)
-      && elf_hash_table (finfo->info)->dynamic_sections_created)
+     forced local syms when non-shared is due to a historical quirk.
+     STT_GNU_IFUNC symbol must go through PLT.  */
+  if ((h->type == STT_GNU_IFUNC
+       && h->ref_regular
+       && !finfo->info->relocatable)
+      || ((h->dynindx != -1
+          || h->forced_local)
+         && ((finfo->info->shared
+              && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+                  || h->root.type != bfd_link_hash_undefweak))
+             || !h->forced_local)
+         && elf_hash_table (finfo->info)->dynamic_sections_created))
     {
       if (! ((*bed->elf_backend_finish_dynamic_symbol)
             (finfo->output_bfd, finfo->info, h, &sym)))
@@ -12487,88 +12492,87 @@ _bfd_elf_make_dynamic_reloc_section (asection *         sec,
   return reloc_sec;
 }
 
-/* Returns the name of the ifunc using dynamic reloc section associated with SEC.  */
-#define IFUNC_INFIX ".ifunc"
+/* Create sections needed by STT_GNU_IFUNC symbol for static
+   executables.  */
 
-static const char *
-get_ifunc_reloc_section_name (bfd *       abfd,
-                             asection *  sec)
+bfd_boolean
+_bfd_elf_create_static_ifunc_sections (bfd *abfd,
+                                      struct bfd_link_info *info)
 {
-  const char *  dot;
-  char *  name;
-  const char *  base_name;
-  unsigned int  strndx = elf_elfheader (abfd)->e_shstrndx;
-  unsigned int  shnam = elf_section_data (sec)->rel_hdr.sh_name;
-
-  base_name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
-  if (base_name == NULL)
-    return NULL;
-
-  dot = strchr (base_name + 1, '.');
-  name = bfd_alloc (abfd, strlen (base_name) + strlen (IFUNC_INFIX) + 1);
-  sprintf (name, "%.*s%s%s", (int)(dot - base_name), base_name, IFUNC_INFIX, dot);
+  flagword flags, pltflags;
+  int ptralign;
+  asection *s;
+  const struct elf_backend_data *bed;
 
-  return name;
-}
+  /* Should never be called for shared library.  */
+  BFD_ASSERT (!info->shared);
 
-/* Like _bfd_elf_make_dynamic_reloc_section but it creates a
-   section for holding relocs against symbols with the STT_GNU_IFUNC
-   type.  The section is attached to the OWNER bfd but it is created
-   with a name based on SEC from ABFD.  */
+  /* This function may be called more than once.  */
+  s = bfd_get_section_by_name (abfd, ".iplt");
+  if (s != NULL)
+    return TRUE;
 
-asection *
-_bfd_elf_make_ifunc_reloc_section (bfd *         abfd,
-                                  asection *    sec,
-                                  bfd *         owner,
-                                  unsigned int  align)
-{
-  asection * reloc_sec = elf_section_data (sec)->indirect_relocs;
+  bed = get_elf_backend_data (abfd);
 
-  if (reloc_sec == NULL)
-    {
-      const char * name = get_ifunc_reloc_section_name (abfd, sec);
+  /* We need to create .iplt, .rel[a].iplt, .igot, .igot.plt,  */
+  flags = bed->dynamic_sec_flags;
 
-      if (name == NULL)
-       return NULL;
+  pltflags = flags;
+  if (bed->plt_not_loaded)
+    /* We do not clear SEC_ALLOC here because we still want the OS to
+       allocate space for the section; it's just that there's nothing
+       to read in from the object file.  */
+    pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
+  else
+    pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
+  if (bed->plt_readonly)
+    pltflags |= SEC_READONLY;
 
-      reloc_sec = bfd_get_section_by_name (owner, name);
+  s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
+  if (s == NULL
+      || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
+    return FALSE;
 
-      if (reloc_sec == NULL)
-       {
-         flagword flags;
+  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;
 
-         flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-         if ((sec->flags & SEC_ALLOC) != 0)
-           flags |= SEC_ALLOC | SEC_LOAD;
+  switch (bed->s->arch_size)
+    {
+    case 32:
+      ptralign = 2;
+      break;
 
-         reloc_sec = bfd_make_section_with_flags (owner, name, flags);
-         
-         if (reloc_sec != NULL
-             && ! bfd_set_section_alignment (owner, reloc_sec, align))
-           reloc_sec = NULL;
-       }
+    case 64:
+      ptralign = 3;
+      break;
 
-      elf_section_data (sec)->indirect_relocs = reloc_sec;
+    default:
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
     }
 
-  return reloc_sec;
-}
-
-/* Returns true if the hash entry refers to a symbol marked for
-   indirect handling during reloc processing.  */
-
-bfd_boolean
-_bfd_elf_is_ifunc_symbol (bfd *abfd, struct elf_link_hash_entry *h)
-{
-  const struct elf_backend_data * bed;
-
-  if (abfd == NULL || h == NULL)
-    return FALSE;
+  /* We don't need the .igot section if we have the .igot.plt
+     section.  */
 
-  bed = get_elf_backend_data (abfd);
+  if (bed->want_got_plt)
+    {
+      s = bfd_make_section_with_flags (abfd, ".igot.plt", flags);
+      if (s == NULL
+         || !bfd_set_section_alignment (abfd, s, ptralign))
+       return FALSE;
+    }
+  else
+    {
+      s = bfd_make_section_with_flags (abfd, ".igot", flags);
+      if (s == NULL
+         || !bfd_set_section_alignment (abfd, s, ptralign))
+       return FALSE;
+    }
 
-  /* GNU/Linux is still using the default value ELFOSABI_NONE.  */
-  return (h->type == STT_GNU_IFUNC
-         && (bed->elf_osabi == ELFOSABI_LINUX
-             || bed->elf_osabi == ELFOSABI_NONE));
+  return TRUE;
 }
index 9c4b545..306ed8f 100644 (file)
@@ -1,3 +1,13 @@
+2009-06-01  H.J. Lu  <hongjiu.lu@intel.com>
+
+       * scripttempl/elf.sc (PLT): Add "*(.iplt)".
+       (GOT): Add "*(.igot.plt)a" and "*(.igot)".
+       (GOTPLT): Add "*(.igot)".
+       (__rel_iplt_start): New.
+       (__rel_iplt_end): Likewise.
+       (__rela_iplt_start): Likewise.
+       (__rela_iplt_end): Likewise.
+
 2009-05-27  Dave Korn  <dave.korn.cygwin@gmail.com>
 
        * deffilep.y (%union):  Add new string-type semantic value 'digits'.
index 123a989..75efa32 100644 (file)
@@ -113,15 +113,15 @@ if test -z "${INITIAL_READONLY_SECTIONS}${CREATE_SHLIB}"; then
   INITIAL_READONLY_SECTIONS=".interp       ${RELOCATING-0} : { *(.interp) }"
 fi
 if test -z "$PLT"; then
-  PLT=".plt          ${RELOCATING-0} : { *(.plt) }"
+  PLT=".plt          ${RELOCATING-0} : { *(.plt) *(.iplt)}"
 fi
 test -n "${DATA_PLT-${BSS_PLT-text}}" && TEXT_PLT=yes
 if test -z "$GOT"; then
   if test -z "$SEPARATE_GOTPLT"; then
-    GOT=".got          ${RELOCATING-0} : { *(.got.plt) *(.got) }"
+    GOT=".got          ${RELOCATING-0} : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }"
   else
-    GOT=".got          ${RELOCATING-0} : { *(.got) }"
-    GOTPLT=".got.plt      ${RELOCATING-0} : { *(.got.plt) }"
+    GOT=".got          ${RELOCATING-0} : { *(.got) *(.igot) }"
+    GOTPLT=".got.plt      ${RELOCATING-0} : { *(.got.plt)  *(.igot.plt) }"
   fi
 fi
 DYNAMIC=".dynamic      ${RELOCATING-0} : { *(.dynamic) }"
@@ -354,8 +354,20 @@ EOF
 fi
 
 cat >> ldscripts/dyntmp.$$ <<EOF
-  .rel.plt      ${RELOCATING-0} : { *(.rel.plt) }
-  .rela.plt     ${RELOCATING-0} : { *(.rela.plt) }
+  .rel.plt      ${RELOCATING-0} :
+    {
+      *(.rel.plt)
+      ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rel_iplt_start = .);}}
+      *(.rel.iplt)
+      ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rel_iplt_end = .);}}
+    }
+  .rela.plt     ${RELOCATING-0} :
+    {
+      *(.rela.plt)
+      ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rela_iplt_start = .);}}
+      *(.rela.iplt)
+      ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rela_iplt_end = .);}}
+    }
   ${OTHER_PLT_RELOC_SECTIONS}
 EOF