+2012-12-16  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/14968
+       * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Also check
+       local IFUNC references.
+       * elf64-x86-64.c (elf_x86_64_adjust_dynamic_symbol): Likewise.
+
 2012-12-14  Tom Tromey  <tromey@redhat.com>
 
-        * elf.c (elfcore_grok_note) <NT_FILE>: New case.
+       * elf.c (elfcore_grok_note) <NT_FILE>: New case.
 
 2012-12-13  H.J. Lu  <hongjiu.lu@intel.com>
 
 
   /* STT_GNU_IFUNC symbol must go through PLT. */
   if (h->type == STT_GNU_IFUNC)
     {
-      /* Check local STT_GNU_IFUNC calls.  */
+      /* All local STT_GNU_IFUNC references must be treate as local
+        calls via local PLT.  */
       if (h->ref_regular
          && SYMBOL_CALLS_LOCAL (info, h))
        {
-         bfd_size_type pc_count = 0;
+         bfd_size_type pc_count = 0, count = 0;
          struct elf_dyn_relocs **pp;
 
          eh = (struct elf_i386_link_hash_entry *) h;
              pc_count += p->pc_count;
              p->count -= p->pc_count;
              p->pc_count = 0;
+             count += p->count;
              if (p->count == 0)
                *pp = p->next;
              else
                pp = &p->next;
            }
 
-         if (pc_count)
+         if (pc_count || count)
            {
              h->needs_plt = 1;
              h->plt.refcount += 1;
 
   /* STT_GNU_IFUNC symbol must go through PLT. */
   if (h->type == STT_GNU_IFUNC)
     {
-      /* Check local STT_GNU_IFUNC calls.  */
+      /* All local STT_GNU_IFUNC references must be treate as local
+        calls via local PLT.  */
       if (h->ref_regular
          && SYMBOL_CALLS_LOCAL (info, h))
        {
-         bfd_size_type pc_count = 0;
+         bfd_size_type pc_count = 0, count = 0;
          struct elf_dyn_relocs **pp;
 
          eh = (struct elf_x86_64_link_hash_entry *) h;
              pc_count += p->pc_count;
              p->count -= p->pc_count;
              p->pc_count = 0;
+             count += p->count;
              if (p->count == 0)
                *pp = p->next;
              else
                pp = &p->next;
            }
 
-         if (pc_count)
+         if (pc_count || count)
            {
              h->needs_plt = 1;
              h->plt.refcount += 1;
 
+2012-12-16  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/14968
+       * ld-ifunc/ifunc-18a-i386.d: New file.
+       * ld-ifunc/ifunc-18a-x86-64.d: Likewise.
+       * ld-ifunc/ifunc-18a.s: Likewise.
+       * ld-ifunc/ifunc-18b-i386.d: Likewise.
+       * ld-ifunc/ifunc-18b-x86-64.d: Likewise.
+       * ld-ifunc/ifunc-18b.s: Likewise.
+       * ld-ifunc/ifunc-19a-i386.d: Likewise.
+       * ld-ifunc/ifunc-19a-x86-64.d: Likewise.
+       * ld-ifunc/ifunc-19a.s: Likewise.
+       * ld-ifunc/ifunc-19b-i386.d: Likewise.
+       * ld-ifunc/ifunc-19b-x86-64.d: Likewise.
+       * ld-ifunc/ifunc-19b.s: Likewise.
+
 2012-12-15  Thomas Schwinge  <thomas@codesourcery.com>
 
        * ld-elf/elf.exp (stack exec, stack size): Run for any GNU target.
 
--- /dev/null
+#source: ifunc-18a.s
+#source: ifunc-18b.s
+#ld: -shared -m elf_i386 -z nocombreloc
+#as: --32
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
+
+Relocation section '.rel.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
 
--- /dev/null
+#source: ifunc-18a.s
+#source: ifunc-18b.s
+#as: --64
+#ld: -shared -melf_x86_64 -z nocombreloc
+#readelf: -r --wide
+#target: x86_64-*-*
+
+Relocation section '.rela.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
 
--- /dev/null
+       .section .data.rel,"aw",@progbits
+       .globl foo_ptrt
+       .type   foo_ptr, @object
+foo_ptr:
+       .dc.a foo
 
--- /dev/null
+#source: ifunc-18b.s
+#source: ifunc-18a.s
+#ld: -shared -m elf_i386 -z nocombreloc
+#as: --32
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
+
+Relocation section '.rel.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
 
--- /dev/null
+#source: ifunc-18b.s
+#source: ifunc-18a.s
+#as: --64
+#ld: -shared -melf_x86_64 -z nocombreloc
+#readelf: -r --wide
+#target: x86_64-*-*
+
+Relocation section '.rela.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
 
--- /dev/null
+       .text
+       .type foo, %gnu_indirect_function
+       .hidden foo
+       .globl foo
+foo:
+       ret
+       .size   foo, .-foo
+       .globl bar
+bar:
+       jmp     foo1@PLT
+       ret
+       .size   bar, .-bar
+       .hidden foo1
+       .globl foo1
+       foo1 = foo
 
--- /dev/null
+#source: ifunc-19a.s
+#source: ifunc-19b.s
+#ld: -shared -m elf_i386 -z nocombreloc
+#as: --32
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
+
+Relocation section '.rel.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
 
--- /dev/null
+#source: ifunc-19a.s
+#source: ifunc-19b.s
+#as: --64
+#ld: -shared -melf_x86_64 -z nocombreloc
+#readelf: -r --wide
+#target: x86_64-*-*
+
+Relocation section '.rela.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
 
--- /dev/null
+       .section .data.rel,"aw",@progbits
+       .globl foo_ptrt
+       .type   foo_ptr, @object
+foo_ptr:
+       .dc.a foo1
 
--- /dev/null
+#source: ifunc-19b.s
+#source: ifunc-19a.s
+#ld: -shared -m elf_i386 -z nocombreloc
+#as: --32
+#readelf: -r --wide
+#target: x86_64-*-* i?86-*-*
+
+Relocation section '.rel.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
+
+Relocation section '.rel.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*
 
--- /dev/null
+#source: ifunc-19b.s
+#source: ifunc-19a.s
+#as: --64
+#ld: -shared -melf_x86_64 -z nocombreloc
+#readelf: -r --wide
+#target: x86_64-*-*
+
+Relocation section '.rela.ifunc' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
+
+Relocation section '.rela.plt' at .*
+[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
+[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_IRELATIVE[ ]+[0-9a-f]*
 
--- /dev/null
+       .text
+       .type foo, %gnu_indirect_function
+       .hidden foo
+       .globl foo
+foo:
+       ret
+       .size   foo, .-foo
+       .globl bar
+bar:
+       jmp     foo1@PLT
+       ret
+       .size   bar, .-bar
+       .hidden foo1
+       .globl foo1
+       foo1 = foo