Add the GOT base for GOT32 relocs against IFUNC
authorH.J. Lu <hjl.tools@gmail.com>
Mon, 13 Jun 2016 18:06:10 +0000 (11:06 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Mon, 13 Jun 2016 18:11:23 +0000 (11:11 -0700)
Add the GOT base for R_386_GOT32/R_386_GOT32X relocations against IFUNC
symbols if there is no base register and disallow them for PIC.

bfd/

PR ld/20244
* elf32-i386.c (elf_i386_relocate_section): Add the .got.plt
section address for R_386_GOT32/R_386_GOT32X relocations against
IFUNC symbols if there is no base register and return error for
PIC.

ld/

PR ld/20244
* testsuite/ld-i386/i386.exp: Run pr20244-2a, pr20244-2b,
pr20244-2c and pr20244-2d.
* testsuite/ld-i386/no-plt.exp: Run pr20244-3a and pr20244-3b.
* testsuite/ld-i386/pr20244-2.s: New file.
* testsuite/ld-i386/pr20244-2a.d: Likewise.
* testsuite/ld-i386/pr20244-2b.d: Likewise.
* testsuite/ld-i386/pr20244-2c.d: Likewise.
* testsuite/ld-i386/pr20244-2d.d: Likewise.
* testsuite/ld-i386/pr20244-3a.c: Likewise.
* testsuite/ld-i386/pr20244-3b.S: Likewise.
* testsuite/ld-i386/pr20244-3c.S: Likewise.
* testsuite/ld-i386/pr20244-3d.S: Likewise.

14 files changed:
bfd/ChangeLog
bfd/elf32-i386.c
ld/ChangeLog
ld/testsuite/ld-i386/i386.exp
ld/testsuite/ld-i386/no-plt.exp
ld/testsuite/ld-i386/pr20244-2.s [new file with mode: 0644]
ld/testsuite/ld-i386/pr20244-2a.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr20244-2b.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr20244-2c.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr20244-2d.d [new file with mode: 0644]
ld/testsuite/ld-i386/pr20244-3a.c [new file with mode: 0644]
ld/testsuite/ld-i386/pr20244-3b.S [new file with mode: 0644]
ld/testsuite/ld-i386/pr20244-3c.S [new file with mode: 0644]
ld/testsuite/ld-i386/pr20244-3d.S [new file with mode: 0644]

index 2a1ae1313305892f8442045f2136c4497d371859..9cfd09e10cf061c2288b41c64273f717a29b700b 100644 (file)
@@ -1,3 +1,11 @@
+2016-06-13  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/20244
+       * elf32-i386.c (elf_i386_relocate_section): Add the .got.plt
+       section address for R_386_GOT32/R_386_GOT32X relocations against
+       IFUNC symbols if there is no base register and return error for
+       PIC.
+
 2016-06-13  H.J. Lu  <hongjiu.lu@intel.com>
 
        * elf32-i386.c (elf_i386_relocate_section): Simplify IFUNC
index fbbf4ab8f70dc9dc07bad39c5e01b56a3dfc15fc..a68ce1fc1862556c5e4a84cfe285c7f040d6879b 100644 (file)
@@ -4039,9 +4039,20 @@ elf_i386_relocate_section (bfd *output_bfd,
                              - gotplt->output_section->vma
                              - gotplt->output_offset);
 
-             /* Adjust for static executables.  */
-             if (htab->elf.splt == NULL)
-               relocation += gotplt->output_offset;
+             if ((*(contents + rel->r_offset - 1) & 0xc7) == 0x5)
+               {
+                 if (bfd_link_pic (info))
+                   goto disallow_got32;
+
+                 /* Add the GOT base if there is no base register.  */
+                 relocation += (gotplt->output_section->vma
+                                + gotplt->output_offset);
+               }
+             else if (htab->elf.splt == NULL)
+               {
+                 /* Adjust for static executables.  */
+                 relocation += gotplt->output_offset;
+               }
 
              goto do_relocation;
 
@@ -4214,6 +4225,7 @@ r_386_got32:
                     is.  */
                  const char *name;
 
+disallow_got32:
                  if (h == NULL)
                    name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
                                             NULL);
@@ -4221,8 +4233,8 @@ r_386_got32:
                    name = h->root.root.string;
 
                  (*_bfd_error_handler)
-                   (_("%B: direct GOT relocation R_386_GOT32 against `%s' without base register can not be used when making a shared object"),
-                    input_bfd, name);
+                   (_("%B: direct GOT relocation %s against `%s' without base register can not be used when making a shared object"),
+                    input_bfd, howto->name, name);
                  bfd_set_error (bfd_error_bad_value);
                  return FALSE;
                }
index a8cceb86eec5af4c2612a37b485a4b6d93d4ad60..e5614ba2b9afd10534c7a0ca0cf5c36493bc6779 100644 (file)
@@ -1,3 +1,19 @@
+2016-06-13  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/20244
+       * testsuite/ld-i386/i386.exp: Run pr20244-2a, pr20244-2b,
+       pr20244-2c and pr20244-2d.
+       * testsuite/ld-i386/no-plt.exp: Run pr20244-3a and pr20244-3b.
+       * testsuite/ld-i386/pr20244-2.s: New file.
+       * testsuite/ld-i386/pr20244-2a.d: Likewise.
+       * testsuite/ld-i386/pr20244-2b.d: Likewise.
+       * testsuite/ld-i386/pr20244-2c.d: Likewise.
+       * testsuite/ld-i386/pr20244-2d.d: Likewise.
+       * testsuite/ld-i386/pr20244-3a.c: Likewise.
+       * testsuite/ld-i386/pr20244-3b.S: Likewise.
+       * testsuite/ld-i386/pr20244-3c.S: Likewise.
+       * testsuite/ld-i386/pr20244-3d.S: Likewise.
+
 2016-06-13  H.J. Lu  <hongjiu.lu@intel.com>
 
        * testsuite/ld-i386/i386.exp: Run ifunc-1a and ifunc-1b.
index 93f11efc1afd0e97fcb80a176df9a7483c6a611c..846892035dbb19406170242a5075e442ccf93115 100644 (file)
@@ -403,6 +403,10 @@ run_dump_test "pr20117"
 run_dump_test "pr20244-1a"
 run_dump_test "pr20244-1b"
 run_dump_test "pr20244-1c"
+run_dump_test "pr20244-2a"
+run_dump_test "pr20244-2b"
+run_dump_test "pr20244-2c"
+run_dump_test "pr20244-2d"
 
 if { !([istarget "i?86-*-linux*"]
        || [istarget "i?86-*-gnu*"]
index 87d64b9d5a1c8633cec11b8294c4670156386875..c4af0a9b6905fd3e83c7cd4f21d5b29d2cee36fa 100644 (file)
@@ -255,3 +255,36 @@ run_ld_link_exec_tests [] [list \
        "pass.out" \
     ] \
 ]
+
+# Run-time tests which require working IFUNC support.
+if { [check_ifunc_available] } {
+    run_cc_link_tests [list \
+       [list \
+           "Build pr20244-3a.o pr20244-3b.o pr20244-3c.o pr20244-3d.o" \
+           "" \
+           "-fPIC -O2 -g" \
+           { pr20244-3a.c pr20244-3b.S pr20244-3c.S pr20244-3d.S } \
+       ] \
+    ]
+
+    run_ld_link_exec_tests [] [list \
+       [list \
+           "Run pr20244-3a" \
+           "tmpdir/pr20244-3a.o tmpdir/pr20244-3b.o \
+            tmpdir/pr20244-3c.o tmpdir/pr20244-3d.o" \
+           "" \
+           { dummy.c } \
+           "pr20244-3a" \
+           "pass.out" \
+       ] \
+       [list \
+           "Run pr20244-3b" \
+           "--static tmpdir/pr20244-3a.o tmpdir/pr20244-3b.o \
+           tmpdir/pr20244-3c.o tmpdir/pr20244-3d.o" \
+           "" \
+           { dummy.c } \
+           "pr20244-3b" \
+           "pass.out" \
+       ] \
+    ]
+}
diff --git a/ld/testsuite/ld-i386/pr20244-2.s b/ld/testsuite/ld-i386/pr20244-2.s
new file mode 100644 (file)
index 0000000..283815a
--- /dev/null
@@ -0,0 +1,17 @@
+       .text
+       .globl  foo
+       .type   foo, @gnu_indirect_function
+foo:
+       ret
+       .text
+       .type   bar, @gnu_indirect_function
+bar:
+       ret
+       .globl  _start
+       .type   _start, @function
+_start:
+       call    *foo@GOT
+       jmp     *bar@GOT
+       movl    $0, bar@GOT
+       cmpl    $0, foo@GOT
+       movl    $bar@GOT, %ecx
diff --git a/ld/testsuite/ld-i386/pr20244-2a.d b/ld/testsuite/ld-i386/pr20244-2a.d
new file mode 100644 (file)
index 0000000..a04902f
--- /dev/null
@@ -0,0 +1,43 @@
+#source: pr20244-2.s
+#as: --32
+#ld: -m elf_i386
+#objdump: --sym -dw
+#notarget: i?86-*-nacl* x86_64-*-nacl*
+
+.*: +file format .*
+
+SYMBOL TABLE:
+#...
+0+80480b1 l   i   .text        00000000 bar
+#...
+0+80480b2 g     F .text        00000000 _start
+#...
+0+80480b0 g   i   .text        00000000 foo
+#...
+
+
+Disassembly of section .plt:
+
+0+8048090 <.plt>:
+ +[a-f0-9]+:   ff 25 e0 90 04 08       jmp    \*0x80490e0
+ +[a-f0-9]+:   68 00 00 00 00          push   \$0x0
+ +[a-f0-9]+:   e9 00 00 00 00          jmp    80480a0 <foo-0x10>
+ +[a-f0-9]+:   ff 25 e4 90 04 08       jmp    \*0x80490e4
+ +[a-f0-9]+:   68 00 00 00 00          push   \$0x0
+ +[a-f0-9]+:   e9 00 00 00 00          jmp    80480b0 <foo>
+
+Disassembly of section .text:
+
+0+80480b0 <foo>:
+ +[a-f0-9]+:   c3                      ret    
+
+0+80480b1 <bar>:
+ +[a-f0-9]+:   c3                      ret    
+
+0+80480b2 <_start>:
+ +[a-f0-9]+:   ff 15 e0 90 04 08       call   \*0x80490e0
+ +[a-f0-9]+:   ff 25 e4 90 04 08       jmp    \*0x80490e4
+ +[a-f0-9]+:   c7 05 e4 90 04 08 00 00 00 00   movl   \$0x0,0x80490e4
+ +[a-f0-9]+:   83 3d e0 90 04 08 00    cmpl   \$0x0,0x80490e0
+ +[a-f0-9]+:   b9 10 00 00 00          mov    \$0x10,%ecx
+#pass
diff --git a/ld/testsuite/ld-i386/pr20244-2b.d b/ld/testsuite/ld-i386/pr20244-2b.d
new file mode 100644 (file)
index 0000000..fc0fa17
--- /dev/null
@@ -0,0 +1,11 @@
+#source: pr20244-2.s
+#as: --32
+#ld: -m elf_i386
+#objdump: -s -j .got.plt
+#notarget: i?86-*-nacl* x86_64-*-nacl*
+
+.*: +file format .*
+
+Contents of section .got.plt:
+ 80490d4 00000000 00000000 00000000 b0800408  ................
+ 80490e4 b1800408                             ....            
diff --git a/ld/testsuite/ld-i386/pr20244-2c.d b/ld/testsuite/ld-i386/pr20244-2c.d
new file mode 100644 (file)
index 0000000..54eee9f
--- /dev/null
@@ -0,0 +1,10 @@
+#source: pr20244-2.s
+#as: --32
+#ld: -m elf_i386
+#readelf: -rW
+#notarget: i?86-*-nacl* x86_64-*-nacl*
+
+Relocation section '.rel.plt' at offset 0x74 contains 2 entries:
+ Offset     Info    Type                Sym. Value  Symbol's Name
+0+80490e4  0000002a R_386_IRELATIVE       
+0+80490e0  0000002a R_386_IRELATIVE       
diff --git a/ld/testsuite/ld-i386/pr20244-2d.d b/ld/testsuite/ld-i386/pr20244-2d.d
new file mode 100644 (file)
index 0000000..c423bf7
--- /dev/null
@@ -0,0 +1,4 @@
+#source: pr20244-2.s
+#as: --32
+#ld: -pie -m elf_i386
+#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object
diff --git a/ld/testsuite/ld-i386/pr20244-3a.c b/ld/testsuite/ld-i386/pr20244-3a.c
new file mode 100644 (file)
index 0000000..370275a
--- /dev/null
@@ -0,0 +1,8 @@
+extern void check (void);
+
+int
+main ()
+{
+  check ();
+  return 0;
+}
diff --git a/ld/testsuite/ld-i386/pr20244-3b.S b/ld/testsuite/ld-i386/pr20244-3b.S
new file mode 100644 (file)
index 0000000..83880da
--- /dev/null
@@ -0,0 +1,30 @@
+       .section        .rodata.str1.1,"aMS",@progbits,1
+.LC0:
+       .string "PASS"
+       .text
+       .p2align 4,,15
+       .globl  check
+       .type   check, @function
+check:
+       subl    $12, %esp
+       call    *get_func1@GOT
+       cmpl    $func1, %eax
+       jne     .L3
+       call    *func1@GOT
+       cmpl    $1, %eax
+       jne     .L3
+       call    *call_func1@GOT
+       cmpl    $1, %eax
+       jne     .L3
+       call    *call_func2@GOT
+       cmpl    $2, %eax
+       jne     .L3
+       subl    $12, %esp
+       pushl   $.LC0
+       call    *puts@GOT
+       addl    $28, %esp
+       ret
+.L3:
+       call    *abort@GOT
+       .size   check, .-check
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-i386/pr20244-3c.S b/ld/testsuite/ld-i386/pr20244-3c.S
new file mode 100644 (file)
index 0000000..0b90013
--- /dev/null
@@ -0,0 +1,15 @@
+       .text
+       .p2align 4,,15
+       .globl  get_func1
+       .type   get_func1, @function
+get_func1:
+       movl    func1@GOT, %eax
+       ret
+       .size   get_func1, .-get_func1
+       .p2align 4,,15
+       .globl  call_func1
+       .type   call_func1, @function
+call_func1:
+       jmp     *func1@GOT
+       .size   call_func1, .-call_func1
+       .section        .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-i386/pr20244-3d.S b/ld/testsuite/ld-i386/pr20244-3d.S
new file mode 100644 (file)
index 0000000..a57f3fc
--- /dev/null
@@ -0,0 +1,44 @@
+       .text
+       .p2align 4,,15
+       .type   implementation1, @function
+implementation1:
+       movl    $1, %eax
+       ret
+       .size   implementation1, .-implementation1
+       .p2align 4,,15
+       .type   implementation2, @function
+implementation2:
+       movl    $2, %eax
+       ret
+       .size   implementation2, .-implementation2
+       .p2align 4,,15
+       .type   resolver2, @function
+resolver2:
+       movl    implementation2@GOT, %eax
+       ret
+       .size   resolver2, .-resolver2
+       .type   func2, @gnu_indirect_function
+       .set    func2,resolver2
+       .p2align 4,,15
+       .type   resolver1, @function
+resolver1:
+       movl    implementation1@GOT, %eax
+       ret
+       .size   resolver1, .-resolver1
+       .globl  func1
+       .type   func1, @gnu_indirect_function
+       .set    func1,resolver1
+       .p2align 4,,15
+       .globl  get_func2
+       .type   get_func2, @function
+get_func2:
+       movl    func2@GOT, %eax
+       ret
+       .size   get_func2, .-get_func2
+       .p2align 4,,15
+       .globl  call_func2
+       .type   call_func2, @function
+call_func2:
+       jmp     *func2@GOT
+       .size   call_func2, .-call_func2
+       .section        .note.GNU-stack,"",@progbits