aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-09-01 05:06:16 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-09-01 05:06:33 -0700
commit04ebc307f9601168c165fb63aa39a676e45454b7 (patch)
tree3db90b1dba71a706df7edb2f28a6e2104587ebdd /ld
parentb07bca4ecd27f9cbaff822e4135abaf0ae6cd0db (diff)
downloadbinutils-04ebc307f9601168c165fb63aa39a676e45454b7.zip
binutils-04ebc307f9601168c165fb63aa39a676e45454b7.tar.gz
binutils-04ebc307f9601168c165fb63aa39a676e45454b7.tar.bz2
Skip PLT for function pointer initialization
We use its PLT entry to initialize function pointer at run-time. If there is no other usage for the PLT entry, we can generate run-time function pointer relocations in read-write section, which can be resolved by dynamic linker, to initialize function pointers. It avoids the extra indirect branch overhead in PLT. bfd/ PR ld/18900 * elf32-i386.c (elf_i386_link_hash_entry): Add func_pointer_refcount. (elf_i386_link_hash_newfunc): Clear func_pointer_refcount. (elf_i386_get_local_sym_hash): Likewise. (elf_i386_copy_indirect_symbol): Also copy func_pointer_refcount. (elf_i386_check_relocs): Increment func_pointer_refcount. (elf_i386_gc_sweep_hook): Decrement func_pointer_refcount. (elf_i386_allocate_dynrelocs): Don't create the PLT entry if there are only function pointer relocations which can be resolved at run-time. Keep dynanamic relocations for run-time function pointer initialization. (elf_i386_relocate_section): Copy dynamic function pointer relocations. * elf64-x86-64.c (elf_x86_64_link_hash_entry): Add func_pointer_refcount. (elf_x86_64_link_hash_newfunc): Clear func_pointer_refcount. (elf_x86_64_get_local_sym_hash): Likewise. (elf_x86_64_copy_indirect_symbol): Also copy func_pointer_refcount. (elf_x86_64_check_relocs): Increment func_pointer_refcount. (elf_x86_64_gc_sweep_hook): Decrement func_pointer_refcount. (elf_x86_64_allocate_dynrelocs): Don't create the PLT entry if there are only function pointer relocations which can be resolved at run-time. Keep dynanamic relocations for run-time function pointer initialization. (elf_x86_64_relocate_section): Copy dynamic function pointer relocations. ld/testsuite/ PR ld/18900 * ld-i386/i386.exp: Run tests for PR ld/18900. * ld-x86-64/x86-64.exp: Likewise. * ld-i386/pr18900.out: New file. * ld-i386/pr18900a.c: Likewise. * ld-i386/pr18900a.c: Likewise. * ld-i386/pr18900a.rd: Likewise. * ld-i386/pr18900b.c: Likewise. * ld-i386/pr18900b.rd: Likewise. * ld-i386/pr18900c.c: Likewise. * ld-x86-64/pr18900.out: Likewise. * ld-x86-64/pr18900a.c: Likewise. * ld-x86-64/pr18900a.rd: Likewise. * ld-x86-64/pr18900b.c: Likewise. * ld-x86-64/pr18900b.rd: Likewise. * ld-x86-64/pr18900c.c: Likewise. * ld-x86-64/mpx3.dd: Updated.
Diffstat (limited to 'ld')
-rw-r--r--ld/testsuite/ChangeLog20
-rw-r--r--ld/testsuite/ld-i386/i386.exp32
-rw-r--r--ld/testsuite/ld-i386/pr18900.out4
-rw-r--r--ld/testsuite/ld-i386/pr18900a.c14
-rw-r--r--ld/testsuite/ld-i386/pr18900a.rd4
-rw-r--r--ld/testsuite/ld-i386/pr18900b.c22
-rw-r--r--ld/testsuite/ld-i386/pr18900b.rd4
-rw-r--r--ld/testsuite/ld-i386/pr18900c.c5
-rw-r--r--ld/testsuite/ld-x86-64/mpx3.dd25
-rw-r--r--ld/testsuite/ld-x86-64/pr18900.out4
-rw-r--r--ld/testsuite/ld-x86-64/pr18900a.c14
-rw-r--r--ld/testsuite/ld-x86-64/pr18900a.rd4
-rw-r--r--ld/testsuite/ld-x86-64/pr18900b.c22
-rw-r--r--ld/testsuite/ld-x86-64/pr18900b.rd4
-rw-r--r--ld/testsuite/ld-x86-64/pr18900c.c5
-rw-r--r--ld/testsuite/ld-x86-64/x86-64.exp32
16 files changed, 199 insertions, 16 deletions
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 7650cda..0241c08 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,23 @@
+2015-09-01 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/18900
+ * ld-i386/i386.exp: Run tests for PR ld/18900.
+ * ld-x86-64/x86-64.exp: Likewise.
+ * ld-i386/pr18900.out: New file.
+ * ld-i386/pr18900a.c: Likewise.
+ * ld-i386/pr18900a.c: Likewise.
+ * ld-i386/pr18900a.rd: Likewise.
+ * ld-i386/pr18900b.c: Likewise.
+ * ld-i386/pr18900b.rd: Likewise.
+ * ld-i386/pr18900c.c: Likewise.
+ * ld-x86-64/pr18900.out: Likewise.
+ * ld-x86-64/pr18900a.c: Likewise.
+ * ld-x86-64/pr18900a.rd: Likewise.
+ * ld-x86-64/pr18900b.c: Likewise.
+ * ld-x86-64/pr18900b.rd: Likewise.
+ * ld-x86-64/pr18900c.c: Likewise.
+ * ld-x86-64/mpx3.dd: Updated.
+
2015-08-27 Alan Modra <amodra@gmail.com>
* ld-powerpc/relocsort.s, * ld-powerpc/relocsort.d: New test.
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index 47911a6..6213dbe 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -466,6 +466,30 @@ if { [isnative]
{{readelf {-Wr} pr17827.rd}} \
"pr17827" \
] \
+ [list \
+ "Build pr18900.so" \
+ "-shared" \
+ "-fPIC" \
+ { pr18900a.c } \
+ "" \
+ "pr18900.so" \
+ ] \
+ [list \
+ "Build pr18900a" \
+ "tmpdir/pr18900.so" \
+ "" \
+ { pr18900b.c pr18900c.c } \
+ {{readelf {-Wrd} pr18900a.rd}} \
+ "pr18900a" \
+ ] \
+ [list \
+ "Build pr18900b" \
+ "tmpdir/pr18900.so" \
+ "" \
+ { pr18900b.c pr18900c.c } \
+ {{readelf {-Wrd} pr18900b.rd}} \
+ "pr18900b" \
+ ] \
]
run_ld_link_exec_tests [] [list \
@@ -520,6 +544,14 @@ if { [isnative]
"pr17689ver" \
"pr17689.out" \
] \
+ [list \
+ "Run pr18900" \
+ "tmpdir/pr18900.so" \
+ "" \
+ { pr18900b.c pr18900c.c } \
+ "pr18900" \
+ "pr18900.out" \
+ ] \
]
}
diff --git a/ld/testsuite/ld-i386/pr18900.out b/ld/testsuite/ld-i386/pr18900.out
new file mode 100644
index 0000000..b462a5a
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr18900.out
@@ -0,0 +1,4 @@
+OK
+OK
+OK
+OK
diff --git a/ld/testsuite/ld-i386/pr18900a.c b/ld/testsuite/ld-i386/pr18900a.c
new file mode 100644
index 0000000..fa2fc06
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr18900a.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+void
+foo (void)
+{
+ printf ("OK\n");
+}
+
+void *
+bar (void)
+{
+ foo ();
+ return &foo;
+}
diff --git a/ld/testsuite/ld-i386/pr18900a.rd b/ld/testsuite/ld-i386/pr18900a.rd
new file mode 100644
index 0000000..0731396
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr18900a.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+.*\(TEXTREL\).*
+#...
diff --git a/ld/testsuite/ld-i386/pr18900b.c b/ld/testsuite/ld-i386/pr18900b.c
new file mode 100644
index 0000000..e666305
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr18900b.c
@@ -0,0 +1,22 @@
+extern void abort (void);
+extern void foo (void);
+extern void *bar (void);
+
+typedef void (*func_p) (void);
+
+extern const func_p p1;
+
+func_p p2 = &foo;
+func_p p3 = &foo;
+
+int
+main ()
+{
+ void *p = bar ();
+ p1 ();
+ p2 ();
+ p3 ();
+ if (p != p1)
+ abort ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-i386/pr18900b.rd b/ld/testsuite/ld-i386/pr18900b.rd
new file mode 100644
index 0000000..e256a70
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr18900b.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_386_JUMP_SLOT[0-9a-f ]+foo
+#...
diff --git a/ld/testsuite/ld-i386/pr18900c.c b/ld/testsuite/ld-i386/pr18900c.c
new file mode 100644
index 0000000..b37ca16
--- /dev/null
+++ b/ld/testsuite/ld-i386/pr18900c.c
@@ -0,0 +1,5 @@
+extern void foo (void);
+
+typedef void (*func_p) (void);
+
+func_p p1 = &foo;
diff --git a/ld/testsuite/ld-x86-64/mpx3.dd b/ld/testsuite/ld-x86-64/mpx3.dd
index 2a8356d..eb529f4 100644
--- a/ld/testsuite/ld-x86-64/mpx3.dd
+++ b/ld/testsuite/ld-x86-64/mpx3.dd
@@ -3,33 +3,26 @@
Disassembly of section .plt:
-0+400290 <.plt>:
-[ ]*[a-f0-9]+: ff 35 6a 01 20 00 pushq 0x20016a\(%rip\) # 600400 <_GLOBAL_OFFSET_TABLE_\+0x8>
-[ ]*[a-f0-9]+: f2 ff 25 6b 01 20 00 bnd jmpq \*0x20016b\(%rip\) # 600408 <_GLOBAL_OFFSET_TABLE_\+0x10>
+0+[a-f0-9]+ <.plt>:
+[ ]*[a-f0-9]+: ff ([0-9a-f]{2} ){5} pushq 0x[a-f0-9]+\(%rip\) # [a-f0-9]+ <_GLOBAL_OFFSET_TABLE_\+0x8>
+[ ]*[a-f0-9]+: f2 ff ([0-9a-f]{2} ){5} bnd jmpq \*0x[a-f0-9]+\(%rip\) # [a-f0-9]+ <_GLOBAL_OFFSET_TABLE_\+0x10>
[ ]*[a-f0-9]+: 0f 1f 00 nopl \(%rax\)
[ ]*[a-f0-9]+: 68 00 00 00 00 pushq \$0x0
-[ ]*[a-f0-9]+: f2 e9 e5 ff ff ff bnd jmpq 400290 <call1@plt-0x30>
-[ ]*[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 d5 ff ff ff bnd jmpq 400290 <call1@plt-0x30>
+[ ]*[a-f0-9]+: f2 e9 ([0-9a-f]{2} ){4} bnd jmpq [a-f0-9]+ <call1@plt-0x20>
[ ]*[a-f0-9]+: 0f 1f 44 00 00 nopl 0x0\(%rax,%rax,1\)
Disassembly of section .plt.bnd:
-0+4002c0 <call1@plt>:
-[ ]*[a-f0-9]+: f2 ff 25 49 01 20 00 bnd jmpq \*0x200149\(%rip\) # 600410 <_GLOBAL_OFFSET_TABLE_\+0x18>
-[ ]*[a-f0-9]+: 90 nop
-
-0+4002c8 <call2@plt>:
-[ ]*[a-f0-9]+: f2 ff 25 49 01 20 00 bnd jmpq \*0x200149\(%rip\) # 600418 <_GLOBAL_OFFSET_TABLE_\+0x20>
+0+[a-f0-9]+ <call1@plt>:
+[ ]*[a-f0-9]+: f2 ff ([0-9a-f]{2} ){5} bnd jmpq \*0x[a-f0-9]+\(%rip\) # [a-f0-9]+ <_GLOBAL_OFFSET_TABLE_\+0x18>
[ ]*[a-f0-9]+: 90 nop
Disassembly of section .text:
-0+4002d0 <_start>:
-[ ]*[a-f0-9]+: bf c0 02 40 00 mov \$0x4002c0,%edi
+0+[a-f0-9]+ <_start>:
+[ ]*[a-f0-9]+: bf ([0-9a-f]{2} ){4} mov \$0x[a-f0-9]+,%edi
[ ]*[a-f0-9]+: f2 ff d7 bnd callq \*%rdi
-[ ]*[a-f0-9]+: 48 8b 3d 41 01 20 00 mov 0x200141\(%rip\),%rdi # 600420 <func>
+[ ]*[a-f0-9]+: 48 8b ([0-9a-f]{2} ){5} mov 0x[a-f0-9]+\(%rip\),%rdi # [a-f0-9]+ <func>
[ ]*[a-f0-9]+: f2 ff d7 bnd callq \*%rdi
[ ]*[a-f0-9]+: c3 retq
#pass
diff --git a/ld/testsuite/ld-x86-64/pr18900.out b/ld/testsuite/ld-x86-64/pr18900.out
new file mode 100644
index 0000000..b462a5a
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr18900.out
@@ -0,0 +1,4 @@
+OK
+OK
+OK
+OK
diff --git a/ld/testsuite/ld-x86-64/pr18900a.c b/ld/testsuite/ld-x86-64/pr18900a.c
new file mode 100644
index 0000000..fa2fc06
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr18900a.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+void
+foo (void)
+{
+ printf ("OK\n");
+}
+
+void *
+bar (void)
+{
+ foo ();
+ return &foo;
+}
diff --git a/ld/testsuite/ld-x86-64/pr18900a.rd b/ld/testsuite/ld-x86-64/pr18900a.rd
new file mode 100644
index 0000000..0731396
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr18900a.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+.*\(TEXTREL\).*
+#...
diff --git a/ld/testsuite/ld-x86-64/pr18900b.c b/ld/testsuite/ld-x86-64/pr18900b.c
new file mode 100644
index 0000000..e666305
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr18900b.c
@@ -0,0 +1,22 @@
+extern void abort (void);
+extern void foo (void);
+extern void *bar (void);
+
+typedef void (*func_p) (void);
+
+extern const func_p p1;
+
+func_p p2 = &foo;
+func_p p3 = &foo;
+
+int
+main ()
+{
+ void *p = bar ();
+ p1 ();
+ p2 ();
+ p3 ();
+ if (p != p1)
+ abort ();
+ return 0;
+}
diff --git a/ld/testsuite/ld-x86-64/pr18900b.rd b/ld/testsuite/ld-x86-64/pr18900b.rd
new file mode 100644
index 0000000..7e46c85
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr18900b.rd
@@ -0,0 +1,4 @@
+#failif
+#...
+[0-9a-f ]+R_X86_64_JUMP_SLOT[0-9a-f ]+foo \+ 0
+#...
diff --git a/ld/testsuite/ld-x86-64/pr18900c.c b/ld/testsuite/ld-x86-64/pr18900c.c
new file mode 100644
index 0000000..b37ca16
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/pr18900c.c
@@ -0,0 +1,5 @@
+extern void foo (void);
+
+typedef void (*func_p) (void);
+
+func_p p1 = &foo;
diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp
index 5409dff..6320999 100644
--- a/ld/testsuite/ld-x86-64/x86-64.exp
+++ b/ld/testsuite/ld-x86-64/x86-64.exp
@@ -476,6 +476,30 @@ if { [isnative] && [which $CC] != 0 } {
{{readelf {-Wr} pr17827.rd}} \
"pr17827" \
] \
+ [list \
+ "Build pr18900.so" \
+ "-shared" \
+ "-fPIC" \
+ { pr18900a.c } \
+ "" \
+ "pr18900.so" \
+ ] \
+ [list \
+ "Build pr18900a" \
+ "tmpdir/pr18900.so" \
+ "" \
+ { pr18900b.c pr18900c.c } \
+ {{readelf {-Wrd} pr18900a.rd}} \
+ "pr18900a" \
+ ] \
+ [list \
+ "Build pr18900b" \
+ "tmpdir/pr18900.so" \
+ "" \
+ { pr18900b.c pr18900c.c } \
+ {{readelf {-Wrd} pr18900b.rd}} \
+ "pr18900b" \
+ ] \
]
run_ld_link_exec_tests [] [list \
@@ -522,6 +546,14 @@ if { [isnative] && [which $CC] != 0 } {
"pr17689now" \
"pr17689.out" \
] \
+ [list \
+ "Run pr18900" \
+ "tmpdir/pr18900.so" \
+ "" \
+ { pr18900b.c pr18900c.c } \
+ "pr18900" \
+ "pr18900.out" \
+ ] \
]
if { [istarget "x86_64-*-linux*"] \