+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
- 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;
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-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.
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*"]
"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