+2014-07-16  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/17154
+       * elf32-i386.c (elf_i386_plt_sym_val): Only match R_*_JUMP_SLOT
+       and R_*_IRELATIVE relocation offset with PLT entry.
+       * elf64-x86-64.c (elf_x86_64_plt_sym_val): Likewise.
+       (elf_x86_64_plt_sym_val_offset_plt_bnd): New.
+       (elf_x86_64_get_synthetic_symtab): Use it.
+
 2014-07-15  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/17057
 
   return TRUE;
 }
 
-/* Return address for Ith PLT stub in section PLT, for relocation REL
-   or (bfd_vma) -1 if it should not be included.  */
+/* Return address in section PLT for the Ith GOTPLT relocation, for
+   relocation REL or (bfd_vma) -1 if it should not be included.  */
 
 static bfd_vma
-elf_i386_plt_sym_val (bfd_vma i, const asection *plt,
-                     const arelent *rel ATTRIBUTE_UNUSED)
+elf_i386_plt_sym_val (bfd_vma i, const asection *plt, const arelent *rel)
 {
-  return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner);
+  bfd *abfd;
+  const struct elf_i386_backend_data *bed;
+  bfd_vma plt_offset;
+
+  /* Only match R_386_JUMP_SLOT and R_386_IRELATIVE.  */
+  if (rel->howto->type != R_386_JUMP_SLOT
+      && rel->howto->type != R_386_IRELATIVE)
+    return (bfd_vma) -1;
+
+  abfd = plt->owner;
+  bed = get_elf_i386_backend_data (abfd);
+  plt_offset = bed->plt->plt_entry_size;
+  while (plt_offset < plt->size)
+    {
+      bfd_vma reloc_offset;
+      bfd_byte reloc_offset_raw[4];
+
+      if (!bfd_get_section_contents (abfd, (asection *) plt,
+                                    reloc_offset_raw,
+                                    plt_offset + bed->plt->plt_reloc_offset,
+                                    sizeof (reloc_offset_raw)))
+       return (bfd_vma) -1;
+
+      reloc_offset = H_GET_32 (abfd, reloc_offset_raw);
+      if (reloc_offset == i * sizeof (Elf32_External_Rel))
+       return plt->vma + plt_offset;
+      plt_offset += bed->plt->plt_entry_size;
+    }
+
+  abort ();
 }
 
 /* Return TRUE if symbol should be hashed in the `.gnu.hash' section.  */
 
   return TRUE;
 }
 
-/* Return address for Ith PLT stub in section PLT, for relocation REL
-   or (bfd_vma) -1 if it should not be included.  */
+/* Return address in section PLT for the Ith GOTPLT relocation, for
+   relocation REL or (bfd_vma) -1 if it should not be included.  */
 
 static bfd_vma
 elf_x86_64_plt_sym_val (bfd_vma i, const asection *plt,
-                       const arelent *rel ATTRIBUTE_UNUSED)
+                       const arelent *rel)
 {
-  return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner);
+  bfd *abfd;
+  const struct elf_x86_64_backend_data *bed;
+  bfd_vma plt_offset;
+
+  /* Only match R_X86_64_JUMP_SLOT and R_X86_64_IRELATIVE.  */
+  if (rel->howto->type != R_X86_64_JUMP_SLOT
+      && rel->howto->type != R_X86_64_IRELATIVE)
+    return (bfd_vma) -1;
+
+  abfd = plt->owner;
+  bed = get_elf_x86_64_backend_data (abfd);
+  plt_offset = bed->plt_entry_size;
+  while (plt_offset < plt->size)
+    {
+      bfd_vma reloc_index;
+      bfd_byte reloc_index_raw[4];
+
+      if (!bfd_get_section_contents (abfd, (asection *) plt,
+                                    reloc_index_raw,
+                                    plt_offset + bed->plt_reloc_offset,
+                                    sizeof (reloc_index_raw)))
+       return (bfd_vma) -1;
+
+      reloc_index = H_GET_32 (abfd, reloc_index_raw);
+      if (reloc_index == i)
+       return plt->vma + plt_offset;
+      plt_offset += bed->plt_entry_size;
+    }
+
+  abort ();
+}
+
+/* Return offset in .plt.bnd section for the Ith GOTPLT relocation with
+   PLT section, or (bfd_vma) -1 if it should not be included.  */
+
+static bfd_vma
+elf_x86_64_plt_sym_val_offset_plt_bnd (bfd_vma i, const asection *plt)
+{
+  const struct elf_x86_64_backend_data *bed = &elf_x86_64_bnd_arch_bed;
+  bfd *abfd = plt->owner;
+  bfd_vma plt_offset = bed->plt_entry_size;
+  while (plt_offset < plt->size)
+    {
+      bfd_vma reloc_index;
+      bfd_byte reloc_index_raw[4];
+
+      if (!bfd_get_section_contents (abfd, (asection *) plt,
+                                    reloc_index_raw,
+                                    plt_offset + bed->plt_reloc_offset,
+                                    sizeof (reloc_index_raw)))
+       return (bfd_vma) -1;
+
+      reloc_index = H_GET_32 (abfd, reloc_index_raw);
+      if (reloc_index == i)
+       {
+         /* This is the index in .plt section.  */
+         long plt_index = plt_offset / bed->plt_entry_size;
+         /* Return the offset in .plt.bnd section.  */
+         return (plt_index - 1) * sizeof (elf_x86_64_legacy_plt2_entry);
+       }
+      plt_offset += bed->plt_entry_size;
+    }
+
+  abort ();
 }
 
 /* Similar to _bfd_elf_get_synthetic_symtab, with .plt.bnd section
   size_t size;
   Elf_Internal_Shdr *hdr;
   char *names;
-  asection *plt;
-  bfd_vma addr;
+  asection *plt, *plt_push;
+
+  plt_push = bfd_get_section_by_name (abfd, ".plt");
+  if (plt_push == NULL)
+    return 0;
 
   plt = bfd_get_section_by_name (abfd, ".plt.bnd");
   /* Use the generic ELF version if there is no .plt.bnd section.  */
   names = (char *) (s + count);
   p = relplt->relocation;
   n = 0;
-  addr = 0;
   for (i = 0; i < count; i++, p++)
     {
+      bfd_vma offset;
       size_t len;
 
+      if (p->howto->type != R_X86_64_JUMP_SLOT
+         && p->howto->type != R_X86_64_IRELATIVE)
+       continue;
+
+      offset = elf_x86_64_plt_sym_val_offset_plt_bnd (i, plt_push);
+
       *s = **p->sym_ptr_ptr;
       /* Undefined syms won't have BSF_LOCAL or BSF_GLOBAL set.  Since
         we are defining a symbol, ensure one of them is set.  */
        s->flags |= BSF_GLOBAL;
       s->flags |= BSF_SYNTHETIC;
       s->section = plt;
-      s->value = addr;
+      s->value = offset;
       s->name = names;
       s->udata.p = NULL;
       len = strlen ((*p->sym_ptr_ptr)->name);
       memcpy (names, "@plt", sizeof ("@plt"));
       names += sizeof ("@plt");
       ++s, ++n;
-      addr += sizeof (elf_x86_64_legacy_plt2_entry);
     }
 
   return n;
 
+2014-07-16  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR binutils/17154
+       * ld-ifunc/pr17154-i386.d: New file.
+       * ld-ifunc/pr17154-x86-64.d: Likewise.
+       * ld-ifunc/pr17154-x86.s: Likewise.
+       * ld-x86-64/bnd-ifunc-2.d: Likewise.
+       * ld-x86-64/bnd-ifunc-2.s: Likewise.
+       * ld-x86-64/mpx.exp: Run bnd-ifunc-2.
+       * ld-x86-64/tlsdesc-nacl.pd: Updated.
+       * ld-x86-64/tlsdesc.pd: Likewise.
+
 2014-07-15  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/17057
 
--- /dev/null
+#source: pr17154-x86.s
+#ld: -m elf_i386 -shared
+#as: --32
+#objdump: -dw
+#target: x86_64-*-* i?86-*-*
+
+#...
+0+1d0 <\*ABS\*@plt-0x10>:
+[      ]*[a-f0-9]+:    ff b3 04 00 00 00       pushl  0x4\(%ebx\)
+[      ]*[a-f0-9]+:    ff a3 08 00 00 00       jmp    \*0x8\(%ebx\)
+[      ]*[a-f0-9]+:    00 00                   add    %al,\(%eax\)
+       ...
+
+0+1e0 <\*ABS\*@plt>:
+[      ]*[a-f0-9]+:    ff a3 0c 00 00 00       jmp    \*0xc\(%ebx\)
+[      ]*[a-f0-9]+:    68 18 00 00 00          push   \$0x18
+[      ]*[a-f0-9]+:    e9 e0 ff ff ff          jmp    1d0 <\*ABS\*@plt-0x10>
+
+0+1f0 <func1@plt>:
+[      ]*[a-f0-9]+:    ff a3 10 00 00 00       jmp    \*0x10\(%ebx\)
+[      ]*[a-f0-9]+:    68 00 00 00 00          push   \$0x0
+[      ]*[a-f0-9]+:    e9 d0 ff ff ff          jmp    1d0 <\*ABS\*@plt-0x10>
+
+0+200 <func2@plt>:
+[      ]*[a-f0-9]+:    ff a3 14 00 00 00       jmp    \*0x14\(%ebx\)
+[      ]*[a-f0-9]+:    68 08 00 00 00          push   \$0x8
+[      ]*[a-f0-9]+:    e9 c0 ff ff ff          jmp    1d0 <\*ABS\*@plt-0x10>
+
+0+210 <\*ABS\*@plt>:
+[      ]*[a-f0-9]+:    ff a3 18 00 00 00       jmp    \*0x18\(%ebx\)
+[      ]*[a-f0-9]+:    68 10 00 00 00          push   \$0x10
+[      ]*[a-f0-9]+:    e9 b0 ff ff ff          jmp    1d0 <\*ABS\*@plt-0x10>
+
+Disassembly of section .text:
+
+0+220 <resolve1>:
+[      ]*[a-f0-9]+:    e8 cb ff ff ff          call   1f0 <func1@plt>
+
+0+225 <g1>:
+[      ]*[a-f0-9]+:    e9 e6 ff ff ff          jmp    210 <\*ABS\*@plt>
+
+0+22a <resolve2>:
+[      ]*[a-f0-9]+:    e8 d1 ff ff ff          call   200 <func2@plt>
+
+0+22f <g2>:
+[      ]*[a-f0-9]+:    e9 ac ff ff ff          jmp    1e0 <\*ABS\*@plt>
+#pass
 
--- /dev/null
+#source: pr17154-x86.s
+#as: --64
+#ld: -shared -melf_x86_64
+#objdump: -dw
+#target: x86_64-*-*
+
+#...
+0+2d0 <\*ABS\*\+0x32a@plt-0x10>:
+[      ]*[a-f0-9]+:    ff 35 5a 01 20 00       pushq  0x20015a\(%rip\)        # 200430 <_GLOBAL_OFFSET_TABLE_\+0x8>
+[      ]*[a-f0-9]+:    ff 25 5c 01 20 00       jmpq   \*0x20015c\(%rip\)        # 200438 <_GLOBAL_OFFSET_TABLE_\+0x10>
+[      ]*[a-f0-9]+:    0f 1f 40 00             nopl   0x0\(%rax\)
+
+0+2e0 <\*ABS\*\+0x32a@plt>:
+[      ]*[a-f0-9]+:    ff 25 5a 01 20 00       jmpq   \*0x20015a\(%rip\)        # 200440 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[      ]*[a-f0-9]+:    68 03 00 00 00          pushq  \$0x3
+[      ]*[a-f0-9]+:    e9 e0 ff ff ff          jmpq   2d0 <\*ABS\*\+0x32a@plt-0x10>
+
+0+2f0 <func1@plt>:
+[      ]*[a-f0-9]+:    ff 25 52 01 20 00       jmpq   \*0x200152\(%rip\)        # 200448 <_GLOBAL_OFFSET_TABLE_\+0x20>
+[      ]*[a-f0-9]+:    68 00 00 00 00          pushq  \$0x0
+[      ]*[a-f0-9]+:    e9 d0 ff ff ff          jmpq   2d0 <\*ABS\*\+0x32a@plt-0x10>
+
+0+300 <func2@plt>:
+[      ]*[a-f0-9]+:    ff 25 4a 01 20 00       jmpq   \*0x20014a\(%rip\)        # 200450 <_GLOBAL_OFFSET_TABLE_\+0x28>
+[      ]*[a-f0-9]+:    68 01 00 00 00          pushq  \$0x1
+[      ]*[a-f0-9]+:    e9 c0 ff ff ff          jmpq   2d0 <\*ABS\*\+0x32a@plt-0x10>
+
+0+310 <\*ABS\*\+0x320@plt>:
+[      ]*[a-f0-9]+:    ff 25 42 01 20 00       jmpq   \*0x200142\(%rip\)        # 200458 <_GLOBAL_OFFSET_TABLE_\+0x30>
+[      ]*[a-f0-9]+:    68 02 00 00 00          pushq  \$0x2
+[      ]*[a-f0-9]+:    e9 b0 ff ff ff          jmpq   2d0 <\*ABS\*\+0x32a@plt-0x10>
+
+Disassembly of section .text:
+
+0+320 <resolve1>:
+[      ]*[a-f0-9]+:    e8 cb ff ff ff          callq  2f0 <func1@plt>
+
+0+325 <g1>:
+[      ]*[a-f0-9]+:    e9 e6 ff ff ff          jmpq   310 <\*ABS\*\+0x320@plt>
+
+0+32a <resolve2>:
+[      ]*[a-f0-9]+:    e8 d1 ff ff ff          callq  300 <func2@plt>
+
+0+32f <g2>:
+[      ]*[a-f0-9]+:    e9 ac ff ff ff          jmpq   2e0 <\*ABS\*\+0x32a@plt>
+#pass
 
--- /dev/null
+       .text
+       .globl  fct1
+       .type   fct1, @gnu_indirect_function
+       .set    fct1,resolve1
+       .hidden int_fct1
+       .globl  int_fct1
+       .set    int_fct1,fct1
+       .type   resolve1, @function
+resolve1:
+       call    func1@PLT
+       .globl  g1
+       .type   g1, @function
+g1:
+       jmp     int_fct1@PLT
+
+       .globl  fct2
+       .type   fct2, @gnu_indirect_function
+       .set    fct2,resolve2
+       .hidden int_fct2
+       .globl  int_fct2
+       .set    int_fct2,fct2
+       .type   resolve2, @function
+resolve2:
+       call    func2@PLT
+       .globl  g2
+       .type   g2, @function
+g2:
+       jmp     int_fct2@PLT
 
--- /dev/null
+#as: --64 -madd-bnd-prefix
+#ld: -shared -melf_x86_64
+#objdump: -dw
+
+#...
+0+2d0 <.plt>:
+[      ]*[a-f0-9]+:    ff 35 7a 01 20 00       pushq  0x20017a\(%rip\)        # 200450 <_GLOBAL_OFFSET_TABLE_\+0x8>
+[      ]*[a-f0-9]+:    f2 ff 25 7b 01 20 00    bnd jmpq \*0x20017b\(%rip\)        # 200458 <_GLOBAL_OFFSET_TABLE_\+0x10>
+[      ]*[a-f0-9]+:    0f 1f 00                nopl   \(%rax\)
+[      ]*[a-f0-9]+:    68 03 00 00 00          pushq  \$0x3
+[      ]*[a-f0-9]+:    f2 e9 e5 ff ff ff       bnd jmpq 2d0 <\*ABS\*\+0x34c@plt-0x50>
+[      ]*[a-f0-9]+:    0f 1f 44 00 00          nopl   0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:    68 00 00 00 00          pushq  \$0x0
+[      ]*[a-f0-9]+:    f2 e9 d5 ff ff ff       bnd jmpq 2d0 <\*ABS\*\+0x34c@plt-0x50>
+[      ]*[a-f0-9]+:    0f 1f 44 00 00          nopl   0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:    68 01 00 00 00          pushq  \$0x1
+[      ]*[a-f0-9]+:    f2 e9 c5 ff ff ff       bnd jmpq 2d0 <\*ABS\*\+0x34c@plt-0x50>
+[      ]*[a-f0-9]+:    0f 1f 44 00 00          nopl   0x0\(%rax,%rax,1\)
+[      ]*[a-f0-9]+:    68 02 00 00 00          pushq  \$0x2
+[      ]*[a-f0-9]+:    f2 e9 b5 ff ff ff       bnd jmpq 2d0 <\*ABS\*\+0x34c@plt-0x50>
+[      ]*[a-f0-9]+:    0f 1f 44 00 00          nopl   0x0\(%rax,%rax,1\)
+
+Disassembly of section .plt.bnd:
+
+0+320 <\*ABS\*\+0x34c@plt>:
+[      ]*[a-f0-9]+:    f2 ff 25 39 01 20 00    bnd jmpq \*0x200139\(%rip\)        # 200460 <_GLOBAL_OFFSET_TABLE_\+0x18>
+[      ]*[a-f0-9]+:    90                      nop
+
+0+328 <func1@plt>:
+[      ]*[a-f0-9]+:    f2 ff 25 39 01 20 00    bnd jmpq \*0x200139\(%rip\)        # 200468 <_GLOBAL_OFFSET_TABLE_\+0x20>
+[      ]*[a-f0-9]+:    90                      nop
+
+0+330 <func2@plt>:
+[      ]*[a-f0-9]+:    f2 ff 25 39 01 20 00    bnd jmpq \*0x200139\(%rip\)        # 200470 <_GLOBAL_OFFSET_TABLE_\+0x28>
+[      ]*[a-f0-9]+:    90                      nop
+
+0+338 <\*ABS\*\+0x340@plt>:
+[      ]*[a-f0-9]+:    f2 ff 25 39 01 20 00    bnd jmpq \*0x200139\(%rip\)        # 200478 <_GLOBAL_OFFSET_TABLE_\+0x30>
+[      ]*[a-f0-9]+:    90                      nop
+
+Disassembly of section .text:
+
+0+340 <resolve1>:
+[      ]*[a-f0-9]+:    f2 e8 e2 ff ff ff       bnd callq 328 <func1@plt>
+
+0+346 <g1>:
+[      ]*[a-f0-9]+:    f2 e9 ec ff ff ff       bnd jmpq 338 <\*ABS\*\+0x340@plt>
+
+0+34c <resolve2>:
+[      ]*[a-f0-9]+:    f2 e8 de ff ff ff       bnd callq 330 <func2@plt>
+
+0+352 <g2>:
+[      ]*[a-f0-9]+:    f2 e9 c8 ff ff ff       bnd jmpq 320 <\*ABS\*\+0x34c@plt>
+#pass
 
--- /dev/null
+       .text
+       .globl  fct1
+       .type   fct1, @gnu_indirect_function
+       .set    fct1,resolve1
+       .hidden int_fct1
+       .globl  int_fct1
+       .set    int_fct1,fct1
+       .type   resolve1, @function
+resolve1:
+       call    func1@PLT
+       .globl  g1
+       .type   g1, @function
+g1:
+       jmp     int_fct1@PLT
+
+       .globl  fct2
+       .type   fct2, @gnu_indirect_function
+       .set    fct2,resolve2
+       .hidden int_fct2
+       .globl  int_fct2
+       .set    int_fct2,fct2
+       .type   resolve2, @function
+resolve2:
+       call    func2@PLT
+       .globl  g2
+       .type   g2, @function
+g2:
+       jmp     int_fct2@PLT
 
 
 run_dump_test "bnd-branch-1"
 run_dump_test "bnd-ifunc-1"
+run_dump_test "bnd-ifunc-2"
 run_dump_test "bnd-plt-1"
 
 
 Disassembly of section .plt:
 
-[0-9a-f]+ <.*@plt-0x40>:
+[0-9a-f]+ <.plt>:
  +[0-9a-f]+:   ff 35 .. .. .. ..       pushq  0x[0-9a-f]+\(%rip\) +# [0-9a-f]+ <_GLOBAL_OFFSET_TABLE_\+0x8>
  +[0-9a-f]+:   4c 8b 1d .. .. .. ..    mov    0x[0-9a-f]+\(%rip\),%r11 +# [0-9a-f]+ <_GLOBAL_OFFSET_TABLE_\+0x10>
  +[0-9a-f]+:   41 83 e3 e0             and    \$0xffffffe0,%r11d
  +[0-9a-f]+:   0f 1f 84 00 00 00 00 *
  +[0-9a-f]+:   00 *
  +[0-9a-f]+:   66 90                   xchg   %ax,%ax
-
-[0-9a-f]+ <.*@plt>:
  +[0-9a-f]+:   ff 35 .. .. .. ..       pushq  0x[0-9a-f]+\(%rip\) +# [0-9a-f]+ <_GLOBAL_OFFSET_TABLE_\+0x8>
  +[0-9a-f]+:   4c 8b 1d .. .. .. ..    mov    0x[0-9a-f]+\(%rip\),%r11 +# [0-9a-f]+ <_DYNAMIC\+0x190>
  +[0-9a-f]+:   41 83 e3 e0             and    \$0xffffffe0,%r11d
 
 
 Disassembly of section .plt:
 
-[0-9a-f]+ <.*@plt-0x10>:
+[0-9a-f]+ <.plt>:
  [0-9a-f]+:    ff 35 .. .. 20 00       pushq  .*\(%rip\)        # 201358 <_GLOBAL_OFFSET_TABLE_\+0x8>
  [0-9a-f]+:    ff 25 .. .. 20 00       jmpq   \*.*\(%rip\)        # 201360 <_GLOBAL_OFFSET_TABLE_\+0x10>
  [0-9a-f]+:    0f 1f 40 00             nopl   0x0\(%rax\)
-[0-9a-f]+ <.*@plt>:
  [0-9a-f]+:    ff 35 .. .. 20 00       pushq  .*\(%rip\)        # 201358 <_GLOBAL_OFFSET_TABLE_\+0x8>
  [0-9a-f]+:    ff 25 .. .. 20 00       jmpq   \*.*\(%rip\)        # 201348 <_DYNAMIC\+0x190>
  [0-9a-f]+:    0f 1f 40 00             nopl   0x0\(%rax\)