mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-15 04:31:49 +08:00
647d4de92e
git commit 46434633f9
said
Make undefined symbols in allocate_dynrelocs dynamic
..if they have dynamic relocs. An undefined symbol in a PIC object
that finds no definition ought to become dynamic in order to support
--allow-shlib-undefined, but there is nothing in the generic ELF
linker code to do this if the reference isn't via the GOT or PLT. (An
initialized function pointer is an example.) So it falls to backend
code to ensure the symbol is made dynamic.
The above isn't true. Undefined symbols are indeed made dynamic for
shared libraries. Undefined symbols are not automatically made
dynamic in executables, and it was the PIE case that triggered an
internal consistency assertion on powerpc64. I guess I could have
jumped the other way when fixing PR21988, and not created a dynamic
reloc. Either way, it doesn't matter a great deal. We're going to
get an error on strong undefined symbols in an executable anyway, and
broken binaries if you try to use --unresolved-symbols=ignore-all to
disable the error.
* testsuite/ld-undefined/fundef.s: New test.
* testsuite/ld-undefined/undefined.exp: Test that undefined
symbols in shared libraries are made dynamic.
208 lines
7.5 KiB
Plaintext
208 lines
7.5 KiB
Plaintext
# Test that the linker reports undefined symbol errors correctly.
|
|
# By Ian Lance Taylor, Cygnus Support
|
|
#
|
|
# Copyright (C) 1995-2017 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.
|
|
|
|
set testund "undefined"
|
|
set testfn "undefined function"
|
|
set testline "undefined line"
|
|
|
|
if { ![is_remote host] && [which $CC] == 0 } {
|
|
verbose "Could not find C compiler!" 1
|
|
untested $testund
|
|
untested $testfn
|
|
untested $testline
|
|
} elseif { ![ld_compile "$CC -g" $srcdir/$subdir/undefined.c tmpdir/undefined.o] } {
|
|
verbose "Unable to compile test file!" 1
|
|
unresolved $testund
|
|
unresolved $testfn
|
|
unresolved $testline
|
|
} else {
|
|
remote_file host delete "tmpdir/undefined"
|
|
|
|
set flags [big_or_little_endian]
|
|
|
|
# Using -e start prevents the SunOS linker from trying to build a
|
|
# shared library.
|
|
send_log "$ld -e start $flags -o tmpdir/undefined tmpdir/undefined.o\n"
|
|
set exec_output [run_host_cmd "$ld" "-e start $flags -o tmpdir/undefined tmpdir/undefined.o"]
|
|
|
|
send_log "$exec_output\n"
|
|
verbose "$exec_output"
|
|
|
|
proc checkund { string testname } {
|
|
global exec_output
|
|
|
|
if [string match "*$string*" $exec_output] {
|
|
pass $testname
|
|
} else {
|
|
fail $testname
|
|
}
|
|
}
|
|
|
|
set mu "undefined reference to `*this_function_is_not_defined'"
|
|
checkund $mu $testund
|
|
|
|
# ARM PE defaults to using stabs debugging, which we can't handle
|
|
# for a COFF file.
|
|
#setup_xfail "arm*-*-pe*"
|
|
|
|
# For Xtensa on GNU Linux systems (or any other system where PIC
|
|
# code is always used), the address of the undefined function is
|
|
# in a literal pool outside the function, so that both the
|
|
# "undefined function" and "undefined line" tests fail.
|
|
setup_xfail xtensa*-*-linux*
|
|
|
|
set mf "tmpdir/undefined.o* In function `function':"
|
|
checkund $mf $testfn
|
|
|
|
if ![is_elf_format] {
|
|
# COFF SH gets this test wrong--it reports line 10, because
|
|
# although the jump is at line 9, the function address, and
|
|
# the reloc, is stored at the end of the function.
|
|
setup_xfail "sh-*-*"
|
|
|
|
# ARM PE defaults to using stabs debugging, which we can't
|
|
# handle for a COFF file.
|
|
#setup_xfail "arm*-*-pe*"
|
|
}
|
|
|
|
set ml "undefined.c:9: undefined reference to `*this_function_is_not_defined'"
|
|
# With targets that use elf/dwarf2, such as the arm-elf toolchain,
|
|
# the code in bfd/elf.c:_bfd_elf_find_nearest_line() is called in
|
|
# order to locate the file name/line number where the undefined
|
|
# reference occurs. Unfortunately this tries to use the dwarf2
|
|
# debug information held in the .debug_info section. This section
|
|
# contains a series of comp_unit structures, each of which has a
|
|
# low/high address range representing the span of memory locations
|
|
# covered by that structure. The structures also index into other
|
|
# structures held in the .debug_line section and together they can
|
|
# translate memory locations back into file/function/line number
|
|
# addresses in the source code. Since the information about the
|
|
# memory region covered by a comp_unit is only determined at link
|
|
# time, the low/high addresses in the .debug_info section and the
|
|
# line addresses in the .debug_line section are computed by
|
|
# generating relocs against known symbols in the object code.
|
|
#
|
|
# When the undefined reference is detected, the relocs in the
|
|
# dwarf2 debug sections have not yet been resolved, so the
|
|
# low/high addresses and the line number address are all set at
|
|
# zero. Thus when _bfd_elf_find_nearest_line() calls
|
|
# _bfd_dwarf2_find_nearest_line() no comp_unit can be found which
|
|
# actually covers the address where the reference occurred, and so
|
|
# _bfd_elf_find_nearest_line() fails.
|
|
#
|
|
# The upshot of all of this, is that the error message reported by
|
|
# the linker, instead of having a source file name & line number
|
|
# as in:
|
|
#
|
|
# undefined.c:9: undefined reference to `this_function_is_not_defined'
|
|
#
|
|
# has an object file & section address instead:
|
|
#
|
|
# undefined.0(.text+0xc): undefined reference to `this_function_is_not_defined'
|
|
#
|
|
# hence the xfails below.
|
|
|
|
setup_xfail mcore-*-elf
|
|
setup_xfail mep-*-*
|
|
setup_xfail mips-sgi-irix6*
|
|
setup_xfail "sh64-*-*"
|
|
# Fails for the MSP430 because it uses SYM_DIFF relocs but it does
|
|
# not provide a special_function for handling them. If
|
|
# optimization is enabled then this test passes because
|
|
# function()'s prologue is eliminated.
|
|
setup_xfail "msp430-*-*"
|
|
|
|
# The undefined test fails on 31 bit s/390 because the address of
|
|
# the function `this_function_is_not_defined' is stored in the
|
|
# literal pool of the function. Therefore the line number in the
|
|
# error message is 8 instead of 9. On 64 bit s/390 this works
|
|
# because of the new brasl instruction that doesn't need a literal
|
|
# pool entry.
|
|
setup_xfail s390-*-*
|
|
|
|
# See comments above for Xtensa.
|
|
setup_xfail xtensa*-*-linux*
|
|
setup_xfail hppa*64*-*-*
|
|
|
|
checkund $ml $testline
|
|
}
|
|
|
|
# Undefined symbols should become dynamic when linking a shared lib.
|
|
set testname "undefined symbols in shared lib"
|
|
|
|
set asflags ""
|
|
switch -glob $target_triplet {
|
|
aarch64* -
|
|
arm* -
|
|
powerpc64* { set asflags "--defsym BL=1" }
|
|
powerpc* { set asflags "--defsym BLPLT=1" }
|
|
hppa* { set asflags "--defsym HPPA=1" }
|
|
i\[3-7\]86* -
|
|
x86_64* { set asflags "--defsym CALLPLT=1" }
|
|
}
|
|
|
|
if { ![is_elf_format] || ![check_shared_lib_support]} then {
|
|
unsupported $testname
|
|
} elseif {![ld_assemble $as "$asflags $srcdir/$subdir/fundef.s" \
|
|
tmpdir/fundef.o]} then {
|
|
fail $testname
|
|
} elseif {![ld_link $ld tmpdir/fundef.so \
|
|
"-shared --allow-shlib-undefined tmpdir/fundef.o"]} then {
|
|
setup_xfail tic6x-*-*
|
|
fail $testname
|
|
} else {
|
|
if {![is_remote host] && [which $nm] == 0} then {
|
|
unresolved "$testname (dyn sym)"
|
|
} else {
|
|
set exec_output [run_host_cmd "$nm" "-D tmpdir/fundef.so"]
|
|
set exec_output [prune_warnings $exec_output]
|
|
|
|
if { ($asflags == ""
|
|
|| ([regexp ".* undef_fun_typed.*" $exec_output]
|
|
&& [regexp ".* undef_fun_notype.*" $exec_output]))
|
|
&& [regexp ".* undef_data.*" $exec_output]
|
|
&& [regexp ".* undef_pfun.*" $exec_output]
|
|
&& [regexp ".* undef_notype.*" $exec_output]} then {
|
|
pass "$testname (dyn sym)"
|
|
} else {
|
|
fail "$testname (dyn sym)"
|
|
}
|
|
}
|
|
|
|
global READELF
|
|
if {![is_remote host] && [which $READELF] == 0} then {
|
|
unresolved "$testname (dyn reloc)"
|
|
} else {
|
|
set exec_output [run_host_cmd "$READELF" "-r tmpdir/fundef.so"]
|
|
set exec_output [prune_warnings $exec_output]
|
|
|
|
# we ought to get two .rel{a}.plt and three .rel{a}.dyn relocs
|
|
if { ($asflags == "" || [regexp ".* contains 2 .*" $exec_output])
|
|
&& [regexp ".* contains 3 .*" $exec_output]
|
|
&& ![regexp "_NONE" $exec_output]} then {
|
|
pass "$testname (dyn reloc)"
|
|
} else {
|
|
fail "$testname (dyn reloc)"
|
|
}
|
|
}
|
|
}
|