From dd7e64d45b317128f5fe813a8da0b13b4ad046ae Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 25 Nov 2014 05:05:39 -0800 Subject: Optimize out i386/x86-64 JUMP_SLOT relocation When there are both PLT and GOT references to the same function symbol, linker will create a GOTPLT slot for PLT entry and a GOT slot for GOT reference. A run-time JUMP_SLOT relocation is created to update the GOTPLT slot and a run-time GLOB_DAT relocation is created to update the GOT slot. Both JUMP_SLOT and GLOB_DAT relocations will apply the same symbol value to GOTPLT and GOT slots, respectively, at run-time. This optimization combines GOTPLT and GOT slots into a single GOT slot and removes the run-time JUMP_SLOT relocation. It replaces the regular PLT entry: indirect jump [GOTPLT slot] push relocation index jump PLT0 with an GOT PLT entry with an indirect jump via the GOT slot: indirect jump [GOT slot] nop and resolves PLT reference to the GOT PLT entry. We must avoid this optimization if pointer equality is needed since we don't clear symbol value in this case and the dynamic linker won't update the GOT slot. Otherwise, the resulting binary will get into an infinite loop at run-time. bfd/ * elf32-i386.c (elf_i386_got_plt_entry): New. (elf_i386_pic_got_plt_entry): Likewise. (elf_i386_link_hash_entry): Add plt_got. (elf_i386_link_hash_table): Likewise. (elf_i386_link_hash_newfunc): Initialize plt_got.offset to -1. (elf_i386_get_local_sym_hash): Likewise. (elf_i386_check_relocs): Create the GOT PLT if there are both PLT and GOT references when the regular PLT is used. (elf_i386_allocate_dynrelocs): Use the GOT PLT if there are both PLT and GOT references unless pointer equality is needed. (elf_i386_relocate_section): Also check the GOT PLT when resolving R_386_PLT32. (elf_i386_finish_dynamic_symbol): Use the GOT PLT if it is available. * elf64-x86-64.c (elf_x86_64_link_hash_entry): Add plt_got. (elf_x86_64_link_hash_table): Likewise. (elf_x86_64_link_hash_newfunc): Initialize plt_got.offset to -1. (elf_x86_64_get_local_sym_hash): Likewise. (elf_x86_64_check_relocs): Create the GOT PLT if there are both PLT and GOT references when the regular PLT is used. (elf_x86_64_allocate_dynrelocs): Use the GOT PLT if there are both PLT and GOT references unless pointer equality is needed. (elf_x86_64_relocate_section): Also check the GOT PLT when resolving R_X86_64_PLT32. (elf_x86_64_finish_dynamic_symbol): Use the GOT PLT if it is available. ld/ * emulparams/elf_i386.sh (TINY_READONLY_SECTION): New. * emulparams/elf_x86_64.sh (TINY_READONLY_SECTION): Add .plt.got. ld/testsuite/ * ld-i386/i386.exp: Add run-time relocation tests for plt-main. * ld-i386/plt-main.rd: New file. * ld-x86-64/plt-main-bnd.dd: Likewise. * ld-x86-64/plt-main.rd: Likewise. * ld-x86-64/x86-64.exp: Add run-time relocation tests for plt-main. --- ld/ChangeLog | 5 +++ ld/emulparams/elf_i386.sh | 4 +++ ld/emulparams/elf_x86_64.sh | 5 ++- ld/testsuite/ChangeLog | 9 +++++ ld/testsuite/ld-i386/i386.exp | 18 ++++++++++ ld/testsuite/ld-i386/plt-main.rd | 4 +++ ld/testsuite/ld-x86-64/plt-main-bnd.dd | 7 ++++ ld/testsuite/ld-x86-64/plt-main.rd | 4 +++ ld/testsuite/ld-x86-64/x86-64.exp | 65 ++++++++++++++++++++++++++++++++++ 9 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 ld/testsuite/ld-i386/plt-main.rd create mode 100644 ld/testsuite/ld-x86-64/plt-main-bnd.dd create mode 100644 ld/testsuite/ld-x86-64/plt-main.rd (limited to 'ld') diff --git a/ld/ChangeLog b/ld/ChangeLog index f6a4d6f..9ec721f 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2014-11-25 H.J. Lu + + * emulparams/elf_i386.sh (TINY_READONLY_SECTION): New. + * emulparams/elf_x86_64.sh (TINY_READONLY_SECTION): Add .plt.got. + 2014-11-24 H.J. Lu * configure: Regenerated. diff --git a/ld/emulparams/elf_i386.sh b/ld/emulparams/elf_i386.sh index 93f1992..2ebfaac 100644 --- a/ld/emulparams/elf_i386.sh +++ b/ld/emulparams/elf_i386.sh @@ -13,6 +13,10 @@ GENERATE_PIE_SCRIPT=yes NO_SMALL_DATA=yes SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 12 ? 12 : 0" IREL_IN_PLT= +# Reuse TINY_READONLY_SECTION which is placed right after .plt section. +TINY_READONLY_SECTION=" +.plt.got ${RELOCATING-0} : { *(.plt.got) } +" # Linux modify the default library search path to first include # a 32-bit specific directory. diff --git a/ld/emulparams/elf_x86_64.sh b/ld/emulparams/elf_x86_64.sh index 1e83a74..aa26a1b 100644 --- a/ld/emulparams/elf_x86_64.sh +++ b/ld/emulparams/elf_x86_64.sh @@ -17,7 +17,10 @@ LARGE_BSS_AFTER_BSS= SEPARATE_GOTPLT="SIZEOF (.got.plt) >= 24 ? 24 : 0" IREL_IN_PLT= # Reuse TINY_READONLY_SECTION which is placed right after .plt section. -TINY_READONLY_SECTION=".plt.bnd ${RELOCATING-0} : { *(.plt.bnd) }" +TINY_READONLY_SECTION=" +.plt.got ${RELOCATING-0} : { *(.plt.got) } +.plt.bnd ${RELOCATING-0} : { *(.plt.bnd) } +" if [ "x${host}" = "x${target}" ]; then case " $EMULATION_LIBPATH " in diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index be12722..a750240 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2014-11-25 H.J. Lu + + * ld-i386/i386.exp: Add run-time relocation tests for plt-main. + * ld-i386/plt-main.rd: New file. + * ld-x86-64/plt-main-bnd.dd: Likewise. + * ld-x86-64/plt-main.rd: Likewise. + * ld-x86-64/x86-64.exp: Add run-time relocation tests for + plt-main. + 2014-11-21 H.J. Lu * ld-i386/plt-lib.c: New file. diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index 4c870b8..304713d 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -309,6 +309,24 @@ if { [isnative] {{readelf {-Wr} plt-main4.rd}} \ "libplt-main4.a" \ ] \ + [list \ + "Build plt-main" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so" \ + "" \ + { plt-main5.c } \ + {{readelf {-Wr} plt-main.rd}} \ + "plt-main" \ + ] \ + [list \ + "Build plt-main with PIE" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -pie" \ + "-fPIC" \ + { plt-main5.c } \ + {{readelf {-Wr} plt-main.rd}} \ + "plt-main" \ + ] \ ] run_ld_link_exec_tests [] [list \ diff --git a/ld/testsuite/ld-i386/plt-main.rd b/ld/testsuite/ld-i386/plt-main.rd new file mode 100644 index 0000000..6d01ff9 --- /dev/null +++ b/ld/testsuite/ld-i386/plt-main.rd @@ -0,0 +1,4 @@ +#failif +#... +[0-9a-f ]+R_386_JUMP_SLOT +0+ +bar +#... diff --git a/ld/testsuite/ld-x86-64/plt-main-bnd.dd b/ld/testsuite/ld-x86-64/plt-main-bnd.dd new file mode 100644 index 0000000..8598e30 --- /dev/null +++ b/ld/testsuite/ld-x86-64/plt-main-bnd.dd @@ -0,0 +1,7 @@ +#... +Disassembly of section .plt.got: + +[a-f0-9]+ <.plt.got>: +[ ]*[a-f0-9]+: f2 ff 25 .. .. 20 00 bnd jmpq \*0x20....\(%rip\) # ...... <_DYNAMIC\+0x...> +[ ]*[a-f0-9]+: 90 nop +#pass diff --git a/ld/testsuite/ld-x86-64/plt-main.rd b/ld/testsuite/ld-x86-64/plt-main.rd new file mode 100644 index 0000000..1effcd4 --- /dev/null +++ b/ld/testsuite/ld-x86-64/plt-main.rd @@ -0,0 +1,4 @@ +#failif +#... +[0-9a-f ]+R_X86_64_JUMP_SLOT +0+ +bar \+ 0 +#... diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index ab1bfd1..886469b 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -374,6 +374,24 @@ if { [isnative] && [which $CC] != 0 } { {{readelf {-Wr} plt-main4.rd}} \ "libplt-main4.a" \ ] \ + [list \ + "Build plt-main" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so" \ + "" \ + { plt-main5.c } \ + {{readelf {-Wr} plt-main.rd}} \ + "plt-main" \ + ] \ + [list \ + "Build plt-main with PIE" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -pie" \ + "-fPIC" \ + { plt-main5.c } \ + {{readelf {-Wr} plt-main.rd}} \ + "plt-main" \ + ] \ ] run_ld_link_exec_tests [] [list \ @@ -397,6 +415,53 @@ if { [isnative] && [which $CC] != 0 } { "-fPIC" \ ] \ ] + + if { [istarget "x86_64-*-linux*"] \ + && ![istarget "x86_64-*-linux*-gnux32"]} { + + run_cc_link_tests [list \ + [list \ + "Build plt-main with -z bndplt" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -z bndplt" \ + "" \ + { plt-main5.c } \ + {{objdump {-drw} plt-main-bnd.dd}} \ + "plt-main-bnd" \ + ] \ + [list \ + "Build plt-main with PIE and -z bndplt" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -z bndplt -pie" \ + "-fPIC" \ + { plt-main5.c } \ + {{objdump {-drw} plt-main-bnd.dd}} \ + "plt-main-pie-bnd" \ + ] \ + ] + + run_ld_link_exec_tests [] [list \ + [list \ + "Run plt-main with -z bndplt" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -z bndplt" \ + "" \ + { plt-main5.c } \ + "plt-main-bnd" \ + "plt-main.out" \ + ] \ + [list \ + "Run plt-main with PIE and -z bndplt" \ + "tmpdir/plt-main1.o tmpdir/plt-main2.o tmpdir/plt-main3.o \ + tmpdir/plt-main4.o tmpdir/libplt-lib.so -z bndplt -pie" \ + "" \ + { plt-main5.c } \ + "plt-main-pie-bnd" \ + "plt-main.out" \ + "-fPIC" \ + ] \ + ] + } } if { ![istarget "x86_64-*-linux*"]} { -- cgit v1.1