This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Make undefined symbols in allocate_dynrelocs dynamic


On Wed, Aug 23, 2017 at 09:04:17AM +0930, Alan Modra wrote:
> ..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.

Anyway, here's a testsuite addition.

	* testsuite/ld-undefined/fundef.s: New test.
	* testsuite/ld-undefined/undefined.exp: Test that undefined
	symbols in shared libraries are made dynamic.

diff --git a/ld/testsuite/ld-undefined/fundef.s b/ld/testsuite/ld-undefined/fundef.s
new file mode 100644
index 0000000..96eb668
--- /dev/null
+++ b/ld/testsuite/ld-undefined/fundef.s
@@ -0,0 +1,31 @@
+	.text
+	.type undef_fun_typed %function
+ .ifdef BL
+	bl undef_fun_typed
+	nop
+	bl undef_fun_notype
+	nop
+ .endif
+ .ifdef BLPLT
+	bl undef_fun_typed@plt
+	nop
+	bl undef_fun_notype@plt
+	nop
+ .endif
+ .ifdef CALLPLT
+	call undef_fun_typed@plt
+	call undef_fun_notype@plt
+ .endif
+ .ifdef HPPA
+	bl undef_fun_typed,%r2
+	nop
+	bl undef_fun_notype,%r2
+	nop
+ .endif
+
+	.data
+	.type undef_data %object
+	.dc.a undef_data
+	.type undef_pfun %function
+	.dc.a undef_pfun
+	.dc.a undef_notype
diff --git a/ld/testsuite/ld-undefined/undefined.exp b/ld/testsuite/ld-undefined/undefined.exp
index a9ba9bb..c0c9012 100644
--- a/ld/testsuite/ld-undefined/undefined.exp
+++ b/ld/testsuite/ld-undefined/undefined.exp
@@ -29,119 +29,179 @@ if { ![is_remote host] && [which $CC] == 0 } {
     untested $testund
     untested $testfn
     untested $testline
-    return
-}
-
-if ![ld_compile "$CC -g" $srcdir/$subdir/undefined.c tmpdir/undefined.o] {
+} 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
-    return
-}
+} else {
+    remote_file host delete "tmpdir/undefined"
 
-remote_file host delete "tmpdir/undefined"
+    set flags [big_or_little_endian]
 
-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"]
 
-# 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"
 
-send_log "$exec_output\n"
-verbose "$exec_output"
+    proc checkund { string testname } {
+	global exec_output
 
-proc checkund { string testname } {
-    global exec_output
-
-    if [string match "*$string*" $exec_output] {
-	pass $testname
-    } else {
-	fail $testname
+	if [string match "*$string*" $exec_output] {
+	    pass $testname
+	} else {
+	    fail $testname
+	}
     }
-}
 
-set mu "undefined reference to `*this_function_is_not_defined'"
-checkund $mu $testund
+    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*"
+    # 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*
+    # 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
+    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-*-*"
+    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*"
+	# 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
 }
 
-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)"
+	}
+    }
+}


-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]