969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/bfd/bfd-in2.h ./bfd/bfd-in2.h
969efb6
*** ../delme/binutils-2.19.51.0.2/bfd/bfd-in2.h	2009-02-04 18:21:50.000000000 +0000
969efb6
--- ./bfd/bfd-in2.h	2009-03-05 11:59:49.000000000 +0000
0b82eb1
*************** typedef struct bfd_symbol
0b82eb1
*** 4568,4573 ****
0b82eb1
--- 4568,4579 ----
0b82eb1
    /* This symbol was created by bfd_get_synthetic_symtab.  */
0b82eb1
  #define BSF_SYNTHETIC          (1 << 21)
0b82eb1
  
0b82eb1
+   /* This symbol is an indirect code object.  Unrelated to BSF_INDIRECT.
0b82eb1
+      The dynamic linker will compute the value of this symbol by
0b82eb1
+      calling the function that it points to.  BSF_FUNCTION must
0b82eb1
+      also be also set.  */
0b82eb1
+ #define BSF_GNU_INDIRECT_FUNCTION (1 << 22)
0b82eb1
+ 
0b82eb1
    flagword flags;
0b82eb1
  
0b82eb1
    /* A pointer to the section to which this symbol is
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/bfd/elf32-i386.c ./bfd/elf32-i386.c
969efb6
*** ../delme/binutils-2.19.51.0.2/bfd/elf32-i386.c	2009-02-04 18:21:50.000000000 +0000
969efb6
--- ./bfd/elf32-i386.c	2009-04-08 16:11:48.000000000 +0100
0b82eb1
*************** elf_i386_tls_transition (struct bfd_link
0b82eb1
*** 1206,1211 ****
0b82eb1
--- 1206,1230 ----
0b82eb1
    return TRUE;
0b82eb1
  }
0b82eb1
  
0b82eb1
+ /* Returns true if the hash entry refers to a symbol
0b82eb1
+    marked for indirect handling during reloc processing.  */
0b82eb1
+ 
0b82eb1
+ static bfd_boolean
0b82eb1
+ is_indirect_symbol (bfd * abfd, struct elf_link_hash_entry * h)
0b82eb1
+ {
0b82eb1
+   const struct elf_backend_data * bed;
0b82eb1
+ 
0b82eb1
+   if (abfd == NULL || h == NULL)
0b82eb1
+     return FALSE;
0b82eb1
+ 
0b82eb1
+   bed = get_elf_backend_data (abfd);
0b82eb1
+ 
0b82eb1
+   return h->type == STT_GNU_IFUNC
0b82eb1
+     && (bed->elf_osabi == ELFOSABI_LINUX
0b82eb1
+ 	/* GNU/Linux is still using the default value 0.  */
0b82eb1
+ 	|| bed->elf_osabi == ELFOSABI_NONE);
0b82eb1
+ }
0b82eb1
+ 
0b82eb1
  /* Look through the relocs for a section during the first phase, and
0b82eb1
     calculate needed space in the global offset table, procedure linkage
0b82eb1
     table, and dynamic reloc sections.  */
0b82eb1
*************** elf_i386_check_relocs (bfd *abfd,
0b82eb1
*** 1483,1488 ****
969efb6
--- 1502,1513 ----
0b82eb1
  
0b82eb1
  		  if (sreloc == NULL)
0b82eb1
  		    return FALSE;
0b82eb1
+ 
0b82eb1
+ 		  /* Create the ifunc section as well, even if we have not encountered a
0b82eb1
+ 		     indirect function symbol yet.  We may not even see one in the input
0b82eb1
+ 		     object file, but we can still encounter them in libraries.  */
0b82eb1
+ 		  (void) _bfd_elf_make_ifunc_reloc_section
0b82eb1
+ 		    (abfd, sec, htab->elf.dynobj, 2);
0b82eb1
  		}
0b82eb1
  
0b82eb1
  	      /* If this is a global symbol, we count the number of
0b82eb1
*************** allocate_dynrelocs (struct elf_link_hash
969efb6
*** 1831,1836 ****
969efb6
--- 1856,1862 ----
969efb6
    struct elf_i386_link_hash_table *htab;
969efb6
    struct elf_i386_link_hash_entry *eh;
969efb6
    struct elf_i386_dyn_relocs *p;
969efb6
+   bfd_boolean use_indirect_section = FALSE;
969efb6
  
969efb6
    if (h->root.type == bfd_link_hash_indirect)
969efb6
      return TRUE;
969efb6
*************** allocate_dynrelocs (struct elf_link_hash
0b82eb1
*** 2052,2057 ****
969efb6
--- 2078,2093 ----
0b82eb1
  	    }
0b82eb1
  	}
0b82eb1
      }
969efb6
+   else if (is_indirect_symbol (info->output_bfd, h)
969efb6
+ 	   && h->dynindx == -1
969efb6
+ 	   && ! h->forced_local)
0b82eb1
+     {
969efb6
+       if (bfd_elf_link_record_dynamic_symbol (info, h)
969efb6
+ 	  && h->dynindx != -1)
969efb6
+ 	use_indirect_section = TRUE;
969efb6
+       else
969efb6
+ 	return FALSE;
0b82eb1
+     }
0b82eb1
    else if (ELIMINATE_COPY_RELOCS)
0b82eb1
      {
0b82eb1
        /* For the non-shared case, discard space for relocs against
0b82eb1
*************** allocate_dynrelocs (struct elf_link_hash
0b82eb1
*** 2090,2096 ****
0b82eb1
      {
0b82eb1
        asection *sreloc;
0b82eb1
  
0b82eb1
!       sreloc = elf_section_data (p->sec)->sreloc;
0b82eb1
  
0b82eb1
        BFD_ASSERT (sreloc != NULL);
0b82eb1
        sreloc->size += p->count * sizeof (Elf32_External_Rel);
969efb6
--- 2126,2135 ----
0b82eb1
      {
0b82eb1
        asection *sreloc;
0b82eb1
  
969efb6
!       if (use_indirect_section)
969efb6
! 	sreloc = elf_section_data (p->sec)->indirect_relocs;
0b82eb1
!       else
0b82eb1
!  	sreloc = elf_section_data (p->sec)->sreloc;
0b82eb1
  
0b82eb1
        BFD_ASSERT (sreloc != NULL);
0b82eb1
        sreloc->size += p->count * sizeof (Elf32_External_Rel);
0b82eb1
*************** elf_i386_relocate_section (bfd *output_b
969efb6
*** 2894,2899 ****
969efb6
--- 2933,2944 ----
969efb6
  		   || h->root.type != bfd_link_hash_undefweak)
969efb6
  	       && (r_type != R_386_PC32
969efb6
  		   || !SYMBOL_CALLS_LOCAL (info, h)))
969efb6
+ 	      || (! info->shared
969efb6
+ 		  && h != NULL
969efb6
+ 		  && h->dynindx != -1
969efb6
+ 		  && ! h->forced_local
969efb6
+ 		  && ((struct elf_i386_link_hash_entry *) h)->dyn_relocs != NULL
969efb6
+ 		  && is_indirect_symbol (output_bfd, h))
969efb6
  	      || (ELIMINATE_COPY_RELOCS
969efb6
  		  && !info->shared
969efb6
  		  && h != NULL
0b82eb1
*************** elf_i386_relocate_section (bfd *output_b
0b82eb1
*** 2942,2948 ****
0b82eb1
  		  outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
0b82eb1
  		}
0b82eb1
  
0b82eb1
! 	      sreloc = elf_section_data (input_section)->sreloc;
0b82eb1
  
0b82eb1
  	      BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
0b82eb1
  
969efb6
--- 2987,3002 ----
0b82eb1
  		  outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
0b82eb1
  		}
0b82eb1
  
969efb6
! 	      if (! info->shared
969efb6
! 		  && h != NULL
969efb6
! 		  && h->dynindx != -1
969efb6
! 		  && ! h->forced_local
969efb6
! 		  && is_indirect_symbol (output_bfd, h)
969efb6
! 		  && elf_section_data (input_section)->indirect_relocs != NULL
969efb6
! 		  && elf_section_data (input_section)->indirect_relocs->contents != NULL)
969efb6
! 		sreloc = elf_section_data (input_section)->indirect_relocs;
969efb6
! 	      else
0b82eb1
!  		sreloc = elf_section_data (input_section)->sreloc;
0b82eb1
  
0b82eb1
  	      BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
0b82eb1
  
969efb6
*************** elf_i386_hash_symbol (struct elf_link_ha
969efb6
*** 4068,4073 ****
969efb6
--- 4122,4146 ----
969efb6
    return _bfd_elf_hash_symbol (h);
969efb6
  }
969efb6
  
969efb6
+ /* Hook called by the linker routine which adds symbols from an object
969efb6
+    file.  */
969efb6
+ 
969efb6
+ static bfd_boolean
969efb6
+ elf_i386_add_symbol_hook (bfd *abfd,
969efb6
+ 			  struct bfd_link_info *info,
969efb6
+ 			  Elf_Internal_Sym *sym,
969efb6
+ 			  const char **namep,
969efb6
+ 			  flagword *flagsp,
969efb6
+ 			  asection **secp,
969efb6
+ 			  bfd_vma *valp)
969efb6
+ {
969efb6
+   if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
969efb6
+     elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
969efb6
+ 
969efb6
+   return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
969efb6
+ 				       secp, valp);
969efb6
+ }
969efb6
+ 
969efb6
  #define TARGET_LITTLE_SYM		bfd_elf32_i386_vec
969efb6
  #define TARGET_LITTLE_NAME		"elf32-i386"
969efb6
  #define ELF_ARCH			bfd_arch_i386
969efb6
*************** elf_i386_hash_symbol (struct elf_link_ha
969efb6
*** 4113,4121 ****
969efb6
  #define elf_backend_plt_sym_val		      elf_i386_plt_sym_val
969efb6
  #define elf_backend_hash_symbol		      elf_i386_hash_symbol
969efb6
  
969efb6
! #define elf_backend_add_symbol_hook \
969efb6
!   _bfd_elf_add_sharable_symbol
969efb6
! #define elf_backend_section_from_bfd_section \
969efb6
    _bfd_elf_sharable_section_from_bfd_section
969efb6
  #define elf_backend_symbol_processing \
969efb6
    _bfd_elf_sharable_symbol_processing
969efb6
--- 4186,4194 ----
969efb6
  #define elf_backend_plt_sym_val		      elf_i386_plt_sym_val
969efb6
  #define elf_backend_hash_symbol		      elf_i386_hash_symbol
969efb6
  
969efb6
! #define elf_backend_add_symbol_hook           elf_i386_add_symbol_hook
969efb6
! 
969efb6
! #define elf_backend_section_from_bfd_section	\
969efb6
    _bfd_elf_sharable_section_from_bfd_section
969efb6
  #define elf_backend_symbol_processing \
969efb6
    _bfd_elf_sharable_symbol_processing
0b82eb1
*************** elf_i386_hash_symbol (struct elf_link_ha
0b82eb1
*** 4128,4133 ****
969efb6
--- 4201,4209 ----
0b82eb1
  #define elf_backend_merge_symbol \
0b82eb1
    _bfd_elf_sharable_merge_symbol
0b82eb1
  
0b82eb1
+ #undef	elf_backend_post_process_headers
0b82eb1
+ #define	elf_backend_post_process_headers	_bfd_elf_set_osabi
0b82eb1
+ 
0b82eb1
  #include "elf32-target.h"
0b82eb1
  
0b82eb1
  /* FreeBSD support.  */
0b82eb1
*************** elf_i386_hash_symbol (struct elf_link_ha
0b82eb1
*** 4144,4158 ****
0b82eb1
     executables and (for simplicity) also all other object files.  */
0b82eb1
  
0b82eb1
  static void
0b82eb1
! elf_i386_post_process_headers (bfd *abfd,
0b82eb1
! 			       struct bfd_link_info *info ATTRIBUTE_UNUSED)
0b82eb1
  {
0b82eb1
!   Elf_Internal_Ehdr *i_ehdrp;
0b82eb1
! 
0b82eb1
!   i_ehdrp = elf_elfheader (abfd);
0b82eb1
  
0b82eb1
-   /* Put an ABI label supported by FreeBSD >= 4.1.  */
0b82eb1
-   i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
0b82eb1
  #ifdef OLD_FREEBSD_ABI_LABEL
0b82eb1
    /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard.  */
0b82eb1
    memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
969efb6
--- 4220,4229 ----
0b82eb1
     executables and (for simplicity) also all other object files.  */
0b82eb1
  
0b82eb1
  static void
0b82eb1
! elf_i386_post_process_headers (bfd *abfd, struct bfd_link_info *info)
0b82eb1
  {
0b82eb1
!   _bfd_elf_set_osabi (abfd, info);
0b82eb1
  
0b82eb1
  #ifdef OLD_FREEBSD_ABI_LABEL
0b82eb1
    /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard.  */
0b82eb1
    memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/bfd/elf64-x86-64.c ./bfd/elf64-x86-64.c
969efb6
*** ../delme/binutils-2.19.51.0.2/bfd/elf64-x86-64.c	2009-02-04 18:21:50.000000000 +0000
969efb6
--- ./bfd/elf64-x86-64.c	2009-04-08 16:07:11.000000000 +0100
969efb6
*************** static reloc_howto_type x86_64_elf_howto
969efb6
*** 161,166 ****
969efb6
--- 161,172 ----
969efb6
  	 FALSE)
969efb6
  };
969efb6
  
969efb6
+ #define IS_X86_64_PCREL_TYPE(TYPE)	\
969efb6
+   (   ((TYPE) == R_X86_64_PC8)		\
969efb6
+    || ((TYPE) == R_X86_64_PC16)		\
969efb6
+    || ((TYPE) == R_X86_64_PC32)		\
969efb6
+    || ((TYPE) == R_X86_64_PC64))
969efb6
+ 
969efb6
  /* Map BFD relocs to the x86_64 elf relocs.  */
969efb6
  struct elf_reloc_map
969efb6
  {
0b82eb1
*************** elf64_x86_64_tls_transition (struct bfd_
0b82eb1
*** 987,992 ****
969efb6
--- 993,1017 ----
0b82eb1
    return TRUE;
0b82eb1
  }
0b82eb1
  
0b82eb1
+ /* Returns true if the hash entry refers to a symbol
0b82eb1
+    marked for indirect handling during reloc processing.  */
0b82eb1
+ 
0b82eb1
+ static bfd_boolean
0b82eb1
+ is_indirect_symbol (bfd * abfd, struct elf_link_hash_entry * h)
0b82eb1
+ {
0b82eb1
+   const struct elf_backend_data * bed;
0b82eb1
+ 
0b82eb1
+   if (abfd == NULL || h == NULL)
0b82eb1
+     return FALSE;
0b82eb1
+ 
0b82eb1
+   bed = get_elf_backend_data (abfd);
0b82eb1
+ 
0b82eb1
+   return h->type == STT_GNU_IFUNC
0b82eb1
+     && (bed->elf_osabi == ELFOSABI_LINUX
0b82eb1
+ 	/* GNU/Linux is still using the default value 0.  */
0b82eb1
+ 	|| bed->elf_osabi == ELFOSABI_NONE);
0b82eb1
+ }
0b82eb1
+ 
0b82eb1
  /* Look through the relocs for a section during the first phase, and
0b82eb1
     calculate needed space in the global offset table, procedure
0b82eb1
     linkage table, and dynamic reloc sections.  */
0b82eb1
*************** elf64_x86_64_check_relocs (bfd *abfd, st
969efb6
*** 1013,1019 ****
969efb6
    sym_hashes = elf_sym_hashes (abfd);
969efb6
  
969efb6
    sreloc = NULL;
969efb6
! 
969efb6
    rel_end = relocs + sec->reloc_count;
969efb6
    for (rel = relocs; rel < rel_end; rel++)
969efb6
      {
969efb6
--- 1038,1044 ----
969efb6
    sym_hashes = elf_sym_hashes (abfd);
969efb6
  
969efb6
    sreloc = NULL;
969efb6
!   
969efb6
    rel_end = relocs + sec->reloc_count;
969efb6
    for (rel = relocs; rel < rel_end; rel++)
969efb6
      {
969efb6
*************** elf64_x86_64_check_relocs (bfd *abfd, st
969efb6
*** 1269,1281 ****
0b82eb1
  	     may need to keep relocations for symbols satisfied by a
0b82eb1
  	     dynamic library if we manage to avoid copy relocs for the
969efb6
  	     symbol.  */
969efb6
- 
0b82eb1
  	  if ((info->shared
0b82eb1
  	       && (sec->flags & SEC_ALLOC) != 0
969efb6
! 	       && (((r_type != R_X86_64_PC8)
969efb6
! 		    && (r_type != R_X86_64_PC16)
969efb6
! 		    && (r_type != R_X86_64_PC32)
969efb6
! 		    && (r_type != R_X86_64_PC64))
969efb6
  		   || (h != NULL
969efb6
  		       && (! SYMBOLIC_BIND (info, h)
969efb6
  			   || h->root.type == bfd_link_hash_defweak
969efb6
--- 1294,1302 ----
0b82eb1
  	     may need to keep relocations for symbols satisfied by a
0b82eb1
  	     dynamic library if we manage to avoid copy relocs for the
969efb6
  	     symbol.  */
0b82eb1
  	  if ((info->shared
0b82eb1
  	       && (sec->flags & SEC_ALLOC) != 0
969efb6
! 	       && (! IS_X86_64_PCREL_TYPE (r_type)
969efb6
  		   || (h != NULL
969efb6
  		       && (! SYMBOLIC_BIND (info, h)
969efb6
  			   || h->root.type == bfd_link_hash_defweak
0b82eb1
*************** elf64_x86_64_check_relocs (bfd *abfd, st
0b82eb1
*** 1303,1308 ****
969efb6
--- 1324,1335 ----
0b82eb1
  
0b82eb1
  		  if (sreloc == NULL)
0b82eb1
  		    return FALSE;
0b82eb1
+ 
969efb6
+ 		  /* Create the ifunc section, even if we will not encounter an
969efb6
+ 		     indirect function symbol.  We may not even see one in the input
0b82eb1
+ 		     object file, but we can still encounter them in libraries.  */
0b82eb1
+ 		  (void) _bfd_elf_make_ifunc_reloc_section
0b82eb1
+ 		    (abfd, sec, htab->elf.dynobj, 2);
0b82eb1
  		}
0b82eb1
  
0b82eb1
  	      /* If this is a global symbol, we count the number of
0b82eb1
*************** elf64_x86_64_check_relocs (bfd *abfd, st
0b82eb1
*** 1334,1339 ****
969efb6
--- 1361,1367 ----
0b82eb1
  	      if (p == NULL || p->sec != sec)
0b82eb1
  		{
0b82eb1
  		  bfd_size_type amt = sizeof *p;
0b82eb1
+ 
0b82eb1
  		  p = ((struct elf64_x86_64_dyn_relocs *)
0b82eb1
  		       bfd_alloc (htab->elf.dynobj, amt));
0b82eb1
  		  if (p == NULL)
969efb6
*************** elf64_x86_64_check_relocs (bfd *abfd, st
969efb6
*** 1346,1355 ****
969efb6
  		}
969efb6
  
969efb6
  	      p->count += 1;
969efb6
! 	      if (r_type == R_X86_64_PC8
969efb6
! 		  || r_type == R_X86_64_PC16
969efb6
! 		  || r_type == R_X86_64_PC32
969efb6
! 		  || r_type == R_X86_64_PC64)
969efb6
  		p->pc_count += 1;
969efb6
  	    }
969efb6
  	  break;
969efb6
--- 1374,1380 ----
969efb6
  		}
969efb6
  
969efb6
  	      p->count += 1;
969efb6
! 	      if (IS_X86_64_PCREL_TYPE (r_type))
969efb6
  		p->pc_count += 1;
969efb6
  	    }
969efb6
  	  break;
969efb6
*************** allocate_dynrelocs (struct elf_link_hash
969efb6
*** 1666,1671 ****
969efb6
--- 1691,1697 ----
969efb6
    struct elf64_x86_64_link_hash_table *htab;
969efb6
    struct elf64_x86_64_link_hash_entry *eh;
969efb6
    struct elf64_x86_64_dyn_relocs *p;
969efb6
+   bfd_boolean use_indirect_section = FALSE;
969efb6
  
969efb6
    if (h->root.type == bfd_link_hash_indirect)
969efb6
      return TRUE;
0b82eb1
*************** allocate_dynrelocs (struct elf_link_hash
0b82eb1
*** 1744,1750 ****
0b82eb1
        && !info->shared
0b82eb1
        && h->dynindx == -1
0b82eb1
        && elf64_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE)
0b82eb1
!     h->got.offset = (bfd_vma) -1;
0b82eb1
    else if (h->got.refcount > 0)
0b82eb1
      {
0b82eb1
        asection *s;
969efb6
--- 1770,1778 ----
0b82eb1
        && !info->shared
0b82eb1
        && h->dynindx == -1
0b82eb1
        && elf64_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE)
0b82eb1
!     {
0b82eb1
!       h->got.offset = (bfd_vma) -1;
0b82eb1
!     }
0b82eb1
    else if (h->got.refcount > 0)
0b82eb1
      {
0b82eb1
        asection *s;
0b82eb1
*************** allocate_dynrelocs (struct elf_link_hash
0b82eb1
*** 1843,1855 ****
0b82eb1
  	  /* Make sure undefined weak symbols are output as a dynamic
0b82eb1
  	     symbol in PIEs.  */
0b82eb1
  	  else if (h->dynindx == -1
0b82eb1
! 		   && !h->forced_local)
0b82eb1
! 	    {
0b82eb1
! 	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
0b82eb1
! 		return FALSE;
0b82eb1
! 	    }
0b82eb1
  	}
0b82eb1
      }
0b82eb1
    else if (ELIMINATE_COPY_RELOCS)
0b82eb1
      {
0b82eb1
        /* For the non-shared case, discard space for relocs against
969efb6
--- 1871,1891 ----
0b82eb1
  	  /* Make sure undefined weak symbols are output as a dynamic
0b82eb1
  	     symbol in PIEs.  */
0b82eb1
  	  else if (h->dynindx == -1
0b82eb1
! 		   && ! h->forced_local
0b82eb1
! 		   && ! bfd_elf_link_record_dynamic_symbol (info, h))
0b82eb1
! 	    return FALSE;
0b82eb1
  	}
0b82eb1
      }
969efb6
+   else if (is_indirect_symbol (info->output_bfd, h)
969efb6
+ 	   && h->dynindx == -1
969efb6
+ 	   && ! h->forced_local)
0b82eb1
+     {
969efb6
+       if (bfd_elf_link_record_dynamic_symbol (info, h)
969efb6
+ 	  && h->dynindx != -1)
969efb6
+ 	use_indirect_section = TRUE;
969efb6
+       else
969efb6
+ 	return FALSE;
0b82eb1
+     }
0b82eb1
    else if (ELIMINATE_COPY_RELOCS)
0b82eb1
      {
0b82eb1
        /* For the non-shared case, discard space for relocs against
0b82eb1
*************** allocate_dynrelocs (struct elf_link_hash
0b82eb1
*** 1866,1876 ****
0b82eb1
  	  /* Make sure this symbol is output as a dynamic symbol.
0b82eb1
  	     Undefined weak syms won't yet be marked as dynamic.  */
0b82eb1
  	  if (h->dynindx == -1
0b82eb1
! 	      && !h->forced_local)
0b82eb1
! 	    {
0b82eb1
! 	      if (! bfd_elf_link_record_dynamic_symbol (info, h))
0b82eb1
! 		return FALSE;
0b82eb1
! 	    }
0b82eb1
  
0b82eb1
  	  /* If that succeeded, we know we'll be keeping all the
0b82eb1
  	     relocs.  */
969efb6
--- 1902,1910 ----
0b82eb1
  	  /* Make sure this symbol is output as a dynamic symbol.
0b82eb1
  	     Undefined weak syms won't yet be marked as dynamic.  */
0b82eb1
  	  if (h->dynindx == -1
0b82eb1
! 	      && ! h->forced_local
0b82eb1
! 	      && ! bfd_elf_link_record_dynamic_symbol (info, h))
0b82eb1
! 	    return FALSE;
0b82eb1
  
0b82eb1
  	  /* If that succeeded, we know we'll be keeping all the
0b82eb1
  	     relocs.  */
0b82eb1
*************** allocate_dynrelocs (struct elf_link_hash
0b82eb1
*** 1888,1894 ****
0b82eb1
      {
0b82eb1
        asection * sreloc;
0b82eb1
  
0b82eb1
!       sreloc = elf_section_data (p->sec)->sreloc;
0b82eb1
  
0b82eb1
        BFD_ASSERT (sreloc != NULL);
0b82eb1
  
969efb6
--- 1922,1931 ----
0b82eb1
      {
0b82eb1
        asection * sreloc;
0b82eb1
  
969efb6
!       if (use_indirect_section)
969efb6
! 	sreloc = elf_section_data (p->sec)->indirect_relocs;
0b82eb1
!       else
0b82eb1
! 	sreloc = elf_section_data (p->sec)->sreloc;
0b82eb1
  
0b82eb1
        BFD_ASSERT (sreloc != NULL);
0b82eb1
  
0b82eb1
*************** elf64_x86_64_relocate_section (bfd *outp
969efb6
*** 2691,2701 ****
969efb6
  	       && (h == NULL
969efb6
  		   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
969efb6
  		   || h->root.type != bfd_link_hash_undefweak)
969efb6
! 	       && ((r_type != R_X86_64_PC8
969efb6
! 		    && r_type != R_X86_64_PC16
969efb6
! 		    && r_type != R_X86_64_PC32
969efb6
! 		    && r_type != R_X86_64_PC64)
969efb6
! 		   || !SYMBOL_CALLS_LOCAL (info, h)))
969efb6
  	      || (ELIMINATE_COPY_RELOCS
969efb6
  		  && !info->shared
969efb6
  		  && h != NULL
969efb6
--- 2728,2741 ----
969efb6
  	       && (h == NULL
969efb6
  		   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
969efb6
  		   || h->root.type != bfd_link_hash_undefweak)
969efb6
! 	       && (! IS_X86_64_PCREL_TYPE (r_type)
969efb6
! 		   || ! SYMBOL_CALLS_LOCAL (info, h)))
969efb6
! 	      || (! info->shared
969efb6
! 		  && h != NULL
969efb6
! 		  && h->dynindx != -1
969efb6
! 		  && ! h->forced_local
969efb6
! 		  && ((struct elf64_x86_64_link_hash_entry *) h)->dyn_relocs != NULL
969efb6
! 		  && is_indirect_symbol (output_bfd, h))
969efb6
  	      || (ELIMINATE_COPY_RELOCS
969efb6
  		  && !info->shared
969efb6
  		  && h != NULL
969efb6
*************** elf64_x86_64_relocate_section (bfd *outp
969efb6
*** 2735,2747 ****
969efb6
  		 become local.  */
969efb6
  	      else if (h != NULL
969efb6
  		       && h->dynindx != -1
969efb6
! 		       && (r_type == R_X86_64_PC8
969efb6
! 			   || r_type == R_X86_64_PC16
969efb6
! 			   || r_type == R_X86_64_PC32
969efb6
! 			   || r_type == R_X86_64_PC64
969efb6
! 			   || !info->shared
969efb6
! 			   || !SYMBOLIC_BIND (info, h)
969efb6
! 			   || !h->def_regular))
969efb6
  		{
969efb6
  		  outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
969efb6
  		  outrel.r_addend = rel->r_addend;
969efb6
--- 2775,2784 ----
969efb6
  		 become local.  */
969efb6
  	      else if (h != NULL
969efb6
  		       && h->dynindx != -1
969efb6
! 		       && (IS_X86_64_PCREL_TYPE (r_type)
969efb6
! 			   || ! info->shared
969efb6
! 			   || ! SYMBOLIC_BIND (info, h)
969efb6
! 			   || ! h->def_regular))
969efb6
  		{
969efb6
  		  outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
969efb6
  		  outrel.r_addend = rel->r_addend;
0b82eb1
*************** elf64_x86_64_relocate_section (bfd *outp
0b82eb1
*** 2790,2796 ****
0b82eb1
  		    }
0b82eb1
  		}
0b82eb1
  
0b82eb1
! 	      sreloc = elf_section_data (input_section)->sreloc;
0b82eb1
  		
0b82eb1
  	      BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
0b82eb1
  
969efb6
--- 2827,2842 ----
0b82eb1
  		    }
0b82eb1
  		}
0b82eb1
  
969efb6
! 	      if (! info->shared
969efb6
! 		  && h != NULL
969efb6
! 		  && h->dynindx != -1
969efb6
! 		  && ! h->forced_local
969efb6
! 		  && is_indirect_symbol (output_bfd, h)
969efb6
! 		  && elf_section_data (input_section)->indirect_relocs != NULL
969efb6
! 		  && elf_section_data (input_section)->indirect_relocs->contents != NULL)
0b82eb1
! 		sreloc = elf_section_data (input_section)->indirect_relocs;
0b82eb1
! 	      else
0b82eb1
! 		sreloc = elf_section_data (input_section)->sreloc;
0b82eb1
  		
0b82eb1
  	      BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
0b82eb1
  
969efb6
*************** elf64_x86_64_add_symbol_hook (bfd *abfd,
969efb6
*** 3712,3717 ****
969efb6
--- 3758,3766 ----
969efb6
        break;
969efb6
      }
0b82eb1
  
969efb6
+   if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
969efb6
+     elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
969efb6
+ 
969efb6
    return _bfd_elf_add_sharable_symbol (abfd, info, sym, namep, flagsp,
969efb6
  				       secp, valp);
969efb6
  }
0b82eb1
*************** static const struct bfd_elf_special_sect
0b82eb1
*** 3958,3963 ****
969efb6
--- 4007,4015 ----
0b82eb1
  #define elf_backend_hash_symbol \
0b82eb1
    elf64_x86_64_hash_symbol
0b82eb1
  
0b82eb1
+ #undef  elf_backend_post_process_headers
0b82eb1
+ #define elf_backend_post_process_headers  _bfd_elf_set_osabi
0b82eb1
+ 
0b82eb1
  #include "elf64-target.h"
0b82eb1
  
0b82eb1
  /* FreeBSD support.  */
0b82eb1
*************** static const struct bfd_elf_special_sect
0b82eb1
*** 3970,3978 ****
0b82eb1
  #undef	ELF_OSABI
0b82eb1
  #define	ELF_OSABI			    ELFOSABI_FREEBSD
0b82eb1
  
0b82eb1
- #undef  elf_backend_post_process_headers
0b82eb1
- #define elf_backend_post_process_headers  _bfd_elf_set_osabi
0b82eb1
- 
0b82eb1
  #undef  elf64_bed
0b82eb1
  #define elf64_bed elf64_x86_64_fbsd_bed
0b82eb1
  
969efb6
--- 4022,4027 ----
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/bfd/elf-bfd.h ./bfd/elf-bfd.h
969efb6
*** ../delme/binutils-2.19.51.0.2/bfd/elf-bfd.h	2009-02-04 18:21:50.000000000 +0000
969efb6
--- ./bfd/elf-bfd.h	2009-03-13 16:48:34.000000000 +0000
0b82eb1
*************** struct bfd_elf_section_data
0b82eb1
*** 1294,1299 ****
0b82eb1
--- 1294,1302 ----
0b82eb1
    /* A pointer to the bfd section used for dynamic relocs.  */
0b82eb1
    asection *sreloc;
0b82eb1
  
0b82eb1
+   /* A pointer to the bfd section used for dynamic relocs against ifunc symbols.  */
0b82eb1
+   asection *indirect_relocs;
0b82eb1
+ 
0b82eb1
    union {
0b82eb1
      /* Group name, if this section is a member of a group.  */
0b82eb1
      const char *name;
0b82eb1
*************** struct elf_obj_tdata
0b82eb1
*** 1556,1561 ****
0b82eb1
--- 1559,1569 ----
0b82eb1
    bfd_size_type build_id_size;
0b82eb1
    bfd_byte *build_id;
0b82eb1
  
969efb6
+   /* True if the bfd contains symbols that have the STT_GNU_IFUNC
969efb6
+      symbol type.  Used to set the osabi field in the ELF header
969efb6
+      structure.  */
969efb6
+   bfd_boolean has_ifunc_symbols;
0b82eb1
+ 
0b82eb1
    /* An identifier used to distinguish different target
0b82eb1
       specific extensions to this structure.  */
0b82eb1
    enum elf_object_id object_id;
0b82eb1
*************** extern int _bfd_elf_obj_attrs_arg_type (
0b82eb1
*** 2158,2163 ****
0b82eb1
--- 2166,2174 ----
0b82eb1
  extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *);
0b82eb1
  extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *);
0b82eb1
  
0b82eb1
+ extern asection * _bfd_elf_make_ifunc_reloc_section
0b82eb1
+   (bfd *, asection *, bfd *, unsigned int);
0b82eb1
+ 
0b82eb1
  /* Large common section.  */
0b82eb1
  extern asection _bfd_elf_large_com_section;
0b82eb1
  
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/bfd/elf.c ./bfd/elf.c
969efb6
*** ../delme/binutils-2.19.51.0.2/bfd/elf.c	2009-02-04 18:21:50.000000000 +0000
969efb6
--- ./bfd/elf.c	2009-03-13 16:49:37.000000000 +0000
0b82eb1
*************** Unable to find equivalent output section
0b82eb1
*** 6508,6513 ****
0b82eb1
--- 6508,6515 ----
0b82eb1
  
0b82eb1
        if ((flags & BSF_THREAD_LOCAL) != 0)
0b82eb1
  	type = STT_TLS;
0b82eb1
+       else if ((flags & BSF_GNU_INDIRECT_FUNCTION) != 0)
0b82eb1
+ 	type = STT_GNU_IFUNC;
0b82eb1
        else if ((flags & BSF_FUNCTION) != 0)
0b82eb1
  	type = STT_FUNC;
0b82eb1
        else if ((flags & BSF_OBJECT) != 0)
0b82eb1
*************** _bfd_elf_set_osabi (bfd * abfd,
0b82eb1
*** 9014,9028 ****
0b82eb1
    i_ehdrp = elf_elfheader (abfd);
0b82eb1
  
0b82eb1
    i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
0b82eb1
  }
0b82eb1
  
0b82eb1
  
0b82eb1
  /* Return TRUE for ELF symbol types that represent functions.
0b82eb1
     This is the default version of this function, which is sufficient for
0b82eb1
!    most targets.  It returns true if TYPE is STT_FUNC.  */
0b82eb1
  
0b82eb1
  bfd_boolean
0b82eb1
  _bfd_elf_is_function_type (unsigned int type)
0b82eb1
  {
0b82eb1
!   return (type == STT_FUNC);
0b82eb1
  }
0b82eb1
--- 9016,9038 ----
0b82eb1
    i_ehdrp = elf_elfheader (abfd);
0b82eb1
  
0b82eb1
    i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
0b82eb1
+ 
0b82eb1
+   /* To make things simpler for the loader on Linux systems we set the
969efb6
+      osabi field to ELFOSABI_LINUX if the binary contains symbols of
969efb6
+      the STT_GNU_IFUNC type.  */
0b82eb1
+   if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
969efb6
+       && elf_tdata (abfd)->has_ifunc_symbols)
0b82eb1
+     i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
0b82eb1
  }
0b82eb1
  
0b82eb1
  
0b82eb1
  /* Return TRUE for ELF symbol types that represent functions.
0b82eb1
     This is the default version of this function, which is sufficient for
0b82eb1
!    most targets.  It returns true if TYPE is STT_FUNC or STT_GNU_IFUNC.  */
0b82eb1
  
0b82eb1
  bfd_boolean
0b82eb1
  _bfd_elf_is_function_type (unsigned int type)
0b82eb1
  {
0b82eb1
!   return (type == STT_FUNC
0b82eb1
! 	  || type == STT_GNU_IFUNC);
0b82eb1
  }
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/bfd/elfcode.h ./bfd/elfcode.h
969efb6
*** ../delme/binutils-2.19.51.0.2/bfd/elfcode.h	2009-04-08 16:23:16.000000000 +0100
969efb6
--- ./bfd/elfcode.h	2009-03-05 11:54:03.000000000 +0000
0b82eb1
*************** elf_slurp_symbol_table (bfd *abfd, asymb
0b82eb1
*** 1371,1376 ****
0b82eb1
--- 1371,1379 ----
0b82eb1
  	    case STT_SRELC:
0b82eb1
  	      sym->symbol.flags |= BSF_SRELC;
0b82eb1
  	      break;
0b82eb1
+ 	    case STT_GNU_IFUNC:
0b82eb1
+ 	      sym->symbol.flags |= BSF_GNU_INDIRECT_FUNCTION;
0b82eb1
+ 	      break;
0b82eb1
  	    }
0b82eb1
  
0b82eb1
  	  if (dynamic)
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/bfd/elflink.c ./bfd/elflink.c
969efb6
*** ../delme/binutils-2.19.51.0.2/bfd/elflink.c	2009-02-04 18:21:50.000000000 +0000
969efb6
--- ./bfd/elflink.c	2009-03-05 11:54:03.000000000 +0000
0b82eb1
*************** _bfd_elf_adjust_dynamic_symbol (struct e
0b82eb1
*** 2776,2781 ****
0b82eb1
--- 2776,2788 ----
0b82eb1
    dynobj = elf_hash_table (eif->info)->dynobj;
0b82eb1
    bed = get_elf_backend_data (dynobj);
0b82eb1
  
0b82eb1
+ 
0b82eb1
+   if (h->type == STT_GNU_IFUNC
0b82eb1
+       && (bed->elf_osabi == ELFOSABI_LINUX
0b82eb1
+ 	  /* GNU/Linux is still using the default value 0.  */
0b82eb1
+ 	  || bed->elf_osabi == ELFOSABI_NONE))
0b82eb1
+     h->needs_plt = 1;
0b82eb1
+ 
0b82eb1
    if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
0b82eb1
      {
0b82eb1
        eif->failed = TRUE;
0b82eb1
*************** _bfd_elf_sharable_merge_symbol
0b82eb1
*** 12806,12808 ****
0b82eb1
--- 12813,12882 ----
0b82eb1
  
0b82eb1
    return TRUE;
0b82eb1
  }
0b82eb1
+ 
0b82eb1
+ /* Returns the name of the ifunc using dynamic reloc section associated with SEC.  */
0b82eb1
+ #define IFUNC_INFIX ".ifunc"
0b82eb1
+ 
0b82eb1
+ static const char *
0b82eb1
+ get_ifunc_reloc_section_name (bfd *       abfd,
0b82eb1
+ 			      asection *  sec)
0b82eb1
+ {
0b82eb1
+   const char *  dot;
0b82eb1
+   char *  name;
0b82eb1
+   const char *  base_name;
0b82eb1
+   unsigned int  strndx = elf_elfheader (abfd)->e_shstrndx;
0b82eb1
+   unsigned int  shnam = elf_section_data (sec)->rel_hdr.sh_name;
0b82eb1
+ 
0b82eb1
+   base_name = bfd_elf_string_from_elf_section (abfd, strndx, shnam);
0b82eb1
+   if (base_name == NULL)
0b82eb1
+     return NULL;
0b82eb1
+ 
0b82eb1
+   dot = strchr (base_name + 1, '.');
0b82eb1
+   name = bfd_alloc (abfd, strlen (base_name) + strlen (IFUNC_INFIX) + 1);
0b82eb1
+   sprintf (name, "%.*s%s%s", (int)(dot - base_name), base_name, IFUNC_INFIX, dot);
0b82eb1
+ 
0b82eb1
+   return name;
0b82eb1
+ }
0b82eb1
+ 
0b82eb1
+ /* Like _bfd_elf_make_dynamic_reloc_section but it creates a
0b82eb1
+    section for holding relocs against symbols with the STT_GNU_IFUNC
0b82eb1
+    type.  The section is attached to the OWNER bfd but it is created
0b82eb1
+    with a name based on SEC from ABFD.  */
0b82eb1
+ 
0b82eb1
+ asection *
0b82eb1
+ _bfd_elf_make_ifunc_reloc_section (bfd *         abfd,
0b82eb1
+ 				   asection *    sec,
0b82eb1
+ 				   bfd *         owner,
0b82eb1
+ 				   unsigned int  align)
0b82eb1
+ {
0b82eb1
+   asection * reloc_sec = elf_section_data (sec)->indirect_relocs;
0b82eb1
+ 
0b82eb1
+   if (reloc_sec == NULL)
0b82eb1
+     {
0b82eb1
+       const char * name = get_ifunc_reloc_section_name (abfd, sec);
0b82eb1
+ 
0b82eb1
+       if (name == NULL)
0b82eb1
+ 	return NULL;
0b82eb1
+ 
0b82eb1
+       reloc_sec = bfd_get_section_by_name (owner, name);
0b82eb1
+ 
0b82eb1
+       if (reloc_sec == NULL)
0b82eb1
+ 	{
0b82eb1
+ 	  flagword flags;
0b82eb1
+ 
0b82eb1
+ 	  flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED);
0b82eb1
+ 	  if ((sec->flags & SEC_ALLOC) != 0)
0b82eb1
+ 	    flags |= SEC_ALLOC | SEC_LOAD;
0b82eb1
+ 
0b82eb1
+ 	  reloc_sec = bfd_make_section_with_flags (owner, name, flags);
0b82eb1
+ 	  
0b82eb1
+ 	  if (reloc_sec != NULL
0b82eb1
+ 	      && ! bfd_set_section_alignment (owner, reloc_sec, align))
0b82eb1
+ 	    reloc_sec = NULL;
0b82eb1
+ 	}
0b82eb1
+ 
0b82eb1
+       elf_section_data (sec)->indirect_relocs = reloc_sec;
0b82eb1
+     }
0b82eb1
+ 
0b82eb1
+   return reloc_sec;
0b82eb1
+ }
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/bfd/syms.c ./bfd/syms.c
969efb6
*** ../delme/binutils-2.19.51.0.2/bfd/syms.c	2009-02-04 18:14:57.000000000 +0000
969efb6
--- ./bfd/syms.c	2009-03-05 11:54:05.000000000 +0000
0b82eb1
*************** CODE_FRAGMENT
0b82eb1
*** 297,302 ****
0b82eb1
--- 297,308 ----
0b82eb1
  .  {* This symbol was created by bfd_get_synthetic_symtab.  *}
0b82eb1
  .#define BSF_SYNTHETIC		(1 << 21)
0b82eb1
  .
0b82eb1
+ .  {* This symbol is an indirect code object.  Unrelated to BSF_INDIRECT.
0b82eb1
+ .     The dynamic linker will compute the value of this symbol by
0b82eb1
+ .     calling the function that it points to.  BSF_FUNCTION must
0b82eb1
+ .     also be also set.  *}
0b82eb1
+ .#define BSF_GNU_INDIRECT_FUNCTION (1 << 22)
0b82eb1
+ .
0b82eb1
  .  flagword flags;
0b82eb1
  .
0b82eb1
  .  {* A pointer to the section to which this symbol is
0b82eb1
*************** bfd_print_symbol_vandf (bfd *abfd, void 
0b82eb1
*** 483,489 ****
0b82eb1
  	   (type & BSF_WEAK) ? 'w' : ' ',
0b82eb1
  	   (type & BSF_CONSTRUCTOR) ? 'C' : ' ',
0b82eb1
  	   (type & BSF_WARNING) ? 'W' : ' ',
0b82eb1
! 	   (type & BSF_INDIRECT) ? 'I' : ' ',
0b82eb1
  	   (type & BSF_DEBUGGING) ? 'd' : (type & BSF_DYNAMIC) ? 'D' : ' ',
0b82eb1
  	   ((type & BSF_FUNCTION)
0b82eb1
  	    ? 'F'
0b82eb1
--- 489,495 ----
0b82eb1
  	   (type & BSF_WEAK) ? 'w' : ' ',
0b82eb1
  	   (type & BSF_CONSTRUCTOR) ? 'C' : ' ',
0b82eb1
  	   (type & BSF_WARNING) ? 'W' : ' ',
0b82eb1
! 	   (type & BSF_INDIRECT) ? 'I' : (type & BSF_GNU_INDIRECT_FUNCTION) ? 'i' : ' ',
0b82eb1
  	   (type & BSF_DEBUGGING) ? 'd' : (type & BSF_DYNAMIC) ? 'D' : ' ',
0b82eb1
  	   ((type & BSF_FUNCTION)
0b82eb1
  	    ? 'F'
0b82eb1
*************** bfd_decode_symclass (asymbol *symbol)
0b82eb1
*** 669,674 ****
0b82eb1
--- 675,682 ----
0b82eb1
      }
0b82eb1
    if (bfd_is_ind_section (symbol->section))
0b82eb1
      return 'I';
0b82eb1
+   if (symbol->flags & BSF_GNU_INDIRECT_FUNCTION)
0b82eb1
+     return 'i';
0b82eb1
    if (symbol->flags & BSF_WEAK)
0b82eb1
      {
0b82eb1
        /* If weak, determine if it's specifically an object
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/binutils/readelf.c ./binutils/readelf.c
969efb6
*** ../delme/binutils-2.19.51.0.2/binutils/readelf.c	2009-02-04 18:21:50.000000000 +0000
969efb6
--- ./binutils/readelf.c	2009-03-05 11:53:48.000000000 +0000
0b82eb1
*************** dump_relocations (FILE *file,
0b82eb1
*** 1247,1255 ****
0b82eb1
  
0b82eb1
  	      printf (" ");
0b82eb1
  
0b82eb1
- 	      print_vma (psym->st_value, LONG_HEX);
0b82eb1
  
0b82eb1
! 	      printf (is_32bit_elf ? "   " : " ");
0b82eb1
  
0b82eb1
  	      if (psym->st_name == 0)
0b82eb1
  		{
0b82eb1
--- 1247,1285 ----
0b82eb1
  
0b82eb1
  	      printf (" ");
0b82eb1
  
0b82eb1
  
0b82eb1
! 	      if (ELF_ST_TYPE (psym->st_info) == STT_GNU_IFUNC)
0b82eb1
! 		{
0b82eb1
! 		  const char * name;
0b82eb1
! 		  unsigned int len;
0b82eb1
! 		  unsigned int width = is_32bit_elf ? 8 : 14;
0b82eb1
! 
0b82eb1
! 		  /* Relocations against GNU_IFUNC symbols do not use the value
0b82eb1
! 		     of the symbol as the address to relocate against.  Instead
0b82eb1
! 		     they invoke the function named by the symbol and use its
0b82eb1
! 		     result as the address for relocation.
0b82eb1
! 
0b82eb1
! 		     To indicate this to the user, do not display the value of
0b82eb1
! 		     the symbol in the "Symbols's Value" field.  Instead show
0b82eb1
! 		     its name followed by () as a hint that the symbol is
0b82eb1
! 		     invoked.  */
0b82eb1
! 
0b82eb1
! 		  if (strtab == NULL
0b82eb1
! 		      || psym->st_name == 0
0b82eb1
! 		      || psym->st_name >= strtablen)
0b82eb1
! 		    name = "??";
0b82eb1
! 		  else
0b82eb1
! 		    name = strtab + psym->st_name;
0b82eb1
! 
0b82eb1
! 		  len = print_symbol (width, name);
0b82eb1
! 		  printf ("()%-*s", len <= width ? (width + 1) - len : 1, " ");
0b82eb1
! 		}
0b82eb1
! 	      else
0b82eb1
! 		{
0b82eb1
! 		  print_vma (psym->st_value, LONG_HEX);
0b82eb1
! 
0b82eb1
! 		  printf (is_32bit_elf ? "   " : " ");
0b82eb1
! 		}
0b82eb1
  
0b82eb1
  	      if (psym->st_name == 0)
0b82eb1
  		{
0b82eb1
*************** get_symbol_type (unsigned int type)
0b82eb1
*** 7166,7171 ****
0b82eb1
--- 7196,7207 ----
0b82eb1
  		return "HP_STUB";
0b82eb1
  	    }
0b82eb1
  
0b82eb1
+ 	  if (type == STT_GNU_IFUNC
0b82eb1
+ 	      && (elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX
0b82eb1
+ 		  /* GNU/Linux is still using the default value 0.  */
0b82eb1
+ 		  || elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE))
0b82eb1
+ 	    return "IFUNC";
0b82eb1
+ 
0b82eb1
  	  snprintf (buff, sizeof (buff), _("<OS specific>: %d"), type);
0b82eb1
  	}
0b82eb1
        else
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/elfcpp/elfcpp.h ./elfcpp/elfcpp.h
969efb6
*** ../delme/binutils-2.19.51.0.2/elfcpp/elfcpp.h	2009-02-04 18:14:52.000000000 +0000
969efb6
--- ./elfcpp/elfcpp.h	2009-03-05 11:53:39.000000000 +0000
0b82eb1
*************** enum STT
0b82eb1
*** 476,481 ****
0b82eb1
--- 476,482 ----
0b82eb1
    STT_COMMON = 5,
0b82eb1
    STT_TLS = 6,
0b82eb1
    STT_LOOS = 10,
0b82eb1
+   STT_GNU_IFUNC = 10,
0b82eb1
    STT_HIOS = 12,
0b82eb1
    STT_LOPROC = 13,
0b82eb1
    STT_HIPROC = 15,
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/gas/config/obj-elf.c ./gas/config/obj-elf.c
969efb6
*** ../delme/binutils-2.19.51.0.2/gas/config/obj-elf.c	2009-02-04 18:21:50.000000000 +0000
969efb6
--- ./gas/config/obj-elf.c	2009-03-05 11:53:52.000000000 +0000
0b82eb1
*************** obj_elf_type (int ignore ATTRIBUTE_UNUSE
0b82eb1
*** 1706,1711 ****
0b82eb1
--- 1706,1725 ----
0b82eb1
  	    }
0b82eb1
  	}
0b82eb1
      }
0b82eb1
+   else if (strcmp (typename, "gnu_indirect_function") == 0
0b82eb1
+       || strcmp (typename, "10") == 0
0b82eb1
+       || strcmp (typename, "STT_GNU_IFUNC") == 0)
0b82eb1
+     {
0b82eb1
+       const struct elf_backend_data *bed;
0b82eb1
+ 
0b82eb1
+       bed = get_elf_backend_data (stdoutput);
0b82eb1
+       if (!(bed->elf_osabi == ELFOSABI_LINUX
0b82eb1
+ 	    /* GNU/Linux is still using the default value 0.  */
0b82eb1
+ 	    || bed->elf_osabi == ELFOSABI_NONE))
0b82eb1
+ 	as_bad (_("symbol type \"%s\" is supported only by GNU targets"),
0b82eb1
+ 		typename);
0b82eb1
+       type = BSF_FUNCTION | BSF_GNU_INDIRECT_FUNCTION;
0b82eb1
+     }
0b82eb1
  #ifdef md_elf_symbol_type
0b82eb1
    else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
0b82eb1
      ;
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/gas/config/tc-i386.c ./gas/config/tc-i386.c
969efb6
*** ../delme/binutils-2.19.51.0.2/gas/config/tc-i386.c	2009-02-04 18:14:55.000000000 +0000
969efb6
--- ./gas/config/tc-i386.c	2009-03-05 11:53:53.000000000 +0000
0b82eb1
*************** tc_i386_fix_adjustable (fixS *fixP ATTRI
0b82eb1
*** 2499,2504 ****
0b82eb1
--- 2499,2508 ----
0b82eb1
        || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
0b82eb1
        || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
0b82eb1
      return 0;
0b82eb1
+ 
0b82eb1
+   if (fixP->fx_addsy != NULL
0b82eb1
+       && symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_GNU_INDIRECT_FUNCTION)
0b82eb1
+     return 0;
0b82eb1
  #endif
0b82eb1
    return 1;
0b82eb1
  }
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/gas/doc/as.texinfo ./gas/doc/as.texinfo
969efb6
*** ../delme/binutils-2.19.51.0.2/gas/doc/as.texinfo	2009-01-06 17:48:21.000000000 +0000
969efb6
--- ./gas/doc/as.texinfo	2009-03-05 11:53:52.000000000 +0000
0b82eb1
*************** The types supported are:
0b82eb1
*** 6277,6282 ****
0b82eb1
--- 6277,6287 ----
0b82eb1
  @itemx function
0b82eb1
  Mark the symbol as being a function name.
0b82eb1
  
0b82eb1
+ @item STT_GNU_IFUNC
0b82eb1
+ @itemx gnu_indirect_function
0b82eb1
+ Mark the symbol as an indirect function when evaluated during reloc
0b82eb1
+ processing.  (This is only supported on Linux targeted assemblers).
0b82eb1
+ 
0b82eb1
  @item STT_OBJECT
0b82eb1
  @itemx object
0b82eb1
  Mark the symbol as being a data object.
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/gas/NEWS ./gas/NEWS
969efb6
*** ../delme/binutils-2.19.51.0.2/gas/NEWS	2009-01-06 17:48:20.000000000 +0000
969efb6
--- ./gas/NEWS	2009-03-05 11:54:03.000000000 +0000
0b82eb1
***************
0b82eb1
*** 1,5 ****
0b82eb1
--- 1,10 ----
0b82eb1
  -*- text -*-
0b82eb1
  
0b82eb1
+ * The .type pseudo-op now accepts a type of STT_GNU_IFUNC which can be used to
0b82eb1
+   indicate that if the symbol is the target of a relocation, its value should
0b82eb1
+   not be use.  Instead the function should be invoked and its result used as
0b82eb1
+   the value.
0b82eb1
+  
0b82eb1
  * Add support for Lattice Mico32 (lm32) architecture.
0b82eb1
  
0b82eb1
  Changes in 2.19:
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/gas/testsuite/gas/elf/type.e ./gas/testsuite/gas/elf/type.e
969efb6
*** ../delme/binutils-2.19.51.0.2/gas/testsuite/gas/elf/type.e	2007-11-03 20:40:37.000000000 +0000
969efb6
--- ./gas/testsuite/gas/elf/type.e	2009-03-05 11:53:56.000000000 +0000
0b82eb1
***************
0b82eb1
*** 1,5 ****
0b82eb1
       .: 0+0     1 FUNC    LOCAL  DEFAULT    . function
0b82eb1
       .: 0+0     1 OBJECT  LOCAL  DEFAULT    . object
0b82eb1
       .: 0+1     1 TLS     LOCAL  DEFAULT    . tls_object
0b82eb1
!      .: 0+2     1 NOTYPE  LOCAL  DEFAULT    . notype
0b82eb1
      ..: 0+1     1 (COMMON|OBJECT)  GLOBAL DEFAULT  COM common
0b82eb1
--- 1,6 ----
0b82eb1
       .: 0+0     1 FUNC    LOCAL  DEFAULT    . function
0b82eb1
+      .: 0+1     1 IFUNC   LOCAL  DEFAULT    . indirect_function
0b82eb1
       .: 0+0     1 OBJECT  LOCAL  DEFAULT    . object
0b82eb1
       .: 0+1     1 TLS     LOCAL  DEFAULT    . tls_object
0b82eb1
!     ..: 0+2     1 NOTYPE  LOCAL  DEFAULT    . notype
0b82eb1
      ..: 0+1     1 (COMMON|OBJECT)  GLOBAL DEFAULT  COM common
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/gas/testsuite/gas/elf/type.s ./gas/testsuite/gas/elf/type.s
969efb6
*** ../delme/binutils-2.19.51.0.2/gas/testsuite/gas/elf/type.s	2007-11-03 20:40:37.000000000 +0000
969efb6
--- ./gas/testsuite/gas/elf/type.s	2009-03-05 11:53:56.000000000 +0000
0b82eb1
***************
0b82eb1
*** 3,8 ****
0b82eb1
--- 3,12 ----
0b82eb1
          .type   function,%function
0b82eb1
  function:
0b82eb1
  	.byte	0x0
0b82eb1
+         .size   indirect_function,1
0b82eb1
+         .type   indirect_function,%gnu_indirect_function
0b82eb1
+ indirect_function:
0b82eb1
+ 	.byte	0x0
0b82eb1
          .data
0b82eb1
          .type   object,%object
0b82eb1
          .size   object,1
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/include/elf/common.h ./include/elf/common.h
969efb6
*** ../delme/binutils-2.19.51.0.2/include/elf/common.h	2009-02-04 18:21:50.000000000 +0000
969efb6
--- ./include/elf/common.h	2009-03-05 11:53:39.000000000 +0000
0b82eb1
***************
0b82eb1
*** 549,554 ****
0b82eb1
--- 549,555 ----
0b82eb1
  #define STT_RELC	8		/* Complex relocation expression */
0b82eb1
  #define STT_SRELC	9		/* Signed Complex relocation expression */
0b82eb1
  #define STT_LOOS	10		/* OS-specific semantics */
0b82eb1
+ #define STT_GNU_IFUNC	10		/* Symbol is an indirect code object */
0b82eb1
  #define STT_HIOS	12		/* OS-specific semantics */
0b82eb1
  #define STT_LOPROC	13		/* Application-specific semantics */
0b82eb1
  #define STT_HIPROC	15		/* Application-specific semantics */
969efb6
diff -rcp ../delme/binutils-2.19.51.0.2/ld/NEWS ./ld/NEWS
969efb6
*** ../delme/binutils-2.19.51.0.2/ld/NEWS	2009-04-08 16:22:56.000000000 +0100
969efb6
--- ./ld/NEWS	2009-03-05 11:53:45.000000000 +0000
0b82eb1
***************
0b82eb1
*** 1,5 ****
0b82eb1
--- 1,9 ----
0b82eb1
  -*- text -*-
0b82eb1
  
0b82eb1
+ * For GNU/Linux systems the linker will now avoid processing any relocations
0b82eb1
+   made against symbols of the STT_GNU_IFUNC type and instead emit them into
0b82eb1
+   the resulting binary for processing by the loader.
0b82eb1
+ 
0b82eb1
  * --as-needed now links in a dynamic library if it satisfies undefined
0b82eb1
    symbols in regular objects, or in other dynamic libraries.  In the
0b82eb1
    latter case the library is not linked if it is found in a DT_NEEDED