aboutsummaryrefslogtreecommitdiff
path: root/ld/emulparams
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2014-11-25 05:05:39 -0800
committerH.J. Lu <hjl.tools@gmail.com>2014-11-25 05:05:39 -0800
commitdd7e64d45b317128f5fe813a8da0b13b4ad046ae (patch)
tree3a7cd48d0ddc44e1840ea97120155a6c73ea31cc /ld/emulparams
parent07e94edf043090a6771eb3b8e7e03339cab8e607 (diff)
downloadgdb-dd7e64d45b317128f5fe813a8da0b13b4ad046ae.zip
gdb-dd7e64d45b317128f5fe813a8da0b13b4ad046ae.tar.gz
gdb-dd7e64d45b317128f5fe813a8da0b13b4ad046ae.tar.bz2
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.
Diffstat (limited to 'ld/emulparams')
-rw-r--r--ld/emulparams/elf_i386.sh4
-rw-r--r--ld/emulparams/elf_x86_64.sh5
2 files changed, 8 insertions, 1 deletions
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