PATCH: PR ld/: IFUNC gas problem

H.J. Lu hjl.tools@gmail.com
Sun Jun 14 02:31:00 GMT 2009


On Sat, Jun 13, 2009 at 1:10 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Jun 12, 2009 at 11:01 PM, Ulrich Drepper <drepper@redhat.com> wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Jakub Jelinek wrote:
>>> On the attached ifunctest.c gcc -O2 -o ifunctest{,.c} compiles/links, but
>>> no R_*_IRELATIVE relocation is emitted and not surprisingly it crashes
>>> at runtime.  Prelink testsuite contains similar testcase, just using
>>> .globl or .globl/.hidden, instead of .local.  I'd say .local @gnu_indirect_function
>>> symbols should be supported as well.
>>
>> Indeed, there is no reason why .local symbols shouldn't be supported.
>
> Please try the enclosed patch and let me know if it works.  Thanks.
>

I am checking in this patch to enable local IFUNC symbols.

-- 
H.J.
---
bfd/

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

	PR ld/10269
	* elf32-i386.c: Include "objalloc.h" and "hashtab.h".
	(elf_i386_link_hash_table): Add loc_hash_table and
	loc_hash_memory.
	(elf_i386_local_hash): New.
	(elf_i386_local_htab_hash): Likewise.
	(elf_i386_local_htab_eq): Likewise.
	(elf_i386_get_local_sym_hash): Likewise.
	(elf_i386_link_hash_table_free): Likewise.
	(elf_i386_allocate_local_dynrelocs): Likewise.
	(elf_i386_finish_local_dynamic_symbol): Likewise.
	(bfd_elf64_bfd_link_hash_table_free): Likewise.
	(elf_i386_link_hash_table_create): Create loc_hash_table and
	loc_hash_memory.
	(elf_i386_check_relocs): Handle local STT_GNU_IFUNC symbols.
	(elf_i386_size_dynamic_sections): Likewise.
	(elf_i386_relocate_section): Likewise.
	(elf_i386_finish_dynamic_sections): Likewise.
	(elf_i386_finish_dynamic_symbol): Check _DYNAMIC only if sym
	isn't NULL.

	* elf64-x86-64.c: Include "objalloc.h" and "hashtab.h".
	(elf64_x86_64_link_hash_table): Add loc_hash_table and
	loc_hash_memory.
	(elf64_x86_64_local_hash): New.
	(elf64_x86_64_local_htab_hash): Likewise.
	(elf64_x86_64_local_htab_eq): Likewise.
	(elf64_x86_64_get_local_sym_hash): Likewise.
	(elf64_x86_64_link_hash_table_free): Likewise.
	(elf64_x86_64_allocate_local_dynrelocs): Likewise.
	(elf64_x86_64_finish_local_dynamic_symbol): Likewise.
	(bfd_elf64_bfd_link_hash_table_free): Likewise.
	(elf64_x86_64_link_hash_table_create): Create loc_hash_table
	and loc_hash_memory.
	(elf64_x86_64_check_relocs): Handle local STT_GNU_IFUNC
	symbols.
	(elf64_x86_64_size_dynamic_sections): Likewise.
	(elf64_x86_64_relocate_section): Likewise.
	(elf64_x86_64_finish_dynamic_sections): Likewise.
	(elf64_x86_64_finish_dynamic_symbol): Check _DYNAMIC only if
	sym isn't NULL.

gas/

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

	PR ld/10269
	* config/tc-i386.c (md_apply_fix): Use TC_FORCE_RELOCATION
	instead of generic_force_reloc.

	* config/tc-i386.h (TC_FORCE_RELOCATION): New.

ld/testsuite/

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

	PR ld/10269
	*: ld-ifunc/ifunc-1-local-x86.d: New.
	*: ld-ifunc/ifunc-1-local-x86.s: Likewise.
	*: ld-ifunc/ifunc-2-local-i386.d: Likewise.
	*: ld-ifunc/ifunc-2-local-i386.s: Likewise.
	*: ld-ifunc/ifunc-2-local-x86-64.d: Likewise.
	*: ld-ifunc/ifunc-2-local-x86-64.s: Likewise.
	*: ld-ifunc/ifunc-4-local-x86.d: Likewise.
	*: ld-ifunc/ifunc-4-local-x86.s: Likewise.
	*: ld-ifunc/ifunc-5-local-i386.s: Likewise.
	*: ld-ifunc/ifunc-5-local-x86-64.s: Likewise.
	*: ld-ifunc/ifunc-5a-local-i386.d: Likewise.
	*: ld-ifunc/ifunc-5a-local-x86-64.d: Likewise.
	*: ld-ifunc/ifunc-5b-local-i386.d: Likewise.
	*: ld-ifunc/ifunc-5b-local-x86-64.d: Likewise.
-------------- next part --------------
bfd/

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

	PR ld/10269
	* elf32-i386.c: Include "objalloc.h" and "hashtab.h".
	(elf_i386_link_hash_table): Add loc_hash_table and
	loc_hash_memory.
	(elf_i386_local_hash): New.
	(elf_i386_local_htab_hash): Likewise.
	(elf_i386_local_htab_eq): Likewise.
	(elf_i386_get_local_sym_hash): Likewise.
	(elf_i386_link_hash_table_free): Likewise.
	(elf_i386_allocate_local_dynrelocs): Likewise.
	(elf_i386_finish_local_dynamic_symbol): Likewise.
	(bfd_elf64_bfd_link_hash_table_free): Likewise.
	(elf_i386_link_hash_table_create): Create loc_hash_table and
	loc_hash_memory.
	(elf_i386_check_relocs): Handle local STT_GNU_IFUNC symbols.
	(elf_i386_size_dynamic_sections): Likewise.
	(elf_i386_relocate_section): Likewise.
	(elf_i386_finish_dynamic_sections): Likewise.
	(elf_i386_finish_dynamic_symbol): Check _DYNAMIC only if sym
	isn't NULL.

	* elf64-x86-64.c: Include "objalloc.h" and "hashtab.h".
	(elf64_x86_64_link_hash_table): Add loc_hash_table and
	loc_hash_memory.
	(elf64_x86_64_local_hash): New.
	(elf64_x86_64_local_htab_hash): Likewise.
	(elf64_x86_64_local_htab_eq): Likewise.
	(elf64_x86_64_get_local_sym_hash): Likewise.
	(elf64_x86_64_link_hash_table_free): Likewise.
	(elf64_x86_64_allocate_local_dynrelocs): Likewise.
	(elf64_x86_64_finish_local_dynamic_symbol): Likewise.
	(bfd_elf64_bfd_link_hash_table_free): Likewise.
	(elf64_x86_64_link_hash_table_create): Create loc_hash_table
	and loc_hash_memory.
	(elf64_x86_64_check_relocs): Handle local STT_GNU_IFUNC
	symbols.
	(elf64_x86_64_size_dynamic_sections): Likewise.
	(elf64_x86_64_relocate_section): Likewise.
	(elf64_x86_64_finish_dynamic_sections): Likewise.
	(elf64_x86_64_finish_dynamic_symbol): Check _DYNAMIC only if
	sym isn't NULL.

gas/

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

	PR ld/10269
	* config/tc-i386.c (md_apply_fix): Use TC_FORCE_RELOCATION
	instead of generic_force_reloc.

	* config/tc-i386.h (TC_FORCE_RELOCATION): New.

ld/testsuite/

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

	PR ld/10269
	*: ld-ifunc/ifunc-1-local-x86.d: New.
	*: ld-ifunc/ifunc-1-local-x86.s: Likewise.
	*: ld-ifunc/ifunc-2-local-i386.d: Likewise.
	*: ld-ifunc/ifunc-2-local-i386.s: Likewise.
	*: ld-ifunc/ifunc-2-local-x86-64.d: Likewise.
	*: ld-ifunc/ifunc-2-local-x86-64.s: Likewise.
	*: ld-ifunc/ifunc-4-local-x86.d: Likewise.
	*: ld-ifunc/ifunc-4-local-x86.s: Likewise.
	*: ld-ifunc/ifunc-5-local-i386.s: Likewise.
	*: ld-ifunc/ifunc-5-local-x86-64.s: Likewise.
	*: ld-ifunc/ifunc-5a-local-i386.d: Likewise.
	*: ld-ifunc/ifunc-5a-local-x86-64.d: Likewise.
	*: ld-ifunc/ifunc-5b-local-i386.d: Likewise.
	*: ld-ifunc/ifunc-5b-local-x86-64.d: Likewise.

Index: ld/testsuite/ChangeLog.ifunc
===================================================================
Index: ld/testsuite/ld-ifunc/ifunc-4-local-x86.s
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-4-local-x86.s	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-4-local-x86.s	(revision 6107)
@@ -0,0 +1,18 @@
+	.text
+	.type foo, %gnu_indirect_function
+	.type	foo, @function
+foo:
+	ret
+	.size	foo, .-foo
+	.type start,"function"
+	.global start
+start:
+	.type _start,"function"
+	.global _start
+_start:
+	.type __start,"function"
+	.global __start
+__start:
+	.type __start,"function"
+	call	foo
+	movl	$foo,%eax

Property changes on: ld/testsuite/ld-ifunc/ifunc-4-local-x86.s
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-5-local-i386.s
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-5-local-i386.s	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-5-local-i386.s	(revision 6107)
@@ -0,0 +1,22 @@
+	.text
+	.type foo, %gnu_indirect_function
+	.type	foo, @function
+foo:
+	ret
+	.size	foo, .-foo
+	.type start,"function"
+	.global start
+start:
+	.type _start,"function"
+	.global _start
+_start:
+	.type __start,"function"
+	.global __start
+__start:
+	.type __start,"function"
+	call	.L6
+.L6:
+	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-.L6], %ebx
+	call	foo@PLT
+	leal	foo@GOT(%ebx), %eax

Property changes on: ld/testsuite/ld-ifunc/ifunc-5-local-i386.s
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-5b-local-x86-64.d
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-5b-local-x86-64.d	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-5b-local-x86-64.d	(revision 6107)
@@ -0,0 +1,9 @@
+#source: ifunc-5-local-x86-64.s
+#as: --64
+#ld: -melf_x86_64 -shared -z nocombreloc
+#readelf: -r --wide
+#target: x86_64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*

Property changes on: ld/testsuite/ld-ifunc/ifunc-5b-local-x86-64.d
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-2-local-i386.d
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-2-local-i386.d	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-2-local-i386.d	(revision 6107)
@@ -0,0 +1,8 @@
+#ld: -m elf_i386 -shared
+#as: --32
+#objdump: -dw
+#target: x86_64-*-* i?86-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+call[ \t0-9a-f]+<\*ABS\*@plt>
+#pass

Property changes on: ld/testsuite/ld-ifunc/ifunc-2-local-i386.d
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-5a-local-i386.d
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-5a-local-i386.d	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-5a-local-i386.d	(revision 6107)
@@ -0,0 +1,9 @@
+#source: ifunc-5-local-i386.s
+#ld: -m elf_i386
+#as: --32
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*

Property changes on: ld/testsuite/ld-ifunc/ifunc-5a-local-i386.d
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-5-local-x86-64.s
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-5-local-x86-64.s	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-5-local-x86-64.s	(revision 6107)
@@ -0,0 +1,18 @@
+	.text
+	.type foo, %gnu_indirect_function
+	.type	foo, @function
+foo:
+	ret
+	.size	foo, .-foo
+	.type start,"function"
+	.global start
+start:
+	.type _start,"function"
+	.global _start
+_start:
+	.type __start,"function"
+	.global __start
+__start:
+	.type __start,"function"
+	call	foo@PLT
+	movq    foo@GOTPCREL(%rip), %rax

Property changes on: ld/testsuite/ld-ifunc/ifunc-5-local-x86-64.s
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-2-local-i386.s
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-2-local-i386.s	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-2-local-i386.s	(revision 6107)
@@ -0,0 +1,18 @@
+	.type foo, %gnu_indirect_function
+	.set __GI_foo, foo
+	.text
+	.type	foo, @function
+foo:
+	ret
+	.size	foo, .-foo
+.globl bar
+	.type	bar, @function
+bar:
+	call	.L6
+.L6:
+	popl	%ebx
+	addl	$_GLOBAL_OFFSET_TABLE_+[.-.L6], %ebx
+	call	__GI_foo
+	leal	__GI_foo@GOTOFF(%ebx), %eax
+	ret
+	.size	bar, .-bar

Property changes on: ld/testsuite/ld-ifunc/ifunc-2-local-i386.s
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-2-local-x86-64.d
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-2-local-x86-64.d	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-2-local-x86-64.d	(revision 6107)
@@ -0,0 +1,9 @@
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -dw
+#target: x86_64-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+call[ \t0-9a-fq]+<\*ABS\*@plt>
+[ \t0-9a-f]+:[ \t0-9a-f]+lea[ \t]+.*\(%rip\),%rax.*[ \t0-9a-fq]+<\*ABS\*@plt>
+#pass

Property changes on: ld/testsuite/ld-ifunc/ifunc-2-local-x86-64.d
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-5a-local-x86-64.d
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-5a-local-x86-64.d	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-5a-local-x86-64.d	(revision 6107)
@@ -0,0 +1,9 @@
+#source: ifunc-5-local-x86-64.s
+#as: --64
+#ld: -melf_x86_64
+#readelf: -r --wide
+#target: x86_64-*-*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*

Property changes on: ld/testsuite/ld-ifunc/ifunc-5a-local-x86-64.d
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-1-local-x86.d
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-1-local-x86.d	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-1-local-x86.d	(revision 6107)
@@ -0,0 +1,7 @@
+#ld: -shared
+#objdump: -dw
+#target: x86_64-*-* i?86-*-*
+
+#...
+[ \t0-9a-f]+:[ \t0-9a-f]+call[ \t0-9a-fq]+<\*ABS\*@plt>
+#pass

Property changes on: ld/testsuite/ld-ifunc/ifunc-1-local-x86.d
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-4-local-x86.d
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-4-local-x86.d	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-4-local-x86.d	(revision 6107)
@@ -0,0 +1,7 @@
+#ld:
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+#...
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_[_0-9A-Z]+_IRELATIVE[ ]*[0-9a-f]*
+#pass

Property changes on: ld/testsuite/ld-ifunc/ifunc-4-local-x86.d
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-2-local-x86-64.s
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-2-local-x86-64.s	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-2-local-x86-64.s	(revision 6107)
@@ -0,0 +1,17 @@
+	.type foo, %gnu_indirect_function
+	.global __GI_foo
+	.hidden __GI_foo
+	.set __GI_foo, foo
+	.text
+.globl foo
+	.type	foo, @function
+foo:
+	ret
+	.size	foo, .-foo
+.globl bar
+	.type	bar, @function
+bar:
+	call	__GI_foo
+	leaq	__GI_foo(%rip), %rax
+	ret
+	.size	bar, .-bar

Property changes on: ld/testsuite/ld-ifunc/ifunc-2-local-x86-64.s
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-5b-local-i386.d
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-5b-local-i386.d	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-5b-local-i386.d	(revision 6107)
@@ -0,0 +1,9 @@
+#source: ifunc-5-local-i386.s
+#ld: -shared -m elf_i386 -z nocombreloc
+#as: --32
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*

Property changes on: ld/testsuite/ld-ifunc/ifunc-5b-local-i386.d
___________________________________________________________________
Added: svn:mergeinfo

Index: ld/testsuite/ld-ifunc/ifunc-1-local-x86.s
===================================================================
--- ld/testsuite/ld-ifunc/ifunc-1-local-x86.s	(revision 0)
+++ ld/testsuite/ld-ifunc/ifunc-1-local-x86.s	(revision 6107)
@@ -0,0 +1,13 @@
+	.type foo, %gnu_indirect_function
+	.set __GI_foo, foo
+	.text
+	.type	foo, @function
+foo:
+	ret
+	.size	foo, .-foo
+.globl bar
+	.type	bar, @function
+bar:
+	call	__GI_foo@PLT
+	ret
+	.size	bar, .-bar

Property changes on: ld/testsuite/ld-ifunc/ifunc-1-local-x86.s
___________________________________________________________________
Added: svn:mergeinfo

Index: bfd/elf64-x86-64.c
===================================================================
--- bfd/elf64-x86-64.c	(revision 6086)
+++ bfd/elf64-x86-64.c	(working copy)
@@ -26,6 +26,8 @@
 #include "libbfd.h"
 #include "elf-bfd.h"
 #include "bfd_stdint.h"
+#include "objalloc.h"
+#include "hashtab.h"
 
 #include "elf/x86-64.h"
 
@@ -520,6 +522,10 @@ struct elf64_x86_64_link_hash_table
 
   /* _TLS_MODULE_BASE_ symbol.  */
   struct bfd_link_hash_entry *tls_module_base;
+
+  /* Used by local STT_GNU_IFUNC symbols.  */
+  htab_t loc_hash_table;
+  void *loc_hash_memory;
 };
 
 /* Get the x86-64 ELF linker hash table from a link_info structure.  */
@@ -562,6 +568,82 @@ elf64_x86_64_link_hash_newfunc (struct b
   return entry;
 }
 
+static hashval_t
+elf64_x86_64_local_hash (int id, int r_sym)
+{
+  return ((((id & 0xff) << 24) | ((id & 0xff00) << 8))
+	  ^ r_sym ^ (id >> 16));
+}
+
+/* Compute a hash of a local hash entry.  We use elf_link_hash_entry
+  for local symbol so that we can handle local STT_GNU_IFUNC symbols
+  as global symbol.  We reuse indx and dynstr_index for local symbol
+  hash since they aren't used by global symbols in this backend.  */
+
+static hashval_t
+elf64_x86_64_local_htab_hash (const void *ptr)
+{
+  struct elf_link_hash_entry *h
+    = (struct elf_link_hash_entry *) ptr;
+  return elf64_x86_64_local_hash (h->indx, h->dynstr_index);
+}
+
+/* Compare local hash entries.  */
+
+static int
+elf64_x86_64_local_htab_eq (const void *ptr1, const void *ptr2)
+{
+  struct elf_link_hash_entry *h1
+     = (struct elf_link_hash_entry *) ptr1;
+  struct elf_link_hash_entry *h2
+    = (struct elf_link_hash_entry *) ptr2;
+
+  return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
+}
+
+/* Find and/or create a hash entry for local symbol.  */
+
+static struct elf_link_hash_entry *
+elf64_x86_64_get_local_sym_hash (struct elf64_x86_64_link_hash_table *htab,
+				 bfd *abfd, const Elf_Internal_Rela *rel,
+				 bfd_boolean create)
+{
+  struct elf64_x86_64_link_hash_entry e, *ret;
+  asection *sec = abfd->sections;
+  hashval_t h = elf64_x86_64_local_hash (sec->id,
+					 ELF64_R_SYM (rel->r_info));
+  void **slot;
+
+  e.elf.indx = sec->id;
+  e.elf.dynstr_index = ELF64_R_SYM (rel->r_info);
+  slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
+				   create ? INSERT : NO_INSERT);
+
+  if (!slot)
+    return NULL;
+
+  if (*slot)
+    {
+      ret = (struct elf64_x86_64_link_hash_entry *) *slot;
+      return &ret->elf;
+    }
+
+  ret = (struct elf64_x86_64_link_hash_entry *)
+	objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
+			sizeof (struct elf64_x86_64_link_hash_entry));
+  if (ret)
+    {
+      memset (ret, 0, sizeof (*ret));
+      ret->elf.indx = sec->id;
+      ret->elf.dynstr_index = ELF64_R_SYM (rel->r_info);
+      ret->elf.dynindx = -1;
+      ret->elf.plt.offset = (bfd_vma) -1;
+      ret->elf.got.offset = (bfd_vma) -1;
+      *slot = ret;
+    }
+  return &ret->elf;
+}
+
 /* Create an X86-64 ELF linker hash table.  */
 
 static struct bfd_link_hash_table *
@@ -600,9 +682,35 @@ elf64_x86_64_link_hash_table_create (bfd
   ret->sgotplt_jump_table_size = 0;
   ret->tls_module_base = NULL;
 
+  ret->loc_hash_table = htab_try_create (1024,
+					 elf64_x86_64_local_htab_hash,
+					 elf64_x86_64_local_htab_eq,
+					 NULL);
+  ret->loc_hash_memory = objalloc_create ();
+  if (!ret->loc_hash_table || !ret->loc_hash_memory)
+    {
+      free (ret);
+      return NULL;
+    }
+
   return &ret->elf.root;
 }
 
+/* Destroy an X86-64 ELF linker hash table.  */
+
+static void
+elf64_x86_64_link_hash_table_free (struct bfd_link_hash_table *hash)
+{
+  struct elf64_x86_64_link_hash_table *htab
+    = (struct elf64_x86_64_link_hash_table *) hash;
+
+  if (htab->loc_hash_table)
+    htab_delete (htab->loc_hash_table);
+  if (htab->loc_hash_memory)
+    objalloc_free ((struct objalloc *) htab->loc_hash_memory);
+  _bfd_generic_link_hash_table_free (hash);
+}
+
 /* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
    shortcuts to them in our hash table.  */
 
@@ -1012,6 +1120,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   asection *sreloc;
+  Elf_Internal_Sym *isymbuf;
 
   if (info->relocatable)
     return TRUE;
@@ -1020,6 +1129,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 
   htab = elf64_x86_64_hash_table (info);
   symtab_hdr = &elf_symtab_hdr (abfd);
+  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   sym_hashes = elf_sym_hashes (abfd);
 
   sreloc = NULL;
@@ -1042,14 +1152,50 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 	}
 
       if (r_symndx < symtab_hdr->sh_info)
-	h = NULL;
+	{
+	  /* A local symbol.  */
+	  Elf_Internal_Sym *isym;
+
+	  /* Read this BFD's local symbols.  */
+	  if (isymbuf == NULL)
+	    {
+	      if (isymbuf == NULL)
+		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+						symtab_hdr->sh_info, 0,
+						NULL, NULL, NULL);
+	      if (isymbuf == NULL)
+		  return FALSE;
+	    }
+
+	  /* Check relocation against local STT_GNU_IFUNC symbol.  */
+	  isym = isymbuf + r_symndx;
+	  if (ELF64_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
+	    {
+	      h = elf64_x86_64_get_local_sym_hash (htab, abfd, rel,
+						   TRUE);
+	      if (h == NULL)
+		return FALSE;
+	      
+	      /* Fake a STT_GNU_IFUNC symbol.  */
+	      h->type = STT_GNU_IFUNC;
+	      h->def_regular = 1;
+	      h->ref_regular = 1;
+	      h->forced_local = 1;
+	      h->root.type = bfd_link_hash_defined;
+	    }
+	  else
+	    h = NULL;
+	}
       else
 	{
 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 	  while (h->root.type == bfd_link_hash_indirect
 		 || h->root.type == bfd_link_hash_warning)
 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	}
 
+      if (h != NULL)
+	{
 	  /* Create the ifunc sections for static executables.  If we
 	     never see an indirect function symbol nor we are building
 	     a static executable, those sections will be empty and
@@ -1117,7 +1263,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
 		     (_("%B: relocation %s against STT_GNU_IFUNC "
 			"symbol `%s' isn't handled by %s"), abfd,
 		      x86_64_elf_howto_table[r_type].name,
-		      h->root.root.string, __FUNCTION__);
+		      h != NULL ? h->root.root.string : "a local symbol",
+		      __FUNCTION__);
 		   bfd_set_error (bfd_error_bad_value);
 		   return FALSE;
 
@@ -2145,6 +2292,25 @@ elf64_x86_64_allocate_dynrelocs (struct 
   return TRUE;
 }
 
+/* Allocate space in .plt, .got and associated reloc sections for
+   local dynamic relocs.  */
+
+static bfd_boolean
+elf64_x86_64_allocate_local_dynrelocs (void **slot, void *inf)
+{
+  struct elf_link_hash_entry *h
+    = (struct elf_link_hash_entry *) *slot;
+
+  if (h->type != STT_GNU_IFUNC
+      || !h->def_regular
+      || !h->ref_regular
+      || !h->forced_local
+      || h->root.type != bfd_link_hash_defined)
+    abort ();
+
+  return elf64_x86_64_allocate_dynrelocs (h, inf);
+}
+
 /* Find any dynamic relocs that apply to read-only sections.  */
 
 static bfd_boolean
@@ -2313,6 +2479,11 @@ elf64_x86_64_size_dynamic_sections (bfd 
   elf_link_hash_traverse (&htab->elf, elf64_x86_64_allocate_dynrelocs,
 			  info);
 
+  /* Allocate .plt and .got entries, and space for local symbols.  */
+  htab_traverse (htab->loc_hash_table,
+		 elf64_x86_64_allocate_local_dynrelocs,
+		 info);
+
   /* For every jump slot reserved in the sgotplt, reloc_count is
      incremented.  However, when we reserve space for TLS descriptors,
      it's not incremented, so in order to compute the space reserved
@@ -2630,7 +2801,21 @@ elf64_x86_64_relocate_section (bfd *outp
 	  sym = local_syms + r_symndx;
 	  sec = local_sections[r_symndx];
 
-	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
+	  relocation = _bfd_elf_rela_local_sym (output_bfd, sym,
+						&sec, rel);
+
+	  /* Relocate against local STT_GNU_IFUNC symbol.  */
+	  if (ELF64_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+	    {
+	      h = elf64_x86_64_get_local_sym_hash (htab, input_bfd,
+						   rel, FALSE);
+	      if (h == NULL)
+		abort ();
+
+	      /* Set STT_GNU_IFUNC symbol value.  */ 
+	      h->root.u.def.value = sym->st_value;
+	      h->root.u.def.section = sec;
+	    }
 	}
       else
 	{
@@ -2710,8 +2895,8 @@ elf64_x86_64_relocate_section (bfd *outp
 		  bfd_byte *loc;
 		  asection *sreloc;
 
-		  /* Need a dynamic relocation get the the real
-		     function address. */
+		  /* Need a dynamic relocation to get the real function
+		     address.  */
 		  outrel.r_offset = _bfd_elf_section_offset (output_bfd,
 							     info,
 							     input_section,
@@ -3941,14 +4126,31 @@ do_glob_dat:
       bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
     }
 
-  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || h == htab->elf.hgot)
+  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  SYM may
+     be NULL for local symbols.  */
+  if (sym != NULL
+      && (strcmp (h->root.root.string, "_DYNAMIC") == 0
+	  || h == htab->elf.hgot))
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
 }
 
+/* Finish up local dynamic symbol handling.  We set the contents of
+   various dynamic sections here.  */
+
+static bfd_boolean
+elf64_x86_64_finish_local_dynamic_symbol (void **slot, void *inf)
+{
+  struct elf_link_hash_entry *h
+    = (struct elf_link_hash_entry *) *slot;
+  struct bfd_link_info *info
+    = (struct bfd_link_info *) inf; 
+
+  return elf64_x86_64_finish_dynamic_symbol (info->output_bfd,
+					     info, h, NULL);
+}
+
 /* Used to decide how to sort relocs in an optimal manner for the
    dynamic linker, before writing them out.  */
 
@@ -4139,6 +4341,11 @@ elf64_x86_64_finish_dynamic_sections (bf
     elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize
       = GOT_ENTRY_SIZE;
 
+  /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols.  */
+  htab_traverse (htab->loc_hash_table,
+		 elf64_x86_64_finish_local_dynamic_symbol,
+		 info);
+
   return TRUE;
 }
 
@@ -4387,6 +4594,8 @@ static const struct bfd_elf_special_sect
 
 #define bfd_elf64_bfd_link_hash_table_create \
   elf64_x86_64_link_hash_table_create
+#define bfd_elf64_bfd_link_hash_table_free \
+  elf64_x86_64_link_hash_table_free
 #define bfd_elf64_bfd_reloc_type_lookup	    elf64_x86_64_reloc_type_lookup
 #define bfd_elf64_bfd_reloc_name_lookup \
   elf64_x86_64_reloc_name_lookup
Index: bfd/elf32-i386.c
===================================================================
--- bfd/elf32-i386.c	(revision 6086)
+++ bfd/elf32-i386.c	(working copy)
@@ -26,6 +26,8 @@
 #include "elf-bfd.h"
 #include "elf-vxworks.h"
 #include "bfd_stdint.h"
+#include "objalloc.h"
+#include "hashtab.h"
 
 /* 386 uses REL relocations instead of RELA.  */
 #define USE_REL	1
@@ -706,6 +708,10 @@ struct elf_i386_link_hash_table
 
   /* _TLS_MODULE_BASE_ symbol.  */
   struct bfd_link_hash_entry *tls_module_base;
+
+  /* Used by local STT_GNU_IFUNC symbols.  */
+  htab_t loc_hash_table;
+  void *loc_hash_memory;
 };
 
 /* Get the i386 ELF linker hash table from a link_info structure.  */
@@ -748,6 +754,82 @@ elf_i386_link_hash_newfunc (struct bfd_h
   return entry;
 }
 
+static hashval_t
+elf_i386_local_hash (int id, int r_sym)
+{
+  return ((((id & 0xff) << 24) | ((id & 0xff00) << 8))
+	  ^ r_sym ^ (id >> 16));
+}
+
+/* Compute a hash of a local hash entry.  We use elf_link_hash_entry
+  for local symbol so that we can handle local STT_GNU_IFUNC symbols
+  as global symbol.  We reuse indx and dynstr_index for local symbol
+  hash since they aren't used by global symbols in this backend.  */
+
+static hashval_t
+elf_i386_local_htab_hash (const void *ptr)
+{
+  struct elf_link_hash_entry *h
+    = (struct elf_link_hash_entry *) ptr;
+  return elf_i386_local_hash (h->indx, h->dynstr_index);
+}
+
+/* Compare local hash entries.  */
+
+static int
+elf_i386_local_htab_eq (const void *ptr1, const void *ptr2)
+{
+  struct elf_link_hash_entry *h1
+     = (struct elf_link_hash_entry *) ptr1;
+  struct elf_link_hash_entry *h2
+    = (struct elf_link_hash_entry *) ptr2;
+
+  return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
+}
+
+/* Find and/or create a hash entry for local symbol.  */
+
+static struct elf_link_hash_entry *
+elf_i386_get_local_sym_hash (struct elf_i386_link_hash_table *htab,
+			     bfd *abfd, const Elf_Internal_Rela *rel,
+			     bfd_boolean create)
+{
+  struct elf_i386_link_hash_entry e, *ret;
+  asection *sec = abfd->sections;
+  hashval_t h = elf_i386_local_hash (sec->id,
+				     ELF32_R_SYM (rel->r_info));
+  void **slot;
+
+  e.elf.indx = sec->id;
+  e.elf.dynstr_index = ELF32_R_SYM (rel->r_info);
+  slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
+				   create ? INSERT : NO_INSERT);
+
+  if (!slot)
+    return NULL;
+
+  if (*slot)
+    {
+      ret = (struct elf_i386_link_hash_entry *) *slot;
+      return &ret->elf;
+    }
+
+  ret = (struct elf_i386_link_hash_entry *)
+	objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
+			sizeof (struct elf_i386_link_hash_entry));
+  if (ret)
+    {
+      memset (ret, 0, sizeof (*ret));
+      ret->elf.indx = sec->id;
+      ret->elf.dynstr_index = ELF32_R_SYM (rel->r_info);
+      ret->elf.dynindx = -1;
+      ret->elf.plt.offset = (bfd_vma) -1;
+      ret->elf.got.offset = (bfd_vma) -1;
+      *slot = ret;
+    }
+  return &ret->elf;
+}
+
 /* Create an i386 ELF linker hash table.  */
 
 static struct bfd_link_hash_table *
@@ -788,9 +870,38 @@ elf_i386_link_hash_table_create (bfd *ab
   ret->plt0_pad_byte = 0;
   ret->tls_module_base = NULL;
 
+  ret->loc_hash_table = htab_try_create (1024,
+					 elf_i386_local_htab_hash,
+					 elf_i386_local_htab_eq,
+					 NULL);
+  ret->loc_hash_memory = objalloc_create ();
+  if (!ret->loc_hash_table || !ret->loc_hash_memory)
+    {
+      free (ret);
+      return NULL;
+    }
+
   return &ret->elf.root;
 }
 
+/* Destroy an i386 ELF linker hash table.  */
+
+static void
+elf_i386_link_hash_table_free (struct bfd_link_hash_table *hash)
+{
+  struct elf_i386_link_hash_table *htab
+    = (struct elf_i386_link_hash_table *) hash;
+
+  if (htab->loc_hash_table)
+    htab_delete (htab->loc_hash_table);
+  if (htab->loc_hash_memory)
+    objalloc_free ((struct objalloc *) htab->loc_hash_memory);
+  _bfd_generic_link_hash_table_free (hash);
+}
+
+/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
+   shortcuts to them in our hash table.  */
+
 /* Create .got, .gotplt, and .rel.got sections in DYNOBJ, and set up
    shortcuts to them in our hash table.  */
 
@@ -1228,6 +1339,7 @@ elf_i386_check_relocs (bfd *abfd,
   const Elf_Internal_Rela *rel;
   const Elf_Internal_Rela *rel_end;
   asection *sreloc;
+  Elf_Internal_Sym *isymbuf;
 
   if (info->relocatable)
     return TRUE;
@@ -1236,6 +1348,7 @@ elf_i386_check_relocs (bfd *abfd,
 
   htab = elf_i386_hash_table (info);
   symtab_hdr = &elf_symtab_hdr (abfd);
+  isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
   sym_hashes = elf_sym_hashes (abfd);
 
   sreloc = NULL;
@@ -1259,14 +1372,50 @@ elf_i386_check_relocs (bfd *abfd,
 	}
 
       if (r_symndx < symtab_hdr->sh_info)
-	h = NULL;
+	{
+	  /* A local symbol.  */
+	  Elf_Internal_Sym *isym;
+
+	  /* Read this BFD's local symbols.  */
+	  if (isymbuf == NULL)
+	    {
+	      if (isymbuf == NULL)
+		isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+						symtab_hdr->sh_info, 0,
+						NULL, NULL, NULL);
+	      if (isymbuf == NULL)
+		  return FALSE;
+	    }
+
+	  /* Check relocation against local STT_GNU_IFUNC symbol.  */
+	  isym = isymbuf + r_symndx;
+	  if (ELF32_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
+	    {
+	      h = elf_i386_get_local_sym_hash (htab, abfd, rel,
+						   TRUE);
+	      if (h == NULL)
+		return FALSE;
+	      
+	      /* Fake a STT_GNU_IFUNC symbol.  */
+	      h->type = STT_GNU_IFUNC;
+	      h->def_regular = 1;
+	      h->ref_regular = 1;
+	      h->forced_local = 1;
+	      h->root.type = bfd_link_hash_defined;
+	    }
+	  else
+	    h = NULL;
+	}
       else
 	{
 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 	  while (h->root.type == bfd_link_hash_indirect
 		 || h->root.type == bfd_link_hash_warning)
 	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	}
 
+      if (h != NULL)
+	{
 	  /* Create the ifunc sections for static executables.  If we
 	     never see an indirect function symbol nor we are building
 	     a static executable, those sections will be empty and
@@ -1331,7 +1480,8 @@ elf_i386_check_relocs (bfd *abfd,
 		     (_("%B: relocation %s against STT_GNU_IFUNC "
 			"symbol `%s' isn't handled by %s"), abfd,
 		      elf_howto_table[r_type].name,
-		      h->root.root.string, __FUNCTION__);
+		      h != NULL ? h->root.root.string : "a local symbol",
+		      __FUNCTION__);
 		   bfd_set_error (bfd_error_bad_value);
 		   return FALSE;
 
@@ -2337,6 +2487,25 @@ elf_i386_allocate_dynrelocs (struct elf_
   return TRUE;
 }
 
+/* Allocate space in .plt, .got and associated reloc sections for
+   local dynamic relocs.  */
+
+static bfd_boolean
+elf_i386_allocate_local_dynrelocs (void **slot, void *inf)
+{
+  struct elf_link_hash_entry *h
+    = (struct elf_link_hash_entry *) *slot;
+
+  if (h->type != STT_GNU_IFUNC
+      || !h->def_regular
+      || !h->ref_regular
+      || !h->forced_local
+      || h->root.type != bfd_link_hash_defined)
+    abort ();
+
+  return elf_i386_allocate_dynrelocs (h, inf);
+}
+
 /* Find any dynamic relocs that apply to read-only sections.  */
 
 static bfd_boolean
@@ -2511,6 +2680,11 @@ elf_i386_size_dynamic_sections (bfd *out
      sym dynamic relocs.  */
   elf_link_hash_traverse (&htab->elf, elf_i386_allocate_dynrelocs, info);
 
+  /* Allocate .plt and .got entries, and space for local symbols.  */
+  htab_traverse (htab->loc_hash_table,
+		 elf_i386_allocate_local_dynrelocs,
+		 info);
+
   /* For every jump slot reserved in the sgotplt, reloc_count is
      incremented.  However, when we reserve space for TLS descriptors,
      it's not incremented, so in order to compute the space reserved
@@ -2916,6 +3090,18 @@ elf_i386_relocate_section (bfd *output_b
 		  break;
 		}
 	    }
+	  else if (ELF32_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+	    {
+	      /* Relocate against local STT_GNU_IFUNC symbol.  */
+	      h = elf_i386_get_local_sym_hash (htab, input_bfd,
+						   rel, FALSE);
+	      if (h == NULL)
+		abort ();
+
+	      /* Set STT_GNU_IFUNC symbol value.  */ 
+	      h->root.u.def.value = sym->st_value;
+	      h->root.u.def.section = sec;
+	    }
 	}
       else
 	{
@@ -2990,8 +3176,8 @@ elf_i386_relocate_section (bfd *output_b
 		  asection *sreloc;
 		  bfd_vma offset;
 
-		  /* Need a dynamic relocation get the the real
-		     function adddress.  */
+		  /* Need a dynamic relocation to get the real function
+		     adddress.  */
 		  offset = _bfd_elf_section_offset (output_bfd,
 						    info,
 						    input_section,
@@ -4310,16 +4496,34 @@ do_glob_dat:
       bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
     }
 
-  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.
+  /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  SYM may
+     be NULL for local symbols.
+
      On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it
      is relative to the ".got" section.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || (!htab->is_vxworks && h == htab->elf.hgot))
+  if (sym != NULL
+      && (strcmp (h->root.root.string, "_DYNAMIC") == 0
+	  || (!htab->is_vxworks && h == htab->elf.hgot)))
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
 }
 
+/* Finish up local dynamic symbol handling.  We set the contents of
+   various dynamic sections here.  */
+
+static bfd_boolean
+elf_i386_finish_local_dynamic_symbol (void **slot, void *inf)
+{
+  struct elf_link_hash_entry *h
+    = (struct elf_link_hash_entry *) *slot;
+  struct bfd_link_info *info
+    = (struct bfd_link_info *) inf; 
+
+  return elf_i386_finish_dynamic_symbol (info->output_bfd, info,
+					 h, NULL);
+}
+
 /* Used to decide how to sort relocs in an optimal manner for the
    dynamic linker, before writing them out.  */
 
@@ -4527,6 +4731,11 @@ elf_i386_finish_dynamic_sections (bfd *o
   if (htab->sgot && htab->sgot->size > 0)
     elf_section_data (htab->sgot->output_section)->this_hdr.sh_entsize = 4;
 
+  /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols.  */
+  htab_traverse (htab->loc_hash_table,
+		 elf_i386_finish_local_dynamic_symbol,
+		 info);
+
   return TRUE;
 }
 
@@ -4592,6 +4801,7 @@ elf_i386_add_symbol_hook (bfd * abfd ATT
 
 #define bfd_elf32_bfd_is_local_label_name     elf_i386_is_local_label_name
 #define bfd_elf32_bfd_link_hash_table_create  elf_i386_link_hash_table_create
+#define bfd_elf32_bfd_link_hash_table_free    elf_i386_link_hash_table_free
 #define bfd_elf32_bfd_reloc_type_lookup	      elf_i386_reloc_type_lookup
 #define bfd_elf32_bfd_reloc_name_lookup	      elf_i386_reloc_name_lookup
 
Index: bfd/ChangeLog.ifunc
===================================================================
Index: gas/ChangeLog.ifunc
===================================================================
Index: gas/config/tc-i386.c
===================================================================
--- gas/config/tc-i386.c	(revision 6086)
+++ gas/config/tc-i386.c	(working copy)
@@ -7231,7 +7231,7 @@ md_apply_fix (fixP, valP, seg)
 	  if ((sym_seg == seg
 	       || (symbol_section_p (fixP->fx_addsy)
 		   && sym_seg != absolute_section))
-	      && !generic_force_reloc (fixP))
+	      && !TC_FORCE_RELOCATION (fixP))
 	    {
 	      /* Yes, we add the values in twice.  This is because
 		 bfd_install_relocation subtracts them out again.  I think
Index: gas/config/tc-i386.h
===================================================================
--- gas/config/tc-i386.h	(revision 6086)
+++ gas/config/tc-i386.h	(working copy)
@@ -138,6 +138,12 @@ extern int tc_i386_fix_adjustable (struc
   (OUTPUT_FLAVOR == bfd_target_elf_flavour)
 #endif
 
+/* BSF_GNU_INDIRECT_FUNCTION symbols always need relocatoon.  */
+#define TC_FORCE_RELOCATION(FIX)			\
+  ((symbol_get_bfdsym ((FIX)->fx_addsy)->flags		\
+    & BSF_GNU_INDIRECT_FUNCTION)			\
+   || generic_force_reloc (FIX))
+
 /* This expression evaluates to true if the relocation is for a local
    object for which we still want to do the relocation at runtime.
    False if we are willing to perform this relocation while building


More information about the Libc-alpha mailing list