diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2014-11-25 05:05:39 -0800 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2014-11-25 05:05:39 -0800 |
commit | dd7e64d45b317128f5fe813a8da0b13b4ad046ae (patch) | |
tree | 3a7cd48d0ddc44e1840ea97120155a6c73ea31cc /ld/emulparams | |
parent | 07e94edf043090a6771eb3b8e7e03339cab8e607 (diff) | |
download | gdb-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.sh | 4 | ||||
-rw-r--r-- | ld/emulparams/elf_x86_64.sh | 5 |
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 |