dd7e64d45b
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.
354 lines
11 KiB
Plaintext
354 lines
11 KiB
Plaintext
# Expect script for ld-i386 tests
|
|
# Copyright (C) 2002-2014 Free Software Foundation, Inc.
|
|
#
|
|
# This file is part of the GNU Binutils.
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
|
# MA 02110-1301, USA.
|
|
#
|
|
|
|
# Test i386 linking; all types of relocs. This tests the assembler and
|
|
# tools like objdump as well as the linker.
|
|
|
|
if {[istarget "i?86-*-vxworks"]} {
|
|
set i386tests {
|
|
{"VxWorks shared library test 1" "-shared -Tvxworks1.ld" ""
|
|
"" {vxworks1-lib.s}
|
|
{{readelf --relocs vxworks1-lib.rd} {objdump -dr vxworks1-lib.dd}
|
|
{readelf --symbols vxworks1-lib.nd} {readelf -d vxworks1-lib.td}}
|
|
"libvxworks1.so"}
|
|
{"VxWorks executable test 1 (dynamic)" \
|
|
"tmpdir/libvxworks1.so -Tvxworks1.ld -q --force-dynamic" ""
|
|
"" {vxworks1.s}
|
|
{{readelf --relocs vxworks1.rd} {objdump -dr vxworks1.dd}}
|
|
"vxworks1"}
|
|
{"VxWorks executable test 2 (dynamic)" \
|
|
"-Tvxworks1.ld -q --force-dynamic" ""
|
|
"" {vxworks2.s}
|
|
{{readelf --segments vxworks2.sd}}
|
|
"vxworks2"}
|
|
{"VxWorks executable test 2 (static)"
|
|
"-Tvxworks1.ld" ""
|
|
"" {vxworks2.s}
|
|
{{readelf --segments vxworks2-static.sd}}
|
|
"vxworks2"}
|
|
}
|
|
run_ld_link_tests $i386tests
|
|
run_dump_test "vxworks1-static"
|
|
}
|
|
|
|
if [istarget "*-*-go32*"] {
|
|
run_ld_link_tests {{"go32 stub" "" "" "" {zero.s} {} "go32stub"}}
|
|
|
|
set src "tmpdir/go32stub"
|
|
set dest "tmpdir/go32stub-copy"
|
|
|
|
set test "go32 stub patch the source"
|
|
set fi [open $src r+]
|
|
fconfigure $fi -translation binary
|
|
if {[read $fi 2] != "MZ"} {
|
|
fail $test
|
|
} else {
|
|
pass $test
|
|
seek $fi 0x40
|
|
puts -nonewline $fi "objcopy-test-go32stub"
|
|
}
|
|
close $fi
|
|
|
|
set test "go32 stub objcopy"
|
|
set status [remote_exec build $OBJCOPY "$OBJCOPYFLAGS $src $dest"]
|
|
set exec_output [lindex $status 1]
|
|
set exec_output [prune_warnings $exec_output]
|
|
if [string match "" $exec_output] then {
|
|
pass $test
|
|
} else {
|
|
send_log "$exec_output\n"
|
|
verbose "$exec_output" 1
|
|
fail $test
|
|
}
|
|
|
|
# cmp would compare the whole files and some data after the initial exe
|
|
# stub could differ.
|
|
set test "go32 stub comparison after objcopy"
|
|
set fi [open $src]
|
|
fconfigure $fi -translation binary
|
|
set src_stub [read $fi 2048]
|
|
close $fi
|
|
set fi [open $dest]
|
|
fconfigure $fi -translation binary
|
|
set dest_stub [read $fi 2048]
|
|
close $fi
|
|
if {$src_stub == $dest_stub} {
|
|
pass $test
|
|
} else {
|
|
fail $test
|
|
}
|
|
}
|
|
|
|
if { !([istarget "i?86-*-elf*"]
|
|
|| (([istarget "i?86-*-linux*"]
|
|
|| [istarget "i?86-*-gnu*"])
|
|
&& ![istarget "*-*-*aout*"]
|
|
&& ![istarget "*-*-*oldld*"])
|
|
|| [istarget "i?86-*-nacl*"]
|
|
|| [istarget "x86_64-*-nacl*"]
|
|
|| [istarget "x86_64-*-linux*"]
|
|
|| [istarget "amd64-*-linux*"]) } {
|
|
return
|
|
}
|
|
|
|
# List contains test-items with 3 items followed by 2 lists:
|
|
# 0:name 1:ld early options 2:ld late options 3:assembler options
|
|
# 4:filenames of assembler files 5: action and options. 6: name of output file
|
|
|
|
# Actions:
|
|
# objdump: Apply objdump options on result. Compare with regex (last arg).
|
|
# nm: Apply nm options on result. Compare with regex (last arg).
|
|
# readelf: Apply readelf options on result. Compare with regex (last arg).
|
|
|
|
set i386tests {
|
|
{"Helper shared library (basic PLT test)"
|
|
"-shared -melf_i386" "" "--32" {pltlib.s} {} "libpltlib.so"}
|
|
{"basic PLT generation (non-PIC)"
|
|
"-melf_i386 tmpdir/libpltlib.so" "" "--32" {plt.s}
|
|
{{objdump -drj.plt plt.pd}} "plt"}
|
|
{"basic PLT generation (PIC)"
|
|
"-shared -melf_i386 tmpdir/libpltlib.so" "" "--32" {plt-pic.s}
|
|
{{objdump -drj.plt plt-pic.pd}} "libplt-pic.so"}
|
|
{"TLS -fpic -shared transitions"
|
|
"-shared -melf_i386 --no-ld-generated-unwind-info" ""
|
|
"--32" {tlspic1.s tlspic2.s}
|
|
{{readelf -Ssrl tlspic.rd} {objdump -drj.text tlspic.dd}
|
|
{objdump -sj.got tlspic.sd} {objdump -sj.tdata tlspic.td}}
|
|
"libtlspic.so"}
|
|
{"TLS descriptor -fpic -shared transitions"
|
|
"-shared -melf_i386 --no-ld-generated-unwind-info" ""
|
|
"--32" {tlsdesc.s tlspic2.s}
|
|
{{readelf -Ssrl tlsdesc.rd} {objdump -drj.text tlsdesc.dd}
|
|
{objdump "-s -j.got -j.got.plt" tlsdesc.sd} {objdump -sj.tdata tlsdesc.td}}
|
|
"libtlsdesc.so"}
|
|
{"Helper shared library" "-shared -melf_i386" ""
|
|
"--32" {tlslib.s} {} "libtlslib.so"}
|
|
{"TLS -fpic and -fno-pic exec transitions"
|
|
"-melf_i386 tmpdir/libtlslib.so --no-ld-generated-unwind-info" ""
|
|
"--32" {tlsbinpic.s tlsbin.s}
|
|
{{readelf -Ssrl tlsbin.rd} {objdump -drj.text tlsbin.dd}
|
|
{objdump -sj.got tlsbin.sd} {objdump -sj.tdata tlsbin.td}}
|
|
"tlsbin"}
|
|
{"TLS descriptor -fpic and -fno-pic exec transitions"
|
|
"-melf_i386 tmpdir/libtlslib.so --no-ld-generated-unwind-info" ""
|
|
"--32" {tlsbindesc.s tlsbin.s}
|
|
{{readelf -Ssrl tlsbindesc.rd} {objdump -drj.text tlsbindesc.dd}
|
|
{objdump -sj.got tlsbindesc.sd} {objdump -sj.tdata tlsbindesc.td}}
|
|
"tlsbindesc"}
|
|
{"TLS -fno-pic -shared"
|
|
"-shared -melf_i386 --no-ld-generated-unwind-info" ""
|
|
"--32" {tlsnopic1.s tlsnopic2.s}
|
|
{{readelf -Ssrl tlsnopic.rd} {objdump -drj.text tlsnopic.dd}
|
|
{objdump -sj.got tlsnopic.sd}} "libtlsnopic.so"}
|
|
{"TLS with global dynamic and descriptors"
|
|
"-shared -melf_i386 --no-ld-generated-unwind-info" ""
|
|
"--32" {tlsgdesc.s}
|
|
{{readelf -Ssrl tlsgdesc.rd} {objdump -drj.text tlsgdesc.dd}}
|
|
"libtlsgdesc.so"}
|
|
{"TLS in debug sections" "-melf_i386" ""
|
|
"--32" {tlsg.s}
|
|
{{objdump -sj.debug_foobar tlsg.sd}} "tlsg"}
|
|
{"TLS @indntpoff with %eax" "-melf_i386" "" "--32" {tlsindntpoff.s}
|
|
{{objdump -drj.text tlsindntpoff.dd}} "tlsindntpoff"}
|
|
{"Reloc section order" "-shared -melf_i386 -z nocombreloc" "" "--32"
|
|
{reloc.s} {{objdump -hw reloc.d}} "reloc.so"}
|
|
{"Basic --emit-relocs support" "-shared -melf_i386 --emit-relocs" "" "--32"
|
|
{emit-relocs.s} {{readelf --relocs emit-relocs.rd}} "emit-relocs.so"}
|
|
{"-z combreloc relocation sections" "-shared -melf_i386 -z combreloc" ""
|
|
"--32" {combreloc.s} {{readelf -r combreloc.d}} "combreloc.so"}
|
|
{"TLS GD->LE transition" "-melf_i386" ""
|
|
"--32" {tlsgd1.s}
|
|
{{objdump -dwr tlsgd1.dd}} "tlsgd1"}
|
|
{"TLS LD->LE transition" "-melf_i386" ""
|
|
"--32" {tlsld1.s}
|
|
{{objdump -dwr tlsld1.dd}} "tlsld1"}
|
|
{"TLS IE->LE transition" "-melf_i386" ""
|
|
"--32" {tlsie1.s}
|
|
{{objdump -dwr tlsie1.dd}} "tlsie1"}
|
|
{"PR ld/17313 (1)" "-melf_i386" ""
|
|
"--32" {zero.s} {} ""}
|
|
{"PR ld/17313 (2)" "-melf_i386 -shared --just-symbols=tmpdir/zero.o" ""
|
|
"--32" {lea1.s} {} "libpr17313.so"}
|
|
{"PR ld/17306 (1)" "-melf_i386" ""
|
|
"--32" {pr17306b.s} {} ""}
|
|
{"PR ld/17306 (2)" "-melf_i386 -shared -Bsymbolic --just-symbols=tmpdir/pr17306b.o" ""
|
|
"--32" {pr17306a.s} {} "libpr17306.so"}
|
|
}
|
|
|
|
# So as to avoid rewriting every last test case here in a nacl variant,
|
|
# we use black magic to massage the generic cases into nacl-variant cases.
|
|
if [istarget "*-*-nacl*"] {
|
|
# Change all the -melf_i386 to -melf_i386_nacl so linking can succeed.
|
|
regsub -all elf_i386 $i386tests elf_i386_nacl i386tests
|
|
|
|
# Same, applied to all the run_dump_test cases.
|
|
set options_regsub(ld) {-melf_i386 -melf_i386_nacl}
|
|
|
|
# The section/segment layout differs too much for the vanilla
|
|
# readelf output files to match. So massage the cases so that
|
|
# they refer to a foo-nacl.rd file instead of a foo.rd file.
|
|
regsub -all {([a-z0-9]+)\.rd} $i386tests {\1-nacl.rd} i386tests
|
|
|
|
# Likewise for PLTs.
|
|
regsub -all -- {([a-z0-9]+)\.pd} $i386tests {\1-nacl.pd} i386tests
|
|
}
|
|
|
|
run_ld_link_tests $i386tests
|
|
|
|
run_dump_test "abs"
|
|
run_dump_test "pcrel8"
|
|
run_dump_test "pcrel16"
|
|
run_dump_test "pcrel16abs"
|
|
run_dump_test "alloc"
|
|
run_dump_test "warn1"
|
|
run_dump_test "tlsgd2"
|
|
run_dump_test "tlsie2"
|
|
run_dump_test "tlsie3"
|
|
run_dump_test "tlsie4"
|
|
run_dump_test "tlsie5"
|
|
run_dump_test "hidden1"
|
|
run_dump_test "hidden2"
|
|
run_dump_test "hidden3"
|
|
run_dump_test "protected1"
|
|
run_dump_test "protected2"
|
|
run_dump_test "protected3"
|
|
run_dump_test "protected4"
|
|
run_dump_test "protected5"
|
|
run_dump_test "tlspie1"
|
|
run_dump_test "tlspie2"
|
|
run_dump_test "nogot1"
|
|
run_dump_test "nogot2"
|
|
run_dump_test "discarded1"
|
|
run_dump_test "pr12718"
|
|
run_dump_test "pr12921"
|
|
run_dump_test "pr12570a"
|
|
run_dump_test "pr12570b"
|
|
run_dump_test "lea1a"
|
|
run_dump_test "lea1b"
|
|
run_dump_test "lea1c"
|
|
run_dump_test "lea1d"
|
|
run_dump_test "lea1e"
|
|
run_dump_test "lea1f"
|
|
run_dump_test "mov1a"
|
|
run_dump_test "mov1b"
|
|
|
|
if { !([istarget "i?86-*-linux*"]
|
|
|| [istarget "i?86-*-gnu*"]
|
|
|| [istarget "i?86-*-nacl*"]
|
|
|| [istarget "x86_64-*-nacl*"]
|
|
|| [istarget "x86_64-*-linux*"]) } {
|
|
return
|
|
}
|
|
|
|
run_dump_test "compressed1"
|
|
run_dump_test "pr12627"
|
|
run_dump_test "pr13302"
|
|
run_dump_test "pr14215"
|
|
run_dump_test "pr17057"
|
|
|
|
# Must be Linux native with the C compiler
|
|
if { [isnative]
|
|
&& [istarget "i?86-*-linux*"]
|
|
&& [which $CC] != 0 } {
|
|
run_cc_link_tests [list \
|
|
[list \
|
|
"Build plt-lib.so" \
|
|
"-shared" \
|
|
"-fPIC" \
|
|
{ plt-lib.c } \
|
|
{} \
|
|
"libplt-lib.so" \
|
|
] \
|
|
[list \
|
|
"Build libplt-main1.a" \
|
|
"" \
|
|
"-fPIC" \
|
|
{ plt-main1.c } \
|
|
{{readelf {-Wr} plt-main1.rd}} \
|
|
"libplt-main1.a" \
|
|
] \
|
|
[list \
|
|
"Build libplt-main2.a" \
|
|
"" \
|
|
"-fPIC" \
|
|
{ plt-main2.c } \
|
|
{{readelf {-Wr} plt-main2.rd}} \
|
|
"libplt-main2.a" \
|
|
] \
|
|
[list \
|
|
"Build libplt-main3.a" \
|
|
"" \
|
|
"-fPIC" \
|
|
{ plt-main3.c } \
|
|
{{readelf {-Wr} plt-main3.rd}} \
|
|
"libplt-main3.a" \
|
|
] \
|
|
[list \
|
|
"Build libplt-main4.a" \
|
|
"" \
|
|
"-fPIC" \
|
|
{ plt-main4.c } \
|
|
{{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 \
|
|
[list \
|
|
"Run 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 } \
|
|
"plt-main" \
|
|
"plt-main.out" \
|
|
] \
|
|
[list \
|
|
"Run 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" \
|
|
"" \
|
|
{ plt-main5.c } \
|
|
"plt-main-pie" \
|
|
"plt-main.out" \
|
|
"-fPIC" \
|
|
] \
|
|
]
|
|
}
|