aboutsummaryrefslogtreecommitdiff
path: root/ld/testsuite/ld-i386
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-05-08 10:10:22 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-05-08 10:11:32 -0700
commitf604c2a2a54ebf88e4a51986c7cdedffe7b3313a (patch)
tree45da9d2bcfba99df2d039a3e2ca3a327aff665e1 /ld/testsuite/ld-i386
parent046734ff424bc5a4c1b6a69630d5bb31aa67165c (diff)
i386: Improve PLT generation and synthetic PLT symbols
On i386, the procedure linkage table (PLT) is used to 1. Call external function. 2. Call internal IFUNC function. The best implementation is selected for the target processor at run-time. 3. Act as the canonical function address. 4. Support LD_AUDIT to audit external function calls. 5. Support LD_PROFILE to profile external function calls. PLT looks like: PLT0: push GOT[1] jmp *GOT[2] nop PLT1: jmp *GOT[name1_index] push name1_reloc_index jmp PLT0 GOT is an array of addresses. Initially the GOT entry of name1 is filled with the address of the "push name1_reloc_index" instruction. The function, name1, is called via "jmp *GOT[name1]" in the PLT entry. Even when lazy binding is disabled by "-z now", the PLT0 entry may still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for canonical function address. 1. With lazy binding, when the external function, name1, is called the first time, dynamic linker is called via PLT0 to update GOT[name1_index] with the actual address of name1 and transfers control to name1 afterwards. 2. PLT is also used to call a local IFUNC function, name1, run-time loader updates GOT[name1_index] when loading the module. This patch 1. Remove PLT layout configurations from i386 backend_data. 2. Add generic, lay and non-lazy PLT layout configurations to i386 link_hash_table. Generic PLT layout includes the PLT entry templates, information how to update the first instruction in PLT and PLT eh_frame informaton, which are initialized in i386 setup_gnu_properties, based on PIC and target selection. PLT section alignment is also set to PLT entry size for non-NaCl/VxWorks target. 3. Remove elf_i386_create_dynamic_sections. create_dynamic_sections isn't always called, but GOT relocations need GOT relocations. Instead, create all i386 specific dynamic sections in i386 setup_gnu_properties, which initializes elf.dynobj, so that i386 check_relocs can be simplified. 4. Rewrite elf_i386_get_synthetic_symtab to check PLT sections against all dynamic relocations to support both lazy and non-lazy PLTs. bfd/ * elf32-i386.c (PLT_ENTRY_SIZE): Renamed to ... (LAZY_PLT_ENTRY_SIZE): This. (NON_LAZY_PLT_ENTRY_SIZE): New. (elf_i386_plt0_entry): Renamed to ... (elf_i386_lazy_plt0_entry): This. (elf_i386_plt_entry): Renamed to ... (elf_i386_lazy_plt_entry): This. (elf_i386_pic_plt0_entry): Renamed to ... (elf_i386_pic_lazy_plt0_entry): This. (elf_i386_pic_plt_entry): Renamed to ... (elf_i386_pic_lazy_plt_entry): This. (elf_i386_got_plt_entry): Renamed to ... (elf_i386_non_lazy_plt_entry): This. (elf_i386_pic_got_plt_entry): Renamed to ... (elf_i386_pic_non_lazy_plt_entry): This. (elf_i386_eh_frame_plt): Renamed to ... (elf_i386_eh_frame_lazy_plt): This. (elf_i386_eh_frame_plt_got): Renamed to ... (elf_i386_eh_frame_non_lazy_plt): This. (elf_i386_plt_layout): Renamed to ... (elf_i386_lazy_plt_layout): This. Remove eh_frame_plt_got and eh_frame_plt_got_size. (elf_i386_non_lazy_plt_layout): New. (elf_i386_plt_layout): Likewise. (elf_i386_non_lazy_plt): Likewise. (GET_PLT_ENTRY_SIZE): Removed. (elf_i386_plt): Renamed to ... (elf_i386_lazy_plt): This. (elf_i386_backend_data): Remove plt. Rename is_vxworks to os. (elf_i386_arch_bed): Updated. (elf_i386_link_hash_table): Add plt, lazy_plt and non_lazy_plt. (elf_i386_create_dynamic_sections): Removed. (elf_i386_check_relocs): Don't check elf.dynobj. Don't call _bfd_elf_create_ifunc_sections nor _bfd_elf_create_got_section. (elf_i386_adjust_dynamic_symbol): Updated. (elf_i386_allocate_dynrelocs): Updated. Pass 0 as PLT header size to _bfd_elf_allocate_ifunc_dyn_relocs and don't allocate size for PLT0 if there is no PLT0. (elf_i386_size_dynamic_sections): Updated. Check whether GOT output section is discarded only if GOT isn't empty. (elf_i386_relocate_section): Updated. Properly get PLT index if there is no PLT0. (elf_i386_finish_dynamic_symbol): Updated. Don't fill the second and third slots in the PLT entry if there is no PLT0. (elf_i386_finish_dynamic_sections): Updated. Don't fill PLT0 if there is no PLT0. Set sh_entsize on the .plt.got section. (elf_i386_nacl_plt): Forward declaration. (elf_i386_get_plt_sym_val): Removed. (elf_i386_get_synthetic_symtab): Rewrite to check PLT sections against all dynamic relocations. (elf_i386_link_setup_gnu_properties): New function. (elf_backend_create_dynamic_sections): Updated. (elf_backend_setup_gnu_properties): New. (elf_i386_nacl_plt): Updated. (elf_i386_nacl_arch_bed): Likewise. (elf_i386_vxworks_arch_bed): Likewise. ld/ * testsuite/ld-i386/i386.exp: Add some -z now tests. * testsuite/ld-i386/plt-pic2.dd: New file. * testsuite/ld-i386/plt2.dd: Likewise. * testsuite/ld-i386/plt2.rd: Likewise. * testsuite/ld-i386/plt2.s: Likewise. * testsuite/ld-ifunc/ifunc-16-i386-now.d: Likewise. * testsuite/ld-ifunc/ifunc-2-i386-now.d: Likewise. * testsuite/ld-ifunc/ifunc-2-local-i386-now.d: Likewise. * testsuite/ld-ifunc/pr17154-i386-now.d: Likewise. * testsuite/ld-i386/pr20830.d: Update the .plt.got section with func@plt.
Diffstat (limited to 'ld/testsuite/ld-i386')
-rw-r--r--ld/testsuite/ld-i386/i386.exp21
-rw-r--r--ld/testsuite/ld-i386/plt-pic2.dd33
-rw-r--r--ld/testsuite/ld-i386/plt2.dd35
-rw-r--r--ld/testsuite/ld-i386/plt2.rd9
-rw-r--r--ld/testsuite/ld-i386/plt2.s7
-rw-r--r--ld/testsuite/ld-i386/pr20830.d4
6 files changed, 107 insertions, 2 deletions
diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp
index a709bcffab..5cb741f2d8 100644
--- a/ld/testsuite/ld-i386/i386.exp
+++ b/ld/testsuite/ld-i386/i386.exp
@@ -1160,6 +1160,27 @@ if { !([istarget "i?86-*-linux*"]
return
}
+run_ld_link_tests [list \
+ [list \
+ "basic PLT generation (non-PIC, -z now)" \
+ "-z now -melf_i386 tmpdir/libpltlib.so" \
+ "" \
+ "--32" \
+ {plt2.s} \
+ {{readelf -SW plt2.rd} {objdump -dwr plt2.dd}} \
+ "plt2" \
+ ] \
+ [list \
+ "basic PLT generation (PIC, -z now)" \
+ "-z now -shared -melf_i386 tmpdir/libpltlib.so" \
+ "" \
+ "--32" \
+ {plt-pic.s} \
+ {{objdump -dwr plt-pic2.dd}} \
+ "plt-pic2.so" \
+ ] \
+]
+
# Linux only tests
run_dump_test "pltgot-1"
run_dump_test "pltgot-2"
diff --git a/ld/testsuite/ld-i386/plt-pic2.dd b/ld/testsuite/ld-i386/plt-pic2.dd
new file mode 100644
index 0000000000..aa311fe8bd
--- /dev/null
+++ b/ld/testsuite/ld-i386/plt-pic2.dd
@@ -0,0 +1,33 @@
+#source: plt-pic.s
+#as: --32
+#ld: -z now -shared -melf_i386
+#objdump: -dwr
+#target: i?86-*-*
+
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+180 <.plt>:
+ +[a-f0-9]+: ff b3 04 00 00 00 pushl 0x4\(%ebx\)
+ +[a-f0-9]+: ff a3 08 00 00 00 jmp \*0x8\(%ebx\)
+ +[a-f0-9]+: 00 00 add %al,\(%eax\)
+ ...
+
+Disassembly of section .plt.got:
+
+0+190 <fn1@plt>:
+ +[a-f0-9]+: ff a3 f8 ff ff ff jmp \*-0x8\(%ebx\)
+ +[a-f0-9]+: 66 90 xchg %ax,%ax
+
+0+198 <fn2@plt>:
+ +[a-f0-9]+: ff a3 fc ff ff ff jmp \*-0x4\(%ebx\)
+ +[a-f0-9]+: 66 90 xchg %ax,%ax
+
+Disassembly of section .text:
+
+0+1a0 <foo>:
+ +[a-f0-9]+: e8 eb ff ff ff call 190 <fn1@plt>
+ +[a-f0-9]+: e9 ee ff ff ff jmp 198 <fn2@plt>
+#pass
diff --git a/ld/testsuite/ld-i386/plt2.dd b/ld/testsuite/ld-i386/plt2.dd
new file mode 100644
index 0000000000..1a5ea6f623
--- /dev/null
+++ b/ld/testsuite/ld-i386/plt2.dd
@@ -0,0 +1,35 @@
+#source: plt2.s
+#as: --32
+#ld: -z now -melf_i386
+#objdump: -dwr
+#target: i?86-*-*
+
+.*: +file format .*
+
+
+Disassembly of section .plt:
+
+0+80481c0 <.plt>:
+ +[a-f0-9]+: ff 35 b4 92 04 08 pushl 0x80492b4
+ +[a-f0-9]+: ff 25 b8 92 04 08 jmp \*0x80492b8
+ +[a-f0-9]+: 00 00 add %al,\(%eax\)
+ ...
+
+0+80481d0 <fn1@plt>:
+ +[a-f0-9]+: ff 25 bc 92 04 08 jmp \*0x80492bc
+ +[a-f0-9]+: 68 00 00 00 00 push \$0x0
+ +[a-f0-9]+: e9 e0 ff ff ff jmp 80481c0 <.plt>
+
+Disassembly of section .plt.got:
+
+0+80481e0 <fn2@plt>:
+ +[a-f0-9]+: ff 25 ac 92 04 08 jmp \*0x80492ac
+ +[a-f0-9]+: 66 90 xchg %ax,%ax
+
+Disassembly of section .text:
+
+0+80481e8 <_start>:
+ +[a-f0-9]+: e8 e3 ff ff ff call 80481d0 <fn1@plt>
+ +[a-f0-9]+: e8 ee ff ff ff call 80481e0 <fn2@plt>
+ +[a-f0-9]+: 81 7c 24 04 d0 81 04 08 cmpl \$0x80481d0,0x4\(%esp\)
+#pass
diff --git a/ld/testsuite/ld-i386/plt2.rd b/ld/testsuite/ld-i386/plt2.rd
new file mode 100644
index 0000000000..11952b4805
--- /dev/null
+++ b/ld/testsuite/ld-i386/plt2.rd
@@ -0,0 +1,9 @@
+#source: plt2.s
+#as: --32
+#ld: -z now -melf_i386
+#readelf: -SW
+#target: i?86-*-*
+
+#...
+ +\[ *[0-9]+\] \.plt +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +0+20 +.* +AX +0 +0 +16
+#pass
diff --git a/ld/testsuite/ld-i386/plt2.s b/ld/testsuite/ld-i386/plt2.s
new file mode 100644
index 0000000000..d902baca55
--- /dev/null
+++ b/ld/testsuite/ld-i386/plt2.s
@@ -0,0 +1,7 @@
+ .text
+ .globl _start
+ .type _start,@function
+_start:
+ call fn1
+ call fn2
+ cmpl $fn1, 4(%esp)
diff --git a/ld/testsuite/ld-i386/pr20830.d b/ld/testsuite/ld-i386/pr20830.d
index caaadd77a4..55fe92475d 100644
--- a/ld/testsuite/ld-i386/pr20830.d
+++ b/ld/testsuite/ld-i386/pr20830.d
@@ -48,13 +48,13 @@ Disassembly of section .plt:
Disassembly of section .plt.got:
-0+180 <.plt.got>:
+0+180 <func@plt>:
+[a-f0-9]+: ff a3 fc ff ff ff jmp \*-0x4\(%ebx\)
+[a-f0-9]+: 66 90 xchg %ax,%ax
Disassembly of section .text:
0+188 <foo>:
- +[a-f0-9]+: e8 f3 ff ff ff call 180 <.plt.got>
+ +[a-f0-9]+: e8 f3 ff ff ff call 180 <func@plt>
+[a-f0-9]+: 8b 83 fc ff ff ff mov -0x4\(%ebx\),%eax
#pass