+2016-06-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from master
+ 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
+ GOT32 adjustment for static executables.
+
2016-06-14 H.J. Lu <hongjiu.lu@intel.com>
Backport from master
}
relocation = off;
-
- /* Adjust for static executables. */
- if (htab->elf.splt == NULL)
- relocation += gotplt->output_offset;
}
else
+ relocation = (base_got->output_section->vma
+ + base_got->output_offset + off
+ - gotplt->output_section->vma
+ - 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)
{
- relocation = (base_got->output_section->vma
- + base_got->output_offset + off
- - gotplt->output_section->vma
- - gotplt->output_offset);
/* Adjust for static executables. */
- if (htab->elf.splt == NULL)
- relocation += gotplt->output_offset;
+ relocation += gotplt->output_offset;
}
goto do_relocation;
is. */
const char *name;
+disallow_got32:
if (h == NULL)
name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
NULL);
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;
}
+2016-06-14 H.J. Lu <hongjiu.lu@intel.com>
+
+ Backport from master
+ 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.
+ * testsuite/ld-i386/ifunc-1a.c: New file.
+ * testsuite/ld-i386/ifunc-1b.S: Likewise.
+ * testsuite/ld-i386/ifunc-1c.S: Likewise.
+ * testsuite/ld-i386/ifunc-1d.S: Likewise.
+
2016-06-14 H.J. Lu <hongjiu.lu@intel.com>
Backport from master
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*"]
]
}
+# Must be native with the C compiler and working IFUNC support,
+if { [isnative]
+ && [check_ifunc_available]
+ && [istarget "i?86-*-*"]
+ && [which $CC] != 0 } {
+ run_cc_link_tests [list \
+ [list \
+ "Build ifunc-1a.o ifunc-1b.o ifunc-1c.o ifunc-1d.o" \
+ "" \
+ "-fPIC -O2 -g" \
+ { ifunc-1a.c ifunc-1b.S ifunc-1c.S ifunc-1d.S } \
+ ] \
+ ]
+
+ run_ld_link_exec_tests [] [list \
+ [list \
+ "Run ifunc-1a" \
+ "tmpdir/ifunc-1a.o tmpdir/ifunc-1b.o \
+ tmpdir/ifunc-1c.o tmpdir/ifunc-1d.o" \
+ "" \
+ { dummy.c } \
+ "ifunc-1a" \
+ "pass.out" \
+ ] \
+ [list \
+ "Run ifunc-1b" \
+ "--static tmpdir/ifunc-1a.o tmpdir/ifunc-1b.o \
+ tmpdir/ifunc-1c.o tmpdir/ifunc-1d.o" \
+ "" \
+ { dummy.c } \
+ "ifunc-1b" \
+ "pass.out" \
+ ] \
+ ]
+}
+
if { !([istarget "i?86-*-linux*"]
|| [istarget "x86_64-*-linux*"]) } {
return
--- /dev/null
+extern void check (void);
+
+int
+main ()
+{
+ check ();
+ return 0;
+}
--- /dev/null
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC0:
+ .string "PASS"
+ .text
+ .p2align 4,,15
+ .globl check
+ .type check, @function
+check:
+ pushl %ebx
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ subl $8, %esp
+ call *get_func1@GOT(%ebx)
+ cmpl func1@GOT(%ebx), %eax
+ jne .L3
+ call *func1@GOT(%ebx)
+ cmpl $1, %eax
+ jne .L3
+ call *call_func1@GOT(%ebx)
+ cmpl $1, %eax
+ jne .L3
+ call *call_func2@GOT(%ebx)
+ cmpl $2, %eax
+ jne .L3
+ leal .LC0@GOTOFF(%ebx), %eax
+ subl $12, %esp
+ pushl %eax
+ call *puts@GOT(%ebx)
+ addl $24, %esp
+ popl %ebx
+ ret
+.L3:
+ call *abort@GOT(%ebx)
+ .size check, .-check
+ .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+ .globl __x86.get_pc_thunk.bx
+ .hidden __x86.get_pc_thunk.bx
+ .type __x86.get_pc_thunk.bx, @function
+__x86.get_pc_thunk.bx:
+ movl (%esp), %ebx
+ ret
+ .section .note.GNU-stack,"",@progbits
--- /dev/null
+ .text
+ .p2align 4,,15
+ .globl get_func1
+ .type get_func1, @function
+get_func1:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ movl func1@GOT(%eax), %eax
+ ret
+ .size get_func1, .-get_func1
+ .p2align 4,,15
+ .globl call_func1
+ .type call_func1, @function
+call_func1:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ jmp *func1@GOT(%eax)
+ .size call_func1, .-call_func1
+ .section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
+ .globl __x86.get_pc_thunk.ax
+ .hidden __x86.get_pc_thunk.ax
+ .type __x86.get_pc_thunk.ax, @function
+__x86.get_pc_thunk.ax:
+ movl (%esp), %eax
+ ret
+ .section .note.GNU-stack,"",@progbits
--- /dev/null
+ .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:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ leal implementation2@GOTOFF(%eax), %eax
+ ret
+ .size resolver2, .-resolver2
+ .type func2, @gnu_indirect_function
+ .set func2,resolver2
+ .p2align 4,,15
+ .type resolver1, @function
+resolver1:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ leal implementation1@GOTOFF(%eax), %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:
+ call __x86.get_pc_thunk.ax
+ addl $_GLOBAL_OFFSET_TABLE_, %eax
+ movl func2@GOT(%eax), %eax
+ ret
+ .size get_func2, .-get_func2
+ .p2align 4,,15
+ .globl call_func2
+ .type call_func2, @function
+call_func2:
+ pushl %ebx
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ subl $8, %esp
+ call *get_func2@GOT(%ebx)
+ cmpl func2@GOT(%ebx), %eax
+ jne .L10
+ addl $8, %esp
+ movl %ebx, %eax
+ popl %ebx
+ jmp *func2@GOT(%eax)
+.L10:
+ call *abort@GOT(%ebx)
+ .size call_func2, .-call_func2
+ .section .text.__x86.get_pc_thunk.ax,"axG",@progbits,__x86.get_pc_thunk.ax,comdat
+ .globl __x86.get_pc_thunk.ax
+ .hidden __x86.get_pc_thunk.ax
+ .type __x86.get_pc_thunk.ax, @function
+__x86.get_pc_thunk.ax:
+ movl (%esp), %eax
+ ret
+ .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+ .globl __x86.get_pc_thunk.bx
+ .hidden __x86.get_pc_thunk.bx
+ .type __x86.get_pc_thunk.bx, @function
+__x86.get_pc_thunk.bx:
+ movl (%esp), %ebx
+ ret
+ .section .note.GNU-stack,"",@progbits
"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" \
+ ] \
+ ]
+}
--- /dev/null
+ .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
--- /dev/null
+#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
--- /dev/null
+#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 ....
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+extern void check (void);
+
+int
+main ()
+{
+ check ();
+ return 0;
+}
--- /dev/null
+ .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
--- /dev/null
+ .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
--- /dev/null
+ .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