This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

COMMITTED: Add support for STT_IFUNC


Hi Guys,

  I am applying the patch below to add support for a new ELF symbol
  type.  It is currently under review by the ELF committee and I am
  reliably informed that it will be added to the official
  specification fairly soon now.  This is what the specification looks
  like:

    STT_IFUNC
 
      This symbol type is the same as STT_IFUNC except that it always
      points to a function or piece of executable code which takes no
      arguments and which returns a function pointer.  If an STT_IFUNC
      symbol is referred to by a relocation then evaluation of that
      relocation is delayed until load-time.  The value used in the
      relocation is the function pointer returned by an invocation
      of the STT_IFUNC symbol.
 
      The purpose of this symbol type is it to allow the run-time to
      select between multiple versions of the implementation of a
      specific function.  The selection made in general will take the
      currently available hardware into account and select the most
      appropriate version.
  
  So this patch adds support for this symbol type to the assembler
  (via ".type <foo>, %STT_IFUNC"), the linker and the binutils.
  Currently linker support has only been added for the x86 and x86_64
  targets, but it can easily be extended to other targets that might
  wish to use it.

  Run-time relocations against this symbol type are placed into a new
  section called .rel[a].ifunc.dyn which immediately follows the
  .rel[a].dyn section.  The idea here is to allow the dynamic linker
  to execute all of the normal dynamic relocations first, before it
  tries to execute any of the STT_IFUNC using dynamic relocs.  This is
  just in case the invoked STT_IFUNC function has any dependencies
  upon other symbols.

  Readelf, nm and objdump have been extended to display the new symbol
  type.  Objdump and nm use the letter 'i' to indicate the new
  symbol type, eg:
  
     080484c0 g   i   .text  00000024              ifunction

  whereas readelf uses IFUNC:
  
     7: 080484c0    36 IFUNC   GLOBAL DEFAULT   14 ifunction
     
  Plus objdump and readelf will append "()" to relocs which are made
  against STT_IFUNC symbols, as a hint that the relocation invokes a
  function:

    RELOCATION RECORDS FOR [.text]:
    OFFSET   TYPE              VALUE 
    00000009 R_386_32          .rodata
    0000009f R_386_PC32        ifunction() 

  Tested against all sorts of toolchains without any regressions.

Cheers
  Nick

include/elf/ChangeLog
2008-12-03  Nick Clifton  <nickc@redhat.com>

	* common.h (STT_IFUNC): Define.

elfcpp/ChangeLog
2008-12-03  Nick Clifton  <nickc@redhat.com>

	* elfcpp.h (enum STT): Add STT_IFUNC.

bfd/ChangeLog
2008-12-03  Nick Clifton  <nickc@redhat.com>

	* syms.c (struct bfd_symbol): Add new flag BSF_INDIRECT_FUNCTION.
	Remove redundant flag BFD_FORT_COMM_DEFAULT_VALUE.  Renumber flags
	to remove gaps.
	(bfd_print_symbol_vandf): Return 'i' for BSF_INDIRECT_FUNCTION.
	(bfd_decode_symclass): Likewise.
	* elf.c (swap_out_syms): Translate BSF_INDIRECT_FUNCTION into
	STT_IFUNC.
	(elf_find_function): Treat STT_IFUNC in the same way as STT_FUNC.
	(_bfd_elf_is_function_type): Likewise.
	* elf32-arm.c (arm_elf_find_function): Likewise.
	(elf32_arm_adjust_dynamic_symbol): Likewise.
	(elf32_arm_swap_symbol_in): Likewise.
	(elf32_arm_additional_program_headers): Likewise.
	* elf32-i386.c (is_indirect_symbol): New function.
	(elf_i386_check_relocs): Also generate dynamic relocs for
	relocations against STT_IFUNC symbols.
	(allocate_dynrelocs): Likewise.
	(elf_i386_relocate_section): Likewise.
	* elf64-x86-64.c (is_indirect_symbol): New function.
	(elf64_x86_64_check_relocs): Also generate dynamic relocs for
	relocations against STT_IFUNC symbols.
	(allocate_dynrelocs): Likewise.
	(elf64_x86_64_relocate_section): Likewise.
	* elfcode.h (elf_slurp_symbol_table): Translate STT_IFUNC into
	BSF_INDIRECT_FUNCTION.
	* elflink.c (_bfd_elf_adjust_dynamic_reloc_section): Add support
	for STT_IFUNC symbols.
	(get_ifunc_reloc_section_name): New function.
	(_bfd_elf_make_ifunc_reloc_section): New function.
	* elf-bfd.h (struct bfd_elf_section_data): Add indirect_relocs field.
	* bfd-in2.h: Regenerate.

gas/ChangeLog
2008-12-03  Nick Clifton  <nickc@redhat.com>

	* config/obj-elf.c (obj_elf_type): Add support for STT_IFUNC type.
	* doc/as.texinfo: Document new feature.
	* NEWS: Mention new feature.

gas/testsuite/ChangeLog
2008-12-03  Nick Clifton  <nickc@redhat.com>

	* gas/elf/type.s: Add test of STT_IFUNC symbol type.
	* gas/elf/type.e: Update expected disassembly.
	* gas/elf/elf.exp: Update grep of symbol types.

ld/ChangeLog
2008-12-03  Nick Clifton  <nickc@redhat.com>

	* NEWS: Mention new feature.
	* NEWS: Mention new feature.
	* pe-dll.c (process_def_file): Replace use of redundant
	BFD_FORT_COMM_DEFAULT_VALUE with 0.
	* scripttempl/elf.sc: Add .rel.ifunc.dyn and .rela.ifunc.dyn
	sections.

ld/testsuite/ChangeLog
2008-12-03  Nick Clifton  <nickc@redhat.com>

	* ld-mips-elf/reloc-1-n32.d: Updated expected output for reloc
	descriptions.
	* ld-mips-elf/reloc-1-n64.d: Likewise.
	* ld-i386/ifunc.d: New test.
	* ld-i386/ifunc.s: Source file for the new test.
	* ld-i386/i386.exp: Run the new test.

Index: include/elf/common.h
===================================================================
RCS file: /cvs/src/src/include/elf/common.h,v
retrieving revision 1.100
diff -c -3 -p -r1.100 common.h
*** include/elf/common.h	13 Nov 2008 15:07:54 -0000	1.100
--- include/elf/common.h	3 Dec 2008 08:01:35 -0000
***************
*** 546,551 ****
--- 546,552 ----
  #define STT_RELC	8		/* Complex relocation expression */
  #define STT_SRELC	9		/* Signed Complex relocation expression */
  #define STT_LOOS	10		/* OS-specific semantics */
+ #define STT_IFUNC	10		/* Symbol is an indirect code object */
  #define STT_HIOS	12		/* OS-specific semantics */
  #define STT_LOPROC	13		/* Application-specific semantics */
  #define STT_HIPROC	15		/* Application-specific semantics */
Index: elfcpp/elfcpp.h
===================================================================
RCS file: /cvs/src/src/elfcpp/elfcpp.h,v
retrieving revision 1.18
diff -c -3 -p -r1.18 elfcpp.h
*** elfcpp/elfcpp.h	12 Jun 2008 16:58:40 -0000	1.18
--- elfcpp/elfcpp.h	3 Dec 2008 08:01:35 -0000
***************
*** 1,6 ****
  // elfcpp.h -- main header file for elfcpp    -*- C++ -*-
  
! // Copyright 2006, 2007, Free Software Foundation, Inc.
  // Written by Ian Lance Taylor <iant@google.com>.
  
  // This file is part of elfcpp.
--- 1,6 ----
  // elfcpp.h -- main header file for elfcpp    -*- C++ -*-
  
! // Copyright 2006, 2007, 2008, Free Software Foundation, Inc.
  // Written by Ian Lance Taylor <iant@google.com>.
  
  // This file is part of elfcpp.
*************** enum STT
*** 476,481 ****
--- 476,482 ----
    STT_COMMON = 5,
    STT_TLS = 6,
    STT_LOOS = 10,
+   STT_IFUNC = 10,
    STT_HIOS = 12,
    STT_LOPROC = 13,
    STT_HIPROC = 15,
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.458
diff -c -3 -p -r1.458 bfd-in2.h
*** bfd/bfd-in2.h	28 Nov 2008 18:02:16 -0000	1.458
--- bfd/bfd-in2.h	3 Dec 2008 08:01:37 -0000
*************** typedef struct bfd_symbol
*** 4445,4544 ****
    symvalue value;
  
    /* Attributes of a symbol.  */
! #define BSF_NO_FLAGS    0x00
  
    /* The symbol has local scope; <<static>> in <<C>>. The value
       is the offset into the section of the data.  */
! #define BSF_LOCAL      0x01
  
    /* The symbol has global scope; initialized data in <<C>>. The
       value is the offset into the section of the data.  */
! #define BSF_GLOBAL     0x02
  
    /* The symbol has global scope and is exported. The value is
       the offset into the section of the data.  */
  #define BSF_EXPORT     BSF_GLOBAL /* No real difference.  */
  
    /* A normal C symbol would be one of:
!      <<BSF_LOCAL>>, <<BSF_FORT_COMM>>,  <<BSF_UNDEFINED>> or
       <<BSF_GLOBAL>>.  */
  
    /* The symbol is a debugging record. The value has an arbitrary
       meaning, unless BSF_DEBUGGING_RELOC is also set.  */
! #define BSF_DEBUGGING  0x08
  
    /* The symbol denotes a function entry point.  Used in ELF,
       perhaps others someday.  */
! #define BSF_FUNCTION    0x10
  
    /* Used by the linker.  */
! #define BSF_KEEP        0x20
! #define BSF_KEEP_G      0x40
  
    /* A weak global symbol, overridable without warnings by
       a regular global symbol of the same name.  */
! #define BSF_WEAK        0x80
  
    /* This symbol was created to point to a section, e.g. ELF's
       STT_SECTION symbols.  */
! #define BSF_SECTION_SYM 0x100
  
    /* The symbol used to be a common symbol, but now it is
       allocated.  */
! #define BSF_OLD_COMMON  0x200
! 
!   /* The default value for common data.  */
! #define BFD_FORT_COMM_DEFAULT_VALUE 0
  
    /* In some files the type of a symbol sometimes alters its
       location in an output file - ie in coff a <<ISFCN>> symbol
       which is also <<C_EXT>> symbol appears where it was
       declared and not at the end of a section.  This bit is set
       by the target BFD part to convey this information.  */
! #define BSF_NOT_AT_END    0x400
  
    /* Signal that the symbol is the label of constructor section.  */
! #define BSF_CONSTRUCTOR   0x800
  
    /* Signal that the symbol is a warning symbol.  The name is a
       warning.  The name of the next symbol is the one to warn about;
       if a reference is made to a symbol with the same name as the next
       symbol, a warning is issued by the linker.  */
! #define BSF_WARNING       0x1000
  
    /* Signal that the symbol is indirect.  This symbol is an indirect
       pointer to the symbol with the same name as the next symbol.  */
! #define BSF_INDIRECT      0x2000
  
    /* BSF_FILE marks symbols that contain a file name.  This is used
       for ELF STT_FILE symbols.  */
! #define BSF_FILE          0x4000
  
    /* Symbol is from dynamic linking information.  */
! #define BSF_DYNAMIC       0x8000
  
    /* The symbol denotes a data object.  Used in ELF, and perhaps
       others someday.  */
! #define BSF_OBJECT        0x10000
  
    /* This symbol is a debugging symbol.  The value is the offset
       into the section of the data.  BSF_DEBUGGING should be set
       as well.  */
! #define BSF_DEBUGGING_RELOC 0x20000
  
    /* This symbol is thread local.  Used in ELF.  */
! #define BSF_THREAD_LOCAL  0x40000
  
    /* This symbol represents a complex relocation expression,
       with the expression tree serialized in the symbol name.  */
! #define BSF_RELC 0x80000
  
    /* This symbol represents a signed complex relocation expression,
       with the expression tree serialized in the symbol name.  */
! #define BSF_SRELC 0x100000
  
    /* This symbol was created by bfd_get_synthetic_symtab.  */
! #define BSF_SYNTHETIC 0x200000
  
    flagword flags;
  
--- 4445,4548 ----
    symvalue value;
  
    /* Attributes of a symbol.  */
! #define BSF_NO_FLAGS           0x00
  
    /* The symbol has local scope; <<static>> in <<C>>. The value
       is the offset into the section of the data.  */
! #define BSF_LOCAL              (1 << 0)
  
    /* The symbol has global scope; initialized data in <<C>>. The
       value is the offset into the section of the data.  */
! #define BSF_GLOBAL             (1 << 1)
  
    /* The symbol has global scope and is exported. The value is
       the offset into the section of the data.  */
  #define BSF_EXPORT     BSF_GLOBAL /* No real difference.  */
  
    /* A normal C symbol would be one of:
!      <<BSF_LOCAL>>, <<BSF_COMMON>>,  <<BSF_UNDEFINED>> or
       <<BSF_GLOBAL>>.  */
  
    /* The symbol is a debugging record. The value has an arbitrary
       meaning, unless BSF_DEBUGGING_RELOC is also set.  */
! #define BSF_DEBUGGING          (1 << 2)
  
    /* The symbol denotes a function entry point.  Used in ELF,
       perhaps others someday.  */
! #define BSF_FUNCTION           (1 << 3)
  
+   /* The symbol is an indirect code object.  Unrelated to BSF_INDIRECT.
+      Relocations against a symbol with this flag have to evaluated at
+      run-time, where the function pointed to by this symbol is invoked
+      in order to determine the value to be used in the relocation.
+      BSF_FUNCTION must also be set for symbols with this flag.  */
+ #define BSF_INDIRECT_FUNCTION  (1 << 4)
+  
    /* Used by the linker.  */
! #define BSF_KEEP               (1 << 5)
! #define BSF_KEEP_G             (1 << 6)
  
    /* A weak global symbol, overridable without warnings by
       a regular global symbol of the same name.  */
! #define BSF_WEAK               (1 << 7)
  
    /* This symbol was created to point to a section, e.g. ELF's
       STT_SECTION symbols.  */
! #define BSF_SECTION_SYM        (1 << 8)
  
    /* The symbol used to be a common symbol, but now it is
       allocated.  */
! #define BSF_OLD_COMMON         (1 << 9)
  
    /* In some files the type of a symbol sometimes alters its
       location in an output file - ie in coff a <<ISFCN>> symbol
       which is also <<C_EXT>> symbol appears where it was
       declared and not at the end of a section.  This bit is set
       by the target BFD part to convey this information.  */
! #define BSF_NOT_AT_END         (1 << 10)
  
    /* Signal that the symbol is the label of constructor section.  */
! #define BSF_CONSTRUCTOR        (1 << 11)
  
    /* Signal that the symbol is a warning symbol.  The name is a
       warning.  The name of the next symbol is the one to warn about;
       if a reference is made to a symbol with the same name as the next
       symbol, a warning is issued by the linker.  */
! #define BSF_WARNING            (1 << 12)
  
    /* Signal that the symbol is indirect.  This symbol is an indirect
       pointer to the symbol with the same name as the next symbol.  */
! #define BSF_INDIRECT           (1 << 13)
  
    /* BSF_FILE marks symbols that contain a file name.  This is used
       for ELF STT_FILE symbols.  */
! #define BSF_FILE               (1 << 14)
  
    /* Symbol is from dynamic linking information.  */
! #define BSF_DYNAMIC            (1 << 15)
  
    /* The symbol denotes a data object.  Used in ELF, and perhaps
       others someday.  */
! #define BSF_OBJECT             (1 << 16)
  
    /* This symbol is a debugging symbol.  The value is the offset
       into the section of the data.  BSF_DEBUGGING should be set
       as well.  */
! #define BSF_DEBUGGING_RELOC    (1 << 17)
  
    /* This symbol is thread local.  Used in ELF.  */
! #define BSF_THREAD_LOCAL       (1 << 18)
  
    /* This symbol represents a complex relocation expression,
       with the expression tree serialized in the symbol name.  */
! #define BSF_RELC               (1 << 19)
  
    /* This symbol represents a signed complex relocation expression,
       with the expression tree serialized in the symbol name.  */
! #define BSF_SRELC              (1 << 20)
  
    /* This symbol was created by bfd_get_synthetic_symtab.  */
! #define BSF_SYNTHETIC          (1 << 21)
  
    flagword flags;
  
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.270
diff -c -3 -p -r1.270 elf-bfd.h
*** bfd/elf-bfd.h	25 Nov 2008 13:03:54 -0000	1.270
--- bfd/elf-bfd.h	3 Dec 2008 08:01:38 -0000
*************** struct bfd_elf_section_data
*** 1287,1292 ****
--- 1287,1295 ----
    /* 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;
*************** extern asection * _bfd_elf_get_dynamic_r
*** 1768,1773 ****
--- 1771,1778 ----
    (bfd *, asection *, bfd_boolean);
  extern asection * _bfd_elf_make_dynamic_reloc_section
    (asection *, bfd *, unsigned int, bfd *, bfd_boolean);
+ extern asection * _bfd_elf_make_ifunc_reloc_section
+   (bfd *, asection *, bfd *, unsigned int);
  extern long _bfd_elf_get_dynamic_reloc_upper_bound
    (bfd *);
  extern long _bfd_elf_canonicalize_dynamic_reloc
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.472
diff -c -3 -p -r1.472 elf.c
*** bfd/elf.c	19 Nov 2008 10:09:21 -0000	1.472
--- bfd/elf.c	3 Dec 2008 08:01:40 -0000
*************** Unable to find equivalent output section
*** 6427,6432 ****
--- 6427,6434 ----
  
        if ((flags & BSF_THREAD_LOCAL) != 0)
  	type = STT_TLS;
+       else if ((flags & BSF_INDIRECT_FUNCTION) != 0)
+ 	type = STT_IFUNC;
        else if ((flags & BSF_FUNCTION) != 0)
  	type = STT_FUNC;
        else if ((flags & BSF_OBJECT) != 0)
*************** elf_find_function (bfd *abfd ATTRIBUTE_U
*** 7120,7125 ****
--- 7122,7128 ----
  	  continue;
  	case STT_NOTYPE:
  	case STT_FUNC:
+ 	case STT_IFUNC:
  	  if (bfd_get_section (&q->symbol) == section
  	      && q->symbol.value >= low_func
  	      && q->symbol.value <= offset)
*************** _bfd_elf_set_osabi (bfd * abfd,
*** 8938,8947 ****
  
  /* Return TRUE for ELF symbol types that represent functions.
     This is the default version of this function, which is sufficient for
!    most targets.  It returns true if TYPE is STT_FUNC.  */
  
  bfd_boolean
  _bfd_elf_is_function_type (unsigned int type)
  {
!   return (type == STT_FUNC);
  }
--- 8941,8950 ----
  
  /* Return TRUE for ELF symbol types that represent functions.
     This is the default version of this function, which is sufficient for
!    most targets.  It returns true if TYPE is STT_FUNC or STT_IFUNC.  */
  
  bfd_boolean
  _bfd_elf_is_function_type (unsigned int type)
  {
!   return (type == STT_FUNC || type == STT_IFUNC);
  }
Index: bfd/elf32-arm.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-arm.c,v
retrieving revision 1.160
diff -c -3 -p -r1.160 elf32-arm.c
*** bfd/elf32-arm.c	25 Nov 2008 15:53:26 -0000	1.160
--- bfd/elf32-arm.c	3 Dec 2008 08:01:43 -0000
*************** arm_elf_find_function (bfd *         abf
*** 9430,9435 ****
--- 9430,9436 ----
  	  filename = bfd_asymbol_name (&q->symbol);
  	  break;
  	case STT_FUNC:
+ 	case STT_IFUNC:
  	case STT_ARM_TFUNC:
  	case STT_NOTYPE:
  	  /* Skip mapping symbols.  */
*************** elf32_arm_adjust_dynamic_symbol (struct 
*** 9555,9561 ****
    /* If this is a function, put it in the procedure linkage table.  We
       will fill in the contents of the procedure linkage table later,
       when we know the address of the .got section.  */
!   if (h->type == STT_FUNC || h->type == STT_ARM_TFUNC
        || h->needs_plt)
      {
        if (h->plt.refcount <= 0
--- 9556,9562 ----
    /* If this is a function, put it in the procedure linkage table.  We
       will fill in the contents of the procedure linkage table later,
       when we know the address of the .got section.  */
!   if (h->type == STT_FUNC || h->type == STT_ARM_TFUNC || h->type == STT_IFUNC
        || h->needs_plt)
      {
        if (h->plt.refcount <= 0
*************** elf32_arm_swap_symbol_in (bfd * abfd,
*** 11729,11735 ****
  
    /* New EABI objects mark thumb function symbols by setting the low bit of
       the address.  Turn these into STT_ARM_TFUNC.  */
!   if (ELF_ST_TYPE (dst->st_info) == STT_FUNC
        && (dst->st_value & 1))
      {
        dst->st_info = ELF_ST_INFO (ELF_ST_BIND (dst->st_info), STT_ARM_TFUNC);
--- 11730,11737 ----
  
    /* New EABI objects mark thumb function symbols by setting the low bit of
       the address.  Turn these into STT_ARM_TFUNC.  */
!   if ((ELF_ST_TYPE (dst->st_info) == STT_FUNC
!        || ELF_ST_TYPE (dst->st_info) == STT_IFUNC)
        && (dst->st_value & 1))
      {
        dst->st_info = ELF_ST_INFO (ELF_ST_BIND (dst->st_info), STT_ARM_TFUNC);
*************** elf32_arm_additional_program_headers (bf
*** 11830,11836 ****
  static bfd_boolean
  elf32_arm_is_function_type (unsigned int type)
  {
!   return (type == STT_FUNC) || (type == STT_ARM_TFUNC);
  }
  
  /* We use this to override swap_symbol_in and swap_symbol_out.  */
--- 11832,11838 ----
  static bfd_boolean
  elf32_arm_is_function_type (unsigned int type)
  {
!   return (type == STT_FUNC) || (type == STT_ARM_TFUNC) || (type == STT_IFUNC);
  }
  
  /* We use this to override swap_symbol_in and swap_symbol_out.  */
Index: bfd/elf32-i386.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-i386.c,v
retrieving revision 1.189
diff -c -3 -p -r1.189 elf32-i386.c
*** bfd/elf32-i386.c	25 Nov 2008 13:03:55 -0000	1.189
--- bfd/elf32-i386.c	3 Dec 2008 08:01:44 -0000
*************** elf_i386_tls_transition (struct bfd_link
*** 1193,1198 ****
--- 1193,1218 ----
    return TRUE;
  }
  
+ /* Returns true if the hash entry refers to a symbol
+    marked for indirect handling during reloc processing.  */
+ 
+ static bfd_boolean
+ is_indirect_symbol (bfd * abfd, struct elf_link_hash_entry * h)
+ {
+   const struct elf_backend_data * bed;
+ 
+   if (abfd == NULL || h == NULL)
+     return FALSE;
+ 
+   bed = get_elf_backend_data (abfd);
+ 
+   return h->type == STT_IFUNC
+     && bed != NULL
+     && (bed->elf_osabi == ELFOSABI_LINUX
+ 	/* GNU/Linux is still using the default value 0.  */
+ 	|| bed->elf_osabi == ELFOSABI_NONE);
+ }
+ 
  /* Look through the relocs for a section during the first phase, and
     calculate needed space in the global offset table, procedure linkage
     table, and dynamic reloc sections.  */
*************** elf_i386_check_relocs (bfd *abfd,
*** 1452,1458 ****
  		  && (sec->flags & SEC_ALLOC) != 0
  		  && h != NULL
  		  && (h->root.type == bfd_link_hash_defweak
! 		      || !h->def_regular)))
  	    {
  	      struct elf_i386_dyn_relocs *p;
  	      struct elf_i386_dyn_relocs **head;
--- 1472,1479 ----
  		  && (sec->flags & SEC_ALLOC) != 0
  		  && h != NULL
  		  && (h->root.type == bfd_link_hash_defweak
! 		      || !h->def_regular))
! 	      || is_indirect_symbol (abfd, h))	      
  	    {
  	      struct elf_i386_dyn_relocs *p;
  	      struct elf_i386_dyn_relocs **head;
*************** elf_i386_check_relocs (bfd *abfd,
*** 1472,1477 ****
--- 1493,1501 ----
  		    return FALSE;
  		}
  
+ 	      if (is_indirect_symbol (abfd, h))
+ 		(void) _bfd_elf_make_ifunc_reloc_section (abfd, sec, htab->elf.dynobj, 2);
+ 
  	      /* If this is a global symbol, we count the number of
  		 relocations we need for this symbol.  */
  	      if (h != NULL)
*************** allocate_dynrelocs (struct elf_link_hash
*** 2033,2038 ****
--- 2057,2071 ----
  	    }
  	}
      }
+   else if (is_indirect_symbol (info->output_bfd, h))
+     {
+       if (h->dynindx == -1
+ 	  && !h->forced_local)
+ 	{
+ 	  if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ 	    return FALSE;
+ 	}
+     }
    else if (ELIMINATE_COPY_RELOCS)
      {
        /* For the non-shared case, discard space for relocs against
*************** allocate_dynrelocs (struct elf_link_hash
*** 2069,2075 ****
    /* 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);
      }
  
--- 2102,2116 ----
    /* Finally, allocate space.  */
    for (p = eh->dyn_relocs; p != NULL; p = p->next)
      {
!       asection *sreloc;
! 
!       if (! info->shared
! 	  && is_indirect_symbol (info->output_bfd, h))
! 	sreloc = elf_section_data (p->sec)->indirect_relocs;
!       else
! 	sreloc = elf_section_data (p->sec)->sreloc;
! 
!       BFD_ASSERT (sreloc != NULL);
        sreloc->size += p->count * sizeof (Elf32_External_Rel);
      }
  
*************** elf_i386_relocate_section (bfd *output_b
*** 2879,2885 ****
  		  && ((h->def_dynamic
  		       && !h->def_regular)
  		      || h->root.type == bfd_link_hash_undefweak
! 		      || h->root.type == bfd_link_hash_undefined)))
  	    {
  	      Elf_Internal_Rela outrel;
  	      bfd_byte *loc;
--- 2919,2926 ----
  		  && ((h->def_dynamic
  		       && !h->def_regular)
  		      || h->root.type == bfd_link_hash_undefweak
! 		      || h->root.type == bfd_link_hash_undefined))
! 	      || is_indirect_symbol (output_bfd, h))
  	    {
  	      Elf_Internal_Rela outrel;
  	      bfd_byte *loc;
*************** elf_i386_relocate_section (bfd *output_b
*** 2919,2937 ****
  		  outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
  		}
  
! 	      sreloc = elf_section_data (input_section)->sreloc;
  	      if (sreloc == NULL)
  		abort ();
  
  	      loc = sreloc->contents;
  	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
  	      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
  
  	      /* If this reloc is against an external symbol, we do
  		 not want to fiddle with the addend.  Otherwise, we
  		 need to include the symbol value so that it becomes
  		 an addend for the dynamic reloc.  */
! 	      if (! relocate)
  		continue;
  	    }
  	  break;
--- 2960,2983 ----
  		  outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
  		}
  
! 	      if (is_indirect_symbol (output_bfd, h))
! 		sreloc = elf_section_data (input_section)->indirect_relocs;
! 	      else
! 		sreloc = elf_section_data (input_section)->sreloc;
! 
  	      if (sreloc == NULL)
  		abort ();
  
  	      loc = sreloc->contents;
  	      loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
+ 
  	      bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
  
  	      /* If this reloc is against an external symbol, we do
  		 not want to fiddle with the addend.  Otherwise, we
  		 need to include the symbol value so that it becomes
  		 an addend for the dynamic reloc.  */
! 	      if (! relocate || is_indirect_symbol (output_bfd, h))
  		continue;
  	    }
  	  break;
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.149
diff -c -3 -p -r1.149 elf64-x86-64.c
*** bfd/elf64-x86-64.c	25 Nov 2008 13:03:56 -0000	1.149
--- bfd/elf64-x86-64.c	3 Dec 2008 08:01:47 -0000
*************** elf64_x86_64_tls_transition (struct bfd_
*** 974,979 ****
--- 974,999 ----
    return TRUE;
  }
  
+ /* Returns true if the hash entry refers to a symbol
+    marked for indirect handling during reloc processing.  */
+ 
+ static bfd_boolean
+ is_indirect_symbol (bfd * abfd, struct elf_link_hash_entry * h)
+ {
+   const struct elf_backend_data * bed;
+ 
+   if (abfd == NULL || h == NULL)
+     return FALSE;
+ 
+   bed = get_elf_backend_data (abfd);
+ 
+   return h->type == STT_IFUNC
+     && bed != NULL
+     && (bed->elf_osabi == ELFOSABI_LINUX
+ 	/* GNU/Linux is still using the default value 0.  */
+ 	|| bed->elf_osabi == ELFOSABI_NONE);
+ }
+ 
  /* Look through the relocs for a section during the first phase, and
     calculate needed space in the global offset table, procedure
     linkage table, and dynamic reloc sections.  */
*************** elf64_x86_64_check_relocs (bfd *abfd, st
*** 1255,1261 ****
  	     If on the other hand, we are creating an executable, we
  	     may need to keep relocations for symbols satisfied by a
  	     dynamic library if we manage to avoid copy relocs for the
! 	     symbol.  */
  	  if ((info->shared
  	       && (sec->flags & SEC_ALLOC) != 0
  	       && (((r_type != R_X86_64_PC8)
--- 1275,1284 ----
  	     If on the other hand, we are creating an executable, we
  	     may need to keep relocations for symbols satisfied by a
  	     dynamic library if we manage to avoid copy relocs for the
! 	     symbol.
! 
! 	     Also we must keep any relocations against IFUNC symbols as
! 	     they will be evaluated at load time.  */
  	  if ((info->shared
  	       && (sec->flags & SEC_ALLOC) != 0
  	       && (((r_type != R_X86_64_PC8)
*************** elf64_x86_64_check_relocs (bfd *abfd, st
*** 1271,1277 ****
  		  && (sec->flags & SEC_ALLOC) != 0
  		  && h != NULL
  		  && (h->root.type == bfd_link_hash_defweak
! 		      || !h->def_regular)))
  	    {
  	      struct elf64_x86_64_dyn_relocs *p;
  	      struct elf64_x86_64_dyn_relocs **head;
--- 1294,1301 ----
  		  && (sec->flags & SEC_ALLOC) != 0
  		  && h != NULL
  		  && (h->root.type == bfd_link_hash_defweak
! 		      || !h->def_regular))
! 	      || is_indirect_symbol (abfd, h))
  	    {
  	      struct elf64_x86_64_dyn_relocs *p;
  	      struct elf64_x86_64_dyn_relocs **head;
*************** elf64_x86_64_check_relocs (bfd *abfd, st
*** 1291,1296 ****
--- 1315,1323 ----
  		    return FALSE;
  		}
  
+ 	      if (is_indirect_symbol (abfd, h))
+ 		(void) _bfd_elf_make_ifunc_reloc_section (abfd, sec, htab->elf.dynobj, 2);
+ 
  	      /* If this is a global symbol, we count the number of
  		 relocations we need for this symbol.  */
  	      if (h != NULL)
*************** allocate_dynrelocs (struct elf_link_hash
*** 1830,1835 ****
--- 1857,1869 ----
  	    }
  	}
      }
+   else if (is_indirect_symbol (info->output_bfd, h))
+     {
+       if (h->dynindx == -1
+ 	  && ! h->forced_local
+ 	  && ! bfd_elf_link_record_dynamic_symbol (info, h))
+ 	return FALSE;    
+     }
    else if (ELIMINATE_COPY_RELOCS)
      {
        /* For the non-shared case, discard space for relocs against
*************** allocate_dynrelocs (struct elf_link_hash
*** 1866,1872 ****
    /* 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);
      }
  
--- 1900,1915 ----
    /* Finally, allocate space.  */
    for (p = eh->dyn_relocs; p != NULL; p = p->next)
      {
!       asection * sreloc;
! 
!       if (! info->shared
! 	  && is_indirect_symbol (info->output_bfd, h))
! 	sreloc = elf_section_data (p->sec)->indirect_relocs;
!       else
! 	sreloc = elf_section_data (p->sec)->sreloc;
! 
!       BFD_ASSERT (sreloc != NULL);
! 
        sreloc->size += p->count * sizeof (Elf64_External_Rela);
      }
  
*************** elf64_x86_64_relocate_section (bfd *outp
*** 2680,2686 ****
  		  && ((h->def_dynamic
  		       && !h->def_regular)
  		      || h->root.type == bfd_link_hash_undefweak
! 		      || h->root.type == bfd_link_hash_undefined)))
  	    {
  	      Elf_Internal_Rela outrel;
  	      bfd_byte *loc;
--- 2721,2728 ----
  		  && ((h->def_dynamic
  		       && !h->def_regular)
  		      || h->root.type == bfd_link_hash_undefweak
! 		      || h->root.type == bfd_link_hash_undefined))
! 	      || is_indirect_symbol (output_bfd, h))
  	    {
  	      Elf_Internal_Rela outrel;
  	      bfd_byte *loc;
*************** elf64_x86_64_relocate_section (bfd *outp
*** 2766,2774 ****
  		    }
  		}
  
! 	      sreloc = elf_section_data (input_section)->sreloc;
! 	      if (sreloc == NULL)
! 		abort ();
  
  	      loc = sreloc->contents;
  	      loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
--- 2808,2819 ----
  		    }
  		}
  
! 	      if (is_indirect_symbol (output_bfd, h))
! 		sreloc = elf_section_data (input_section)->indirect_relocs;
! 	      else
! 		sreloc = elf_section_data (input_section)->sreloc;
! 		
! 	      BFD_ASSERT (sreloc != NULL);
  
  	      loc = sreloc->contents;
  	      loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
*************** elf64_x86_64_relocate_section (bfd *outp
*** 2778,2784 ****
  		 not want to fiddle with the addend.  Otherwise, we
  		 need to include the symbol value so that it becomes
  		 an addend for the dynamic reloc.  */
! 	      if (! relocate)
  		continue;
  	    }
  
--- 2823,2829 ----
  		 not want to fiddle with the addend.  Otherwise, we
  		 need to include the symbol value so that it becomes
  		 an addend for the dynamic reloc.  */
! 	      if (! relocate || is_indirect_symbol (output_bfd, h))
  		continue;
  	    }
  
Index: bfd/elfcode.h
===================================================================
RCS file: /cvs/src/src/bfd/elfcode.h,v
retrieving revision 1.91
diff -c -3 -p -r1.91 elfcode.h
*** bfd/elfcode.h	1 Aug 2008 12:21:28 -0000	1.91
--- bfd/elfcode.h	3 Dec 2008 08:01:47 -0000
*************** elf_slurp_symbol_table (bfd *abfd, asymb
*** 1311,1316 ****
--- 1311,1319 ----
  	    case STT_SRELC:
  	      sym->symbol.flags |= BSF_SRELC;
  	      break;
+ 	    case STT_IFUNC:
+ 	      sym->symbol.flags |= BSF_INDIRECT_FUNCTION;
+ 	      break;
  	    }
  
  	  if (dynamic)
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.318
diff -c -3 -p -r1.318 elflink.c
*** bfd/elflink.c	26 Nov 2008 01:04:15 -0000	1.318
--- bfd/elflink.c	3 Dec 2008 08:01:49 -0000
*************** _bfd_elf_adjust_dynamic_symbol (struct e
*** 2652,2657 ****
--- 2652,2664 ----
  
    dynobj = elf_hash_table (eif->info)->dynobj;
    bed = get_elf_backend_data (dynobj);
+ 
+   if (h->type == STT_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;
*************** _bfd_elf_make_dynamic_reloc_section (ase
*** 12400,12402 ****
--- 12407,12477 ----
  
    return reloc_sec;
  }
+ 
+ #define IFUNC_INFIX ".ifunc"
+ 
+ /* Returns the name of the ifunc-using-dynamic-reloc section associated with SEC.  */
+ 
+ static const char *
+ get_ifunc_reloc_section_name (bfd *       abfd,
+ 			      asection *  sec)
+ {
+   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);
+ 
+   return name;
+ }
+ 
+ /* Like _bfd_elf_make_dynamic_reloc_section but it creates a
+    section for holding relocs against symbols with the STT_IFUNC
+    type.  The section is attached to the OWNER bfd but it is created
+    with a name based on SEC from ABFD.  */
+ 
+ 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;
+ 
+   if (reloc_sec == NULL)
+     {
+       const char * name = get_ifunc_reloc_section_name (abfd, sec);
+ 
+       if (name == NULL)
+ 	return NULL;
+ 
+       reloc_sec = bfd_get_section_by_name (owner, name);
+ 
+       if (reloc_sec == NULL)
+ 	{
+ 	  flagword flags;
+ 
+ 	  flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+ 	  if ((sec->flags & SEC_ALLOC) != 0)
+ 	    flags |= SEC_ALLOC | SEC_LOAD;
+ 
+ 	  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;
+ 	}
+ 
+       elf_section_data (sec)->indirect_relocs = reloc_sec;
+     }
+ 
+   return reloc_sec;
+ }
Index: bfd/syms.c
===================================================================
RCS file: /cvs/src/src/bfd/syms.c,v
retrieving revision 1.47
diff -c -3 -p -r1.47 syms.c
*** bfd/syms.c	30 Jun 2008 20:51:58 -0000	1.47
--- bfd/syms.c	3 Dec 2008 08:01:49 -0000
*************** CODE_FRAGMENT
*** 205,304 ****
  .  symvalue value;
  .
  .  {* Attributes of a symbol.  *}
! .#define BSF_NO_FLAGS    0x00
  .
  .  {* The symbol has local scope; <<static>> in <<C>>. The value
  .     is the offset into the section of the data.  *}
! .#define BSF_LOCAL	0x01
  .
  .  {* The symbol has global scope; initialized data in <<C>>. The
  .     value is the offset into the section of the data.  *}
! .#define BSF_GLOBAL	0x02
  .
  .  {* The symbol has global scope and is exported. The value is
  .     the offset into the section of the data.  *}
  .#define BSF_EXPORT	BSF_GLOBAL {* No real difference.  *}
  .
  .  {* A normal C symbol would be one of:
! .     <<BSF_LOCAL>>, <<BSF_FORT_COMM>>,  <<BSF_UNDEFINED>> or
  .     <<BSF_GLOBAL>>.  *}
  .
  .  {* The symbol is a debugging record. The value has an arbitrary
  .     meaning, unless BSF_DEBUGGING_RELOC is also set.  *}
! .#define BSF_DEBUGGING	0x08
  .
  .  {* The symbol denotes a function entry point.  Used in ELF,
  .     perhaps others someday.  *}
! .#define BSF_FUNCTION    0x10
  .
  .  {* Used by the linker.  *}
! .#define BSF_KEEP        0x20
! .#define BSF_KEEP_G      0x40
  .
  .  {* A weak global symbol, overridable without warnings by
  .     a regular global symbol of the same name.  *}
! .#define BSF_WEAK        0x80
  .
  .  {* This symbol was created to point to a section, e.g. ELF's
  .     STT_SECTION symbols.  *}
! .#define BSF_SECTION_SYM 0x100
  .
  .  {* The symbol used to be a common symbol, but now it is
  .     allocated.  *}
! .#define BSF_OLD_COMMON  0x200
! .
! .  {* The default value for common data.  *}
! .#define BFD_FORT_COMM_DEFAULT_VALUE 0
  .
  .  {* In some files the type of a symbol sometimes alters its
  .     location in an output file - ie in coff a <<ISFCN>> symbol
  .     which is also <<C_EXT>> symbol appears where it was
  .     declared and not at the end of a section.  This bit is set
  .     by the target BFD part to convey this information.  *}
! .#define BSF_NOT_AT_END    0x400
  .
  .  {* Signal that the symbol is the label of constructor section.  *}
! .#define BSF_CONSTRUCTOR   0x800
  .
  .  {* Signal that the symbol is a warning symbol.  The name is a
  .     warning.  The name of the next symbol is the one to warn about;
  .     if a reference is made to a symbol with the same name as the next
  .     symbol, a warning is issued by the linker.  *}
! .#define BSF_WARNING       0x1000
  .
  .  {* Signal that the symbol is indirect.  This symbol is an indirect
  .     pointer to the symbol with the same name as the next symbol.  *}
! .#define BSF_INDIRECT      0x2000
  .
  .  {* BSF_FILE marks symbols that contain a file name.  This is used
  .     for ELF STT_FILE symbols.  *}
! .#define BSF_FILE          0x4000
  .
  .  {* Symbol is from dynamic linking information.  *}
! .#define BSF_DYNAMIC	   0x8000
  .
  .  {* The symbol denotes a data object.  Used in ELF, and perhaps
  .     others someday.  *}
! .#define BSF_OBJECT	   0x10000
  .
  .  {* This symbol is a debugging symbol.  The value is the offset
  .     into the section of the data.  BSF_DEBUGGING should be set
  .     as well.  *}
! .#define BSF_DEBUGGING_RELOC 0x20000
  .
  .  {* This symbol is thread local.  Used in ELF.  *}
! .#define BSF_THREAD_LOCAL  0x40000
  .
  .  {* This symbol represents a complex relocation expression,
  .     with the expression tree serialized in the symbol name.  *}
! .#define BSF_RELC 0x80000
  .
  .  {* This symbol represents a signed complex relocation expression,
  .     with the expression tree serialized in the symbol name.  *}
! .#define BSF_SRELC 0x100000
  .
  .  {* This symbol was created by bfd_get_synthetic_symtab.  *}
! .#define BSF_SYNTHETIC 0x200000
  .
  .  flagword flags;
  .
--- 205,308 ----
  .  symvalue value;
  .
  .  {* Attributes of a symbol.  *}
! .#define BSF_NO_FLAGS    	0x00
  .
  .  {* The symbol has local scope; <<static>> in <<C>>. The value
  .     is the offset into the section of the data.  *}
! .#define BSF_LOCAL		(1 << 0)
  .
  .  {* The symbol has global scope; initialized data in <<C>>. The
  .     value is the offset into the section of the data.  *}
! .#define BSF_GLOBAL		(1 << 1)
  .
  .  {* The symbol has global scope and is exported. The value is
  .     the offset into the section of the data.  *}
  .#define BSF_EXPORT	BSF_GLOBAL {* No real difference.  *}
  .
  .  {* A normal C symbol would be one of:
! .     <<BSF_LOCAL>>, <<BSF_COMMON>>,  <<BSF_UNDEFINED>> or
  .     <<BSF_GLOBAL>>.  *}
  .
  .  {* The symbol is a debugging record. The value has an arbitrary
  .     meaning, unless BSF_DEBUGGING_RELOC is also set.  *}
! .#define BSF_DEBUGGING		(1 << 2)
  .
  .  {* The symbol denotes a function entry point.  Used in ELF,
  .     perhaps others someday.  *}
! .#define BSF_FUNCTION		(1 << 3)
  .
+ .  {* The symbol is an indirect code object.  Unrelated to BSF_INDIRECT.
+ .     Relocations against a symbol with this flag have to evaluated at
+ .     run-time, where the function pointed to by this symbol is invoked
+ .     in order to determine the value to be used in the relocation.
+ .     BSF_FUNCTION must also be set for symbols with this flag.  *}
+ .#define BSF_INDIRECT_FUNCTION	(1 << 4)
+ . 
  .  {* Used by the linker.  *}
! .#define BSF_KEEP		(1 << 5)
! .#define BSF_KEEP_G		(1 << 6)
  .
  .  {* A weak global symbol, overridable without warnings by
  .     a regular global symbol of the same name.  *}
! .#define BSF_WEAK		(1 << 7)
  .
  .  {* This symbol was created to point to a section, e.g. ELF's
  .     STT_SECTION symbols.  *}
! .#define BSF_SECTION_SYM	(1 << 8)
  .
  .  {* The symbol used to be a common symbol, but now it is
  .     allocated.  *}
! .#define BSF_OLD_COMMON		(1 << 9)
  .
  .  {* In some files the type of a symbol sometimes alters its
  .     location in an output file - ie in coff a <<ISFCN>> symbol
  .     which is also <<C_EXT>> symbol appears where it was
  .     declared and not at the end of a section.  This bit is set
  .     by the target BFD part to convey this information.  *}
! .#define BSF_NOT_AT_END		(1 << 10)
  .
  .  {* Signal that the symbol is the label of constructor section.  *}
! .#define BSF_CONSTRUCTOR	(1 << 11)
  .
  .  {* Signal that the symbol is a warning symbol.  The name is a
  .     warning.  The name of the next symbol is the one to warn about;
  .     if a reference is made to a symbol with the same name as the next
  .     symbol, a warning is issued by the linker.  *}
! .#define BSF_WARNING		(1 << 12)
  .
  .  {* Signal that the symbol is indirect.  This symbol is an indirect
  .     pointer to the symbol with the same name as the next symbol.  *}
! .#define BSF_INDIRECT		(1 << 13)
  .
  .  {* BSF_FILE marks symbols that contain a file name.  This is used
  .     for ELF STT_FILE symbols.  *}
! .#define BSF_FILE		(1 << 14)
  .
  .  {* Symbol is from dynamic linking information.  *}
! .#define BSF_DYNAMIC		(1 << 15)
  .
  .  {* The symbol denotes a data object.  Used in ELF, and perhaps
  .     others someday.  *}
! .#define BSF_OBJECT		(1 << 16)
  .
  .  {* This symbol is a debugging symbol.  The value is the offset
  .     into the section of the data.  BSF_DEBUGGING should be set
  .     as well.  *}
! .#define BSF_DEBUGGING_RELOC	(1 << 17)
  .
  .  {* This symbol is thread local.  Used in ELF.  *}
! .#define BSF_THREAD_LOCAL	(1 << 18)
  .
  .  {* This symbol represents a complex relocation expression,
  .     with the expression tree serialized in the symbol name.  *}
! .#define BSF_RELC		(1 << 19)
  .
  .  {* This symbol represents a signed complex relocation expression,
  .     with the expression tree serialized in the symbol name.  *}
! .#define BSF_SRELC		(1 << 20)
  .
  .  {* This symbol was created by bfd_get_synthetic_symtab.  *}
! .#define BSF_SYNTHETIC		(1 << 21)
  .
  .  flagword flags;
  .
*************** bfd_print_symbol_vandf (bfd *abfd, void 
*** 486,492 ****
  	   (type & BSF_WEAK) ? 'w' : ' ',
  	   (type & BSF_CONSTRUCTOR) ? 'C' : ' ',
  	   (type & BSF_WARNING) ? 'W' : ' ',
! 	   (type & BSF_INDIRECT) ? 'I' : ' ',
  	   (type & BSF_DEBUGGING) ? 'd' : (type & BSF_DYNAMIC) ? 'D' : ' ',
  	   ((type & BSF_FUNCTION)
  	    ? 'F'
--- 490,496 ----
  	   (type & BSF_WEAK) ? 'w' : ' ',
  	   (type & BSF_CONSTRUCTOR) ? 'C' : ' ',
  	   (type & BSF_WARNING) ? 'W' : ' ',
! 	   (type & BSF_INDIRECT) ? 'I' : (type & BSF_INDIRECT_FUNCTION) ? 'i' : ' ',
  	   (type & BSF_DEBUGGING) ? 'd' : (type & BSF_DYNAMIC) ? 'D' : ' ',
  	   ((type & BSF_FUNCTION)
  	    ? 'F'
*************** bfd_decode_symclass (asymbol *symbol)
*** 672,677 ****
--- 676,683 ----
      }
    if (bfd_is_ind_section (symbol->section))
      return 'I';
+   if (symbol->flags & BSF_INDIRECT_FUNCTION)
+     return 'i';
    if (symbol->flags & BSF_WEAK)
      {
        /* If weak, determine if it's specifically an object
Index: gas/NEWS
===================================================================
RCS file: /cvs/src/src/gas/NEWS,v
retrieving revision 1.99
diff -c -3 -p -r1.99 NEWS
*** gas/NEWS	28 Sep 2008 15:15:32 -0000	1.99
--- gas/NEWS	3 Dec 2008 08:01:49 -0000
***************
*** 1,5 ****
--- 1,10 ----
  -*- text -*-
  
+ * The .type pseudo-op now accepts a type of STT_IFUNC which can be used to
+   indicate that if the symbol is the target of a relocation, its value should
+   not be used.  Instead the function should be invoked and its result used as
+   the value.
+  
  Changes in 2.19:
  
  * New pseudo op .cfi_val_encoded_addr, to record constant addresses in unwind
Index: gas/config/obj-elf.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-elf.c,v
retrieving revision 1.109
diff -c -3 -p -r1.109 obj-elf.c
*** gas/config/obj-elf.c	23 Apr 2008 13:54:56 -0000	1.109
--- gas/config/obj-elf.c	3 Dec 2008 08:01:50 -0000
*************** obj_elf_type (int ignore ATTRIBUTE_UNUSE
*** 1663,1668 ****
--- 1663,1682 ----
  	    }
  	}
      }
+   else if (strcmp (typename, "indirect_function") == 0
+       || strcmp (typename, "10") == 0
+       || strcmp (typename, "STT_IFUNC") == 0)
+     {
+       const struct elf_backend_data *bed;
+ 
+       bed = get_elf_backend_data (stdoutput);
+       if (!(bed->elf_osabi == ELFOSABI_LINUX
+ 	    /* GNU/Linux is still using the default value 0.  */
+ 	    || bed->elf_osabi == ELFOSABI_NONE))
+ 	as_bad (_("symbol type \"%s\" is supported only by GNU targets"),
+ 		typename);
+       type = BSF_FUNCTION | BSF_INDIRECT_FUNCTION;
+     }
  #ifdef md_elf_symbol_type
    else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
      ;
Index: gas/doc/as.texinfo
===================================================================
RCS file: /cvs/src/src/gas/doc/as.texinfo,v
retrieving revision 1.190
diff -c -3 -p -r1.190 as.texinfo
*** gas/doc/as.texinfo	19 Nov 2008 16:22:47 -0000	1.190
--- gas/doc/as.texinfo	3 Dec 2008 08:01:53 -0000
*************** The syntaxes supported are:
*** 6267,6273 ****
    .type <name> STT_<TYPE_IN_UPPER_CASE>
    .type <name>,#<type>
    .type <name>,@@<type>
!   .type <name>,%>type>
    .type <name>,"<type>"
  @end smallexample
  
--- 6267,6273 ----
    .type <name> STT_<TYPE_IN_UPPER_CASE>
    .type <name>,#<type>
    .type <name>,@@<type>
!   .type <name>,%<type>
    .type <name>,"<type>"
  @end smallexample
  
*************** Mark the symbol as being a thead-local d
*** 6289,6294 ****
--- 6289,6303 ----
  @item STT_COMMON
  @itemx common
  Mark the symbol as being a common data object.
+ 
+ @item STT_NOTYPE
+ @itemx notype
+ Does not mark the symbol in any way.  It is supported just for completeness.
+ 
+ @item STT_IFUNC
+ @itemx indirect_function
+ Mark the symbol as an indirect function when evaluated during reloc
+ processing.  (This is only supported on Linux targeted assemblers).
  @end table
  
  Note: Some targets support extra types in addition to those listed above.
Index: gas/testsuite/gas/elf/elf.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/elf/elf.exp,v
retrieving revision 1.47
diff -c -3 -p -r1.47 elf.exp
*** gas/testsuite/gas/elf/elf.exp	15 Sep 2008 13:53:47 -0000	1.47
--- gas/testsuite/gas/elf/elf.exp	3 Dec 2008 08:01:53 -0000
*************** if { ([istarget "*-*-*elf*"]		
*** 114,120 ****
      run_elf_list_test "section5" "" "-al" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\""
      run_dump_test "struct" 
      run_dump_test "symver" 
!     run_elf_list_test "type" "" "" "-s" "| grep \"1 \\\[FONTC\\\]\""
      run_dump_test "section6" 
      run_dump_test "section7" 
  }
--- 114,120 ----
      run_elf_list_test "section5" "" "-al" "-SW" "| grep \" \\\\.test\\\[0-9\\\]\""
      run_dump_test "struct" 
      run_dump_test "symver" 
!     run_elf_list_test "type" "" "" "-s" "| grep \"1 \\\[FIONTC\\\]\""
      run_dump_test "section6" 
      run_dump_test "section7" 
  }
Index: gas/testsuite/gas/elf/type.e
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/elf/type.e,v
retrieving revision 1.3
diff -c -3 -p -r1.3 type.e
*** gas/testsuite/gas/elf/type.e	16 Oct 2007 14:42:15 -0000	1.3
--- gas/testsuite/gas/elf/type.e	3 Dec 2008 08:01:53 -0000
***************
*** 1,4 ****
--- 1,5 ----
       .: 0+0     1 FUNC    LOCAL  DEFAULT    . function
+      .: 0+1     1 IFUNC   LOCAL  DEFAULT    . indirect_function
       .: 0+0     1 OBJECT  LOCAL  DEFAULT    . object
       .: 0+1     1 TLS     LOCAL  DEFAULT    . tls_object
       .: 0+2     1 NOTYPE  LOCAL  DEFAULT    . notype
Index: gas/testsuite/gas/elf/type.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/elf/type.s,v
retrieving revision 1.3
diff -c -3 -p -r1.3 type.s
*** gas/testsuite/gas/elf/type.s	16 Oct 2007 14:42:15 -0000	1.3
--- gas/testsuite/gas/elf/type.s	3 Dec 2008 08:01:53 -0000
***************
*** 3,8 ****
--- 3,12 ----
          .type   function,%function
  function:
  	.byte	0x0
+         .size   indirect_function,1
+         .type   indirect_function,%indirect_function
+ indirect_function:
+ 	.byte	0x0
          .data
          .type   object,%object
          .size   object,1
Index: ld/NEWS
===================================================================
RCS file: /cvs/src/src/ld/NEWS,v
retrieving revision 1.89
diff -c -3 -p -r1.89 NEWS
*** ld/NEWS	27 Nov 2008 12:41:14 -0000	1.89
--- ld/NEWS	3 Dec 2008 08:01:54 -0000
***************
*** 1,4 ****
--- 1,7 ----
  -*- text -*-
+ * For GNU/Linux systems the linker will now forego processing any relocations
+   made against symbols of the STT_IFUNC type and instead emit them into
+   the resulting binary for processing by the loader.
  
  * Add CR16 ELF --embedded-relocs (used to embedded relocations into binaries 
    for Embedded-PIC code) option.
Index: ld/pe-dll.c
===================================================================
RCS file: /cvs/src/src/ld/pe-dll.c,v
retrieving revision 1.111
diff -c -3 -p -r1.111 pe-dll.c
*** ld/pe-dll.c	2 Dec 2008 09:33:12 -0000	1.111
--- ld/pe-dll.c	3 Dec 2008 08:01:54 -0000
*************** process_def_file (bfd *abfd ATTRIBUTE_UN
*** 633,639 ****
  		 We should not export undefined symbols.  */
  	      if (symbols[j]->section != &bfd_und_section
  		  && ((symbols[j]->flags & BSF_GLOBAL)
! 		      || (symbols[j]->flags == BFD_FORT_COMM_DEFAULT_VALUE)))
  		{
  		  const char *sn = symbols[j]->name;
  
--- 633,639 ----
  		 We should not export undefined symbols.  */
  	      if (symbols[j]->section != &bfd_und_section
  		  && ((symbols[j]->flags & BSF_GLOBAL)
! 		      || (symbols[j]->flags == 0)))
  		{
  		  const char *sn = symbols[j]->name;
  
Index: ld/scripttempl/elf.sc
===================================================================
RCS file: /cvs/src/src/ld/scripttempl/elf.sc,v
retrieving revision 1.86
diff -c -3 -p -r1.86 elf.sc
*** ld/scripttempl/elf.sc	22 Oct 2008 05:20:44 -0000	1.86
--- ld/scripttempl/elf.sc	3 Dec 2008 08:01:55 -0000
*************** EOF
*** 333,344 ****
--- 333,352 ----
  sed -e '/^[ 	]*[{}][ 	]*$/d;/:[ 	]*$/d;/\.rela\./d;s/^.*: { *\(.*\)}$/      \1/' $COMBRELOC >> ldscripts/dyntmp.$$
  cat >> ldscripts/dyntmp.$$ <<EOF
      }
+   .rel.ifunc.dyn      ${RELOCATING-0} :
+     {
+       *(.rel.ifunc.*)
+     }
    .rela.dyn     ${RELOCATING-0} :
      {
  EOF
  sed -e '/^[ 	]*[{}][ 	]*$/d;/:[ 	]*$/d;/\.rel\./d;s/^.*: { *\(.*\)}/      \1/' $COMBRELOC >> ldscripts/dyntmp.$$
  cat >> ldscripts/dyntmp.$$ <<EOF
      }
+   .rela.ifunc.dyn     ${RELOCATING-0} :
+     {
+       *(.rela.ifunc.*)
+     }
  EOF
  fi
  
Index: ld/testsuite/ld-mips-elf/reloc-1-n32.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-mips-elf/reloc-1-n32.d,v
retrieving revision 1.1
diff -c -3 -p -r1.1 reloc-1-n32.d
*** ld/testsuite/ld-mips-elf/reloc-1-n32.d	18 Dec 2003 10:25:12 -0000	1.1
--- ld/testsuite/ld-mips-elf/reloc-1-n32.d	3 Dec 2008 08:01:55 -0000
*************** Relocation section '\.rela\.text' .*
*** 8,17 ****
  #
  # Relocations against tstarta
  #
! .* R_MIPS_HI16 .* \.text \+ ffff7ff0
! .* R_MIPS_LO16 .* \.text \+ ffff7ff0
! .* R_MIPS_HI16 .* \.text \+ ffff8000
! .* R_MIPS_LO16 .* \.text \+ ffff8000
  .* R_MIPS_HI16 .* \.text \+ 0
  .* R_MIPS_LO16 .* \.text \+ 0
  .* R_MIPS_HI16 .* \.text \+ 7ff0
--- 8,17 ----
  #
  # Relocations against tstarta
  #
! .* R_MIPS_HI16 .* \.text \- 8010
! .* R_MIPS_LO16 .* \.text \- 8010
! .* R_MIPS_HI16 .* \.text \- 8000
! .* R_MIPS_LO16 .* \.text \- 8000
  .* R_MIPS_HI16 .* \.text \+ 0
  .* R_MIPS_LO16 .* \.text \+ 0
  .* R_MIPS_HI16 .* \.text \+ 7ff0
*************** Relocation section '\.rela\.text' .*
*** 21,30 ****
  #
  # Relocations against t32a
  #
! .* R_MIPS_HI16 .* \.text \+ ffff8010
! .* R_MIPS_LO16 .* \.text \+ ffff8010
! .* R_MIPS_HI16 .* \.text \+ ffff8020
! .* R_MIPS_LO16 .* \.text \+ ffff8020
  .* R_MIPS_HI16 .* \.text \+ 20
  .* R_MIPS_LO16 .* \.text \+ 20
  .* R_MIPS_HI16 .* \.text \+ 8010
--- 21,30 ----
  #
  # Relocations against t32a
  #
! .* R_MIPS_HI16 .* \.text \- 7ff0
! .* R_MIPS_LO16 .* \.text \- 7ff0
! .* R_MIPS_HI16 .* \.text \- 7fe0
! .* R_MIPS_LO16 .* \.text \- 7fe0
  .* R_MIPS_HI16 .* \.text \+ 20
  .* R_MIPS_LO16 .* \.text \+ 20
  .* R_MIPS_HI16 .* \.text \+ 8010
*************** Relocation section '\.rela\.text' .*
*** 34,43 ****
  #
  # Relocations against _start
  #
! .* R_MIPS_HI16 .* _start \+ ffff7ff0
! .* R_MIPS_LO16 .* _start \+ ffff7ff0
! .* R_MIPS_HI16 .* _start \+ ffff8000
! .* R_MIPS_LO16 .* _start \+ ffff8000
  .* R_MIPS_HI16 .* _start \+ 0
  .* R_MIPS_LO16 .* _start \+ 0
  .* R_MIPS_HI16 .* _start \+ 7ff0
--- 34,43 ----
  #
  # Relocations against _start
  #
! .* R_MIPS_HI16 .* _start \- 8010
! .* R_MIPS_LO16 .* _start \- 8010
! .* R_MIPS_HI16 .* _start \- 8000
! .* R_MIPS_LO16 .* _start \- 8000
  .* R_MIPS_HI16 .* _start \+ 0
  .* R_MIPS_LO16 .* _start \+ 0
  .* R_MIPS_HI16 .* _start \+ 7ff0
*************** Relocation section '\.rela\.text' .*
*** 47,56 ****
  #
  # Relocations against tstarta
  #
! .* R_MIPS_GOT16 .* \.text \+ ffff7ff0
! .* R_MIPS_LO16 .* \.text \+ ffff7ff0
! .* R_MIPS_GOT16 .* \.text \+ ffff8000
! .* R_MIPS_LO16 .* \.text \+ ffff8000
  .* R_MIPS_GOT16 .* \.text \+ 0
  .* R_MIPS_LO16 .* \.text \+ 0
  .* R_MIPS_GOT16 .* \.text \+ 7ff0
--- 47,56 ----
  #
  # Relocations against tstarta
  #
! .* R_MIPS_GOT16 .* \.text \- 8010
! .* R_MIPS_LO16 .* \.text \- 8010
! .* R_MIPS_GOT16 .* \.text \- 8000
! .* R_MIPS_LO16 .* \.text \- 8000
  .* R_MIPS_GOT16 .* \.text \+ 0
  .* R_MIPS_LO16 .* \.text \+ 0
  .* R_MIPS_GOT16 .* \.text \+ 7ff0
*************** Relocation section '\.rela\.text' .*
*** 60,69 ****
  #
  # Relocations against t32a
  #
! .* R_MIPS_GOT16 .* \.text \+ ffff8010
! .* R_MIPS_LO16 .* \.text \+ ffff8010
! .* R_MIPS_GOT16 .* \.text \+ ffff8020
! .* R_MIPS_LO16 .* \.text \+ ffff8020
  .* R_MIPS_GOT16 .* \.text \+ 20
  .* R_MIPS_LO16 .* \.text \+ 20
  .* R_MIPS_GOT16 .* \.text \+ 8010
--- 60,69 ----
  #
  # Relocations against t32a
  #
! .* R_MIPS_GOT16 .* \.text \- 7ff0
! .* R_MIPS_LO16 .* \.text \- 7ff0
! .* R_MIPS_GOT16 .* \.text \- 7fe0
! .* R_MIPS_LO16 .* \.text \- 7fe0
  .* R_MIPS_GOT16 .* \.text \+ 20
  .* R_MIPS_LO16 .* \.text \+ 20
  .* R_MIPS_GOT16 .* \.text \+ 8010
*************** Relocation section '\.rela\.text' .*
*** 73,92 ****
  #
  # Relocations against sdg
  #
! .* R_MIPS_GPREL16 .* sdg \+ fffffffc
  .* R_MIPS_GPREL16 .* sdg \+ 0
  .* R_MIPS_GPREL16 .* sdg \+ 4
  #
  # Relocations against sdla.  .sdata should be the first piece of gp-relative
  # data, which the linker script should put _gp - 0x7ff0.
  #
! .* R_MIPS_GPREL16 .* \.sdata \+ ffff801c
! .* R_MIPS_GPREL16 .* \.sdata \+ ffff8020
! .* R_MIPS_GPREL16 .* \.sdata \+ ffff8024
  #
  # Relocations against tstarta
  #
! .* R_MIPS_26 .* \.text \+ fffffffc
  .* R_MIPS_26 .* \.text \+ 0
  .* R_MIPS_26 .* \.text \+ 4
  #
--- 73,92 ----
  #
  # Relocations against sdg
  #
! .* R_MIPS_GPREL16 .* sdg \- 4
  .* R_MIPS_GPREL16 .* sdg \+ 0
  .* R_MIPS_GPREL16 .* sdg \+ 4
  #
  # Relocations against sdla.  .sdata should be the first piece of gp-relative
  # data, which the linker script should put _gp - 0x7ff0.
  #
! .* R_MIPS_GPREL16 .* \.sdata \- 7fe4
! .* R_MIPS_GPREL16 .* \.sdata \- 7fe0
! .* R_MIPS_GPREL16 .* \.sdata \- 7fdc
  #
  # Relocations against tstarta
  #
! .* R_MIPS_26 .* \.text \- 4
  .* R_MIPS_26 .* \.text \+ 0
  .* R_MIPS_26 .* \.text \+ 4
  #
*************** Relocation section '\.rela\.text' .*
*** 98,104 ****
  #
  # Relocations against _start
  #
! .* R_MIPS_26 .* _start \+ fffffffc
  .* R_MIPS_26 .* _start \+ 0
  .* R_MIPS_26 .* _start \+ 4
  #
--- 98,104 ----
  #
  # Relocations against _start
  #
! .* R_MIPS_26 .* _start \- 4
  .* R_MIPS_26 .* _start \+ 0
  .* R_MIPS_26 .* _start \+ 4
  #
*************** Relocation section '\.rela\.text' .*
*** 130,139 ****
  #
  # Relocations against _start
  #
! .* R_MIPS_HI16 .* _start \+ ffff7ff0
! .* R_MIPS_LO16 .* _start \+ ffff7ff0
! .* R_MIPS_HI16 .* _start \+ ffff8000
! .* R_MIPS_LO16 .* _start \+ ffff8000
  .* R_MIPS_HI16 .* _start \+ 0
  .* R_MIPS_LO16 .* _start \+ 0
  .* R_MIPS_HI16 .* _start \+ 7ff0
--- 130,139 ----
  #
  # Relocations against _start
  #
! .* R_MIPS_HI16 .* _start \- 8010
! .* R_MIPS_LO16 .* _start \- 8010
! .* R_MIPS_HI16 .* _start \- 8000
! .* R_MIPS_LO16 .* _start \- 8000
  .* R_MIPS_HI16 .* _start \+ 0
  .* R_MIPS_LO16 .* _start \+ 0
  .* R_MIPS_HI16 .* _start \+ 7ff0
*************** Relocation section '\.rela\.text' .*
*** 169,183 ****
  #
  # Relocations against sdg
  #
! .* R_MIPS_GPREL16 .* sdg \+ fffffffc
  .* R_MIPS_GPREL16 .* sdg \+ 0
  .* R_MIPS_GPREL16 .* sdg \+ 4
  #
  # Relocations against sdlb
  #
! .* R_MIPS_GPREL16 .* \.sdata \+ ffff803c
! .* R_MIPS_GPREL16 .* \.sdata \+ ffff8040
! .* R_MIPS_GPREL16 .* \.sdata \+ ffff8044
  #
  # Relocations against tstartb
  #
--- 169,183 ----
  #
  # Relocations against sdg
  #
! .* R_MIPS_GPREL16 .* sdg \- 4
  .* R_MIPS_GPREL16 .* sdg \+ 0
  .* R_MIPS_GPREL16 .* sdg \+ 4
  #
  # Relocations against sdlb
  #
! .* R_MIPS_GPREL16 .* \.sdata \- 7fc4
! .* R_MIPS_GPREL16 .* \.sdata \- 7fc0
! .* R_MIPS_GPREL16 .* \.sdata \- 7fbc
  #
  # Relocations against tstartb
  #
*************** Relocation section '\.rela\.text' .*
*** 193,199 ****
  #
  # Relocations against _start
  #
! .* R_MIPS_26 .* _start \+ fffffffc
  .* R_MIPS_26 .* _start \+ 0
  .* R_MIPS_26 .* _start \+ 4
  #pass
--- 193,199 ----
  #
  # Relocations against _start
  #
! .* R_MIPS_26 .* _start \- 4
  .* R_MIPS_26 .* _start \+ 0
  .* R_MIPS_26 .* _start \+ 4
  #pass
Index: ld/testsuite/ld-mips-elf/reloc-1-n64.d
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-mips-elf/reloc-1-n64.d,v
retrieving revision 1.2
diff -c -3 -p -r1.2 reloc-1-n64.d
*** ld/testsuite/ld-mips-elf/reloc-1-n64.d	18 Oct 2006 13:02:01 -0000	1.2
--- ld/testsuite/ld-mips-elf/reloc-1-n64.d	3 Dec 2008 08:01:55 -0000
*************** Relocation section '\.rela\.text' .*
*** 8,23 ****
  #
  # Relocations against tstarta
  #
! .* R_MIPS_HI16 .* \.text \+ f+7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \+ f+7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_HI16 .* \.text \+ f+8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \+ f+8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_HI16 .* \.text \+ 0
--- 8,23 ----
  #
  # Relocations against tstarta
  #
! .* R_MIPS_HI16 .* \.text \- 8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \- 8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_HI16 .* \.text \- 8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \- 8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_HI16 .* \.text \+ 0
*************** Relocation section '\.rela\.text' .*
*** 41,56 ****
  #
  # Relocations against t32a
  #
! .* R_MIPS_HI16 .* \.text \+ f+8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \+ f+8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_HI16 .* \.text \+ f+8020
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \+ f+8020
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_HI16 .* \.text \+ 20
--- 41,56 ----
  #
  # Relocations against t32a
  #
! .* R_MIPS_HI16 .* \.text \- 7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \- 7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_HI16 .* \.text \- 7fe0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \- 7fe0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_HI16 .* \.text \+ 20
*************** Relocation section '\.rela\.text' .*
*** 74,89 ****
  #
  # Relocations against _start
  #
! .* R_MIPS_HI16 .* _start \+ f+7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* _start \+ f+7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_HI16 .* _start \+ f+8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* _start \+ f+8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_HI16 .* _start \+ 0
--- 74,89 ----
  #
  # Relocations against _start
  #
! .* R_MIPS_HI16 .* _start \- 8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* _start \- 8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_HI16 .* _start \- 8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* _start \- 8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_HI16 .* _start \+ 0
*************** Relocation section '\.rela\.text' .*
*** 107,122 ****
  #
  # Relocations against tstarta
  #
! .* R_MIPS_GOT16 .* \.text \+ f+7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \+ f+7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GOT16 .* \.text \+ f+8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \+ f+8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_GOT16 .* \.text \+ 0
--- 107,122 ----
  #
  # Relocations against tstarta
  #
! .* R_MIPS_GOT16 .* \.text \- 8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \- 8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GOT16 .* \.text \- 8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \- 8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_GOT16 .* \.text \+ 0
*************** Relocation section '\.rela\.text' .*
*** 140,155 ****
  #
  # Relocations against t32a
  #
! .* R_MIPS_GOT16 .* \.text \+ f+8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \+ f+8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GOT16 .* \.text \+ f+8020
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \+ f+8020
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_GOT16 .* \.text \+ 20
--- 140,155 ----
  #
  # Relocations against t32a
  #
! .* R_MIPS_GOT16 .* \.text \- 7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \- 7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GOT16 .* \.text \- 7fe0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* \.text \- 7fe0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_GOT16 .* \.text \+ 20
*************** Relocation section '\.rela\.text' .*
*** 173,179 ****
  #
  # Relocations against sdg
  #
! .* R_MIPS_GPREL16 .* sdg \+ f+fffc
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_GPREL16 .* sdg \+ 0
--- 173,179 ----
  #
  # Relocations against sdg
  #
! .* R_MIPS_GPREL16 .* sdg \- 4
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_GPREL16 .* sdg \+ 0
*************** Relocation section '\.rela\.text' .*
*** 186,204 ****
  # Relocations against sdla.  .sdata should be the first piece of gp-relative
  # data, which the linker script should put _gp - 0x7ff0.
  #
! .* R_MIPS_GPREL16 .* \.sdata \+ f+801c
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GPREL16 .* \.sdata \+ f+8020
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GPREL16 .* \.sdata \+ f+8024
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  #
  # Relocations against tstarta
  #
! .* R_MIPS_26 .* \.text \+ f+fffc
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_26 .* \.text \+ 0
--- 186,204 ----
  # Relocations against sdla.  .sdata should be the first piece of gp-relative
  # data, which the linker script should put _gp - 0x7ff0.
  #
! .* R_MIPS_GPREL16 .* \.sdata \- 7fe4
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GPREL16 .* \.sdata \- 7fe0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GPREL16 .* \.sdata \- 7fdc
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  #
  # Relocations against tstarta
  #
! .* R_MIPS_26 .* \.text \- 4
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_26 .* \.text \+ 0
*************** Relocation section '\.rela\.text' .*
*** 222,228 ****
  #
  # Relocations against _start
  #
! .* R_MIPS_26 .* _start \+ f+fffc
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_26 .* _start \+ 0
--- 222,228 ----
  #
  # Relocations against _start
  #
! .* R_MIPS_26 .* _start \- 4
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_26 .* _start \+ 0
*************** Relocation section '\.rela\.text' .*
*** 300,315 ****
  #
  # Relocations against _start
  #
! .* R_MIPS_HI16 .* _start \+ f+7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* _start \+ f+7ff0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_HI16 .* _start \+ f+8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* _start \+ f+8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_HI16 .* _start \+ 0
--- 300,315 ----
  #
  # Relocations against _start
  #
! .* R_MIPS_HI16 .* _start \- 8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* _start \- 8010
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_HI16 .* _start \- 8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_LO16 .* _start \- 8000
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_HI16 .* _start \+ 0
*************** Relocation section '\.rela\.text' .*
*** 399,405 ****
  #
  # Relocations against sdg
  #
! .* R_MIPS_GPREL16 .* sdg \+ f+fffc
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_GPREL16 .* sdg \+ 0
--- 399,405 ----
  #
  # Relocations against sdg
  #
! .* R_MIPS_GPREL16 .* sdg \- 4
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_GPREL16 .* sdg \+ 0
*************** Relocation section '\.rela\.text' .*
*** 411,423 ****
  #
  # Relocations against sdlb
  #
! .* R_MIPS_GPREL16 .* \.sdata \+ f+803c
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GPREL16 .* \.sdata \+ f+8040
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GPREL16 .* \.sdata \+ f+8044
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  #
--- 411,423 ----
  #
  # Relocations against sdlb
  #
! .* R_MIPS_GPREL16 .* \.sdata \- 7fc4
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GPREL16 .* \.sdata \- 7fc0
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
! .* R_MIPS_GPREL16 .* \.sdata \- 7fbc
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  #
*************** Relocation section '\.rela\.text' .*
*** 447,453 ****
  #
  # Relocations against _start
  #
! .* R_MIPS_26 .* _start \+ f+fffc
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_26 .* _start \+ 0
--- 447,453 ----
  #
  # Relocations against _start
  #
! .* R_MIPS_26 .* _start \- 4
  .* R_MIPS_NONE *
  .* R_MIPS_NONE *
  .* R_MIPS_26 .* _start \+ 0

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]