summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2016-06-13 11:06:10 -0700
committerH.J. Lu <hjl.tools@gmail.com>2016-06-13 11:11:23 -0700
commit712ec27916b5604d29d928dec060fd1ba0fd9edb (patch)
tree221a14aa497e282aad40ccacf3bd8abbe30a9de8
parentca8c86efe7765262e25ebb08004012ba2fdadf52 (diff)
downloadbinutils-gdb-712ec27916b5604d29d928dec060fd1ba0fd9edb.tar.gz
Add the GOT base for GOT32 relocs against IFUNC
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.
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elf32-i386.c22
-rw-r--r--ld/ChangeLog16
-rw-r--r--ld/testsuite/ld-i386/i386.exp4
-rw-r--r--ld/testsuite/ld-i386/no-plt.exp33
-rw-r--r--ld/testsuite/ld-i386/pr20244-2.s17
-rw-r--r--ld/testsuite/ld-i386/pr20244-2a.d43
-rw-r--r--ld/testsuite/ld-i386/pr20244-2b.d11
-rw-r--r--ld/testsuite/ld-i386/pr20244-2c.d10
-rw-r--r--ld/testsuite/ld-i386/pr20244-2d.d4
-rw-r--r--ld/testsuite/ld-i386/pr20244-3a.c8
-rw-r--r--ld/testsuite/ld-i386/pr20244-3b.S30
-rw-r--r--ld/testsuite/ld-i386/pr20244-3c.S15
-rw-r--r--ld/testsuite/ld-i386/pr20244-3d.S44
14 files changed, 260 insertions, 5 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 2a1ae131330..9cfd09e10cf 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,13 @@
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.
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index fbbf4ab8f70..a68ce1fc186 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -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;
}
diff --git a/ld/ChangeLog b/ld/ChangeLog
index a8cceb86eec..e5614ba2b9a 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,21 @@
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.
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 93f11efc1af..846892035db 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -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*"]
diff --git a/ld/testsuite/ld-i386/no-plt.exp b/ld/testsuite/ld-i386/no-plt.exp
index 87d64b9d5a1..c4af0a9b690 100644
--- a/ld/testsuite/ld-i386/no-plt.exp
+++ b/ld/testsuite/ld-i386/no-plt.exp
@@ -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
index 00000000000..283815a9e7e
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20244-2.s
@@ -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
index 00000000000..a04902fb0fa
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20244-2a.d
@@ -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
index 00000000000..fc0fa17ca07
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20244-2b.d
@@ -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
index 00000000000..54eee9f9c29
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20244-2c.d
@@ -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
index 00000000000..c423bf787ed
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20244-2d.d
@@ -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
index 00000000000..370275a0768
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20244-3a.c
@@ -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
index 00000000000..83880da6d6b
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20244-3b.S
@@ -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
index 00000000000..0b900136974
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20244-3c.S
@@ -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
index 00000000000..a57f3fc1c1a
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr20244-3d.S
@@ -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