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.
This commit is contained in:
H.J. Lu 2017-05-08 10:10:22 -07:00
parent 046734ff42
commit f604c2a2a5
13 changed files with 1154 additions and 409 deletions

View File

@ -1,3 +1,62 @@
2017-05-08 H.J. Lu <hongjiu.lu@intel.com>
* 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.
2017-05-08 Thomas Preud'homme <thomas.preudhomme@arm.com>
* elflink.c (elf_output_implib): Remove executable flag from import

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,17 @@
2017-05-08 H.J. Lu <hongjiu.lu@intel.com>
* 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.
2017-05-08 Thomas Preud'homme <thomas.preudhomme@arm.com>
* testsuite/ld-arm/arm-elf.exp

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,7 @@
.text
.globl _start
.type _start,@function
_start:
call fn1
call fn2
cmpl $fn1, 4(%esp)

View File

@ -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

View File

@ -0,0 +1,14 @@
#source: ifunc-16-x86.s
#ld: -z now -shared -m elf_i386
#as: --32
#readelf: -r --wide
#target: x86_64-*-* i?86-*-*
#notarget: x86_64-*-nacl* i?86-*-nacl*
Relocation section '.rel.dyn' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_GLOB_DAT[ ]+0+[ ]+ifunc
Relocation section '.rel.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_386_IRELATIVE[ ]*

View File

@ -0,0 +1,36 @@
#source: ifunc-2-i386.s
#ld: -z now -m elf_i386 -shared
#as: --32
#objdump: -dw
#target: x86_64-*-* i?86-*-*
#notarget: x86_64-*-nacl* i?86-*-nacl*
.*: +file format .*
Disassembly of section .plt:
0+150 <.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\)
...
0+160 <\*ABS\*@plt>:
+[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\)
+[a-f0-9]+: 68 00 00 00 00 push \$0x0
+[a-f0-9]+: e9 e0 ff ff ff jmp 150 <.plt>
Disassembly of section .text:
0+170 <foo>:
+[a-f0-9]+: c3 ret
0+171 <bar>:
+[a-f0-9]+: e8 00 00 00 00 call 176 <bar\+0x5>
+[a-f0-9]+: 5b pop %ebx
+[a-f0-9]+: 81 c3 9e 10 00 00 add \$0x109e,%ebx
+[a-f0-9]+: e8 de ff ff ff call 160 <\*ABS\*@plt>
+[a-f0-9]+: 8d 83 4c ef ff ff lea -0x10b4\(%ebx\),%eax
+[a-f0-9]+: c3 ret
#pass

View File

@ -0,0 +1,36 @@
#source: ifunc-2-local-i386.s
#ld: -z now -m elf_i386 -shared
#as: --32
#objdump: -dw
#target: x86_64-*-* i?86-*-*
#notarget: x86_64-*-nacl* i?86-*-nacl*
.*: +file format .*
Disassembly of section .plt:
0+140 <.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\)
...
0+150 <\*ABS\*@plt>:
+[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\)
+[a-f0-9]+: 68 00 00 00 00 push \$0x0
+[a-f0-9]+: e9 e0 ff ff ff jmp 140 <.plt>
Disassembly of section .text:
0+160 <__GI_foo>:
+[a-f0-9]+: c3 ret
0+161 <bar>:
+[a-f0-9]+: e8 00 00 00 00 call 166 <bar\+0x5>
+[a-f0-9]+: 5b pop %ebx
+[a-f0-9]+: 81 c3 9e 10 00 00 add \$0x109e,%ebx
+[a-f0-9]+: e8 de ff ff ff call 150 <\*ABS\*@plt>
+[a-f0-9]+: 8d 83 4c ef ff ff lea -0x10b4\(%ebx\),%eax
+[a-f0-9]+: c3 ret
#pass

View File

@ -0,0 +1,52 @@
#source: pr17154-x86.s
#ld: -z now -m elf_i386 -shared
#as: --32
#objdump: -dw
#target: x86_64-*-* i?86-*-*
#notarget: x86_64-*-nacl* i?86-*-nacl*
.*: +file format .*
Disassembly of section .plt:
0+1d0 <.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\)
...
0+1e0 <\*ABS\*@plt>:
+[a-f0-9]+: ff a3 0c 00 00 00 jmp \*0xc\(%ebx\)
+[a-f0-9]+: 68 08 00 00 00 push \$0x8
+[a-f0-9]+: e9 e0 ff ff ff jmp 1d0 <.plt>
0+1f0 <\*ABS\*@plt>:
+[a-f0-9]+: ff a3 10 00 00 00 jmp \*0x10\(%ebx\)
+[a-f0-9]+: 68 00 00 00 00 push \$0x0
+[a-f0-9]+: e9 d0 ff ff ff jmp 1d0 <.plt>
Disassembly of section .plt.got:
0+200 <func1@plt>:
+[a-f0-9]+: ff a3 f8 ff ff ff jmp \*-0x8\(%ebx\)
+[a-f0-9]+: 66 90 xchg %ax,%ax
0+208 <func2@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+210 <resolve1>:
+[a-f0-9]+: e8 eb ff ff ff call 200 <func1@plt>
0+215 <g1>:
+[a-f0-9]+: e9 d6 ff ff ff jmp 1f0 <\*ABS\*@plt>
0+21a <resolve2>:
+[a-f0-9]+: e8 e9 ff ff ff call 208 <func2@plt>
0+21f <g2>:
+[a-f0-9]+: e9 bc ff ff ff jmp 1e0 <\*ABS\*@plt>
#pass