diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-05-08 10:10:22 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-05-08 10:11:32 -0700 |
commit | f604c2a2a54ebf88e4a51986c7cdedffe7b3313a (patch) | |
tree | 45da9d2bcfba99df2d039a3e2ca3a327aff665e1 /ld | |
parent | 046734ff424bc5a4c1b6a69630d5bb31aa67165c (diff) | |
download | gdb-f604c2a2a54ebf88e4a51986c7cdedffe7b3313a.zip gdb-f604c2a2a54ebf88e4a51986c7cdedffe7b3313a.tar.gz gdb-f604c2a2a54ebf88e4a51986c7cdedffe7b3313a.tar.bz2 |
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')
-rw-r--r-- | ld/ChangeLog | 14 | ||||
-rw-r--r-- | ld/testsuite/ld-i386/i386.exp | 21 | ||||
-rw-r--r-- | ld/testsuite/ld-i386/plt-pic2.dd | 33 | ||||
-rw-r--r-- | ld/testsuite/ld-i386/plt2.dd | 35 | ||||
-rw-r--r-- | ld/testsuite/ld-i386/plt2.rd | 9 | ||||
-rw-r--r-- | ld/testsuite/ld-i386/plt2.s | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-i386/pr20830.d | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-ifunc/ifunc-16-i386-now.d | 14 | ||||
-rw-r--r-- | ld/testsuite/ld-ifunc/ifunc-2-i386-now.d | 36 | ||||
-rw-r--r-- | ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d | 36 | ||||
-rw-r--r-- | ld/testsuite/ld-ifunc/pr17154-i386-now.d | 52 |
11 files changed, 259 insertions, 2 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index cd85a35..c56b3db 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -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 diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index a709bcf..5cb741f 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 0000000..aa311fe --- /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 0000000..1a5ea6f --- /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 0000000..11952b4 --- /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 0000000..d902bac --- /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 caaadd7..55fe924 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 diff --git a/ld/testsuite/ld-ifunc/ifunc-16-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-16-i386-now.d new file mode 100644 index 0000000..088b1f3 --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-16-i386-now.d @@ -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[ ]* diff --git a/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d new file mode 100644 index 0000000..ebe7ded --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-2-i386-now.d @@ -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 diff --git a/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d new file mode 100644 index 0000000..7cb2e54 --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-2-local-i386-now.d @@ -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 diff --git a/ld/testsuite/ld-ifunc/pr17154-i386-now.d b/ld/testsuite/ld-ifunc/pr17154-i386-now.d new file mode 100644 index 0000000..006af67 --- /dev/null +++ b/ld/testsuite/ld-ifunc/pr17154-i386-now.d @@ -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 |