# Support routines for LD testsuite.
-# Copyright (C) 1994-2016 Free Software Foundation, Inc.
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
#
# This file is part of the GNU Binutils.
#
# Returns 0 otherwise.
#
proc at_least_gcc_version { major minor } {
+ global CC
if {![info exists CC]} {
set CC [find_gcc]
}
if { $CC == "" } {
- return 0
+ return 0
}
set state [remote_exec host $CC --version]
+ if { [lindex $state 0] != 0 } {
+ return 0;
+ }
set tmp "[lindex $state 1]\n"
# Look for (eg) 4.6.1 in the version output.
set ver_re "\[^\\.0-9\]+(\[1-9\]\[0-9\]*)\\.(\[0-9\]+)(?:\\.\[0-9\]+)?"
return $flags
}
-# Link a program using ld.
+# Link a program using ld
#
proc default_ld_link { ld target objects } {
- global HOSTING_EMU
- global HOSTING_CRT0
- global HOSTING_SCRT0
- global HOSTING_LIBS
- global HOSTING_SLIBS
- global LIBS
- global host_triplet
- global link_output
- global exec_output
-
- if { [ string match "* -pie *" $objects ] } {
- set objs "$HOSTING_SCRT0 $objects"
- set libs "$LIBS $HOSTING_SLIBS"
- } else {
- set objs "$HOSTING_CRT0 $objects"
- set libs "$LIBS $HOSTING_LIBS"
- }
-
- if [is_endian_output_format $objects] then {
- set flags [big_or_little_endian]
- } else {
- set flags ""
- }
-
- remote_file host delete $target
-
- return [run_host_cmd_yesno "$ld" "$HOSTING_EMU $flags -o $target $objs $libs"]
-}
-
-# Link a program using ld, without including any libraries.
-#
-proc default_ld_simple_link { ld target objects } {
global host_triplet
global exec_output
# Define various symbols needed when not linking against all
# target libs.
-proc ld_simple_link_defsyms {} {
+proc ld_link_defsyms {} {
set flags "--defsym __stack_chk_fail=0"
global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS LDFLAGS
global host_triplet runtests
global env verbose
+ global ld_elf_shared_opt
+
+ if { [is_elf_format] && [check_shared_lib_support] } {
+ set ld_extra_opt "$ld_elf_shared_opt"
+ } else {
+ set ld_extra_opt ""
+ }
if [string match "*/*" $name] {
set file $name
set dumpfile tmpdir/dump.out
set run_ld 0
set run_objcopy 0
+ set objfile_names {}
set opts(as) {}
set opts(ld) {}
set opts(ld_after_inputfiles) {}
} else {
lappend asflags {}
}
+
+ # Create the object file name based on nothing but the source
+ # file name.
+ set new_objfile \
+ [concat tmpdir/[file rootname [file tail [lindex $opt_val 0]]].o]
+ # But, sometimes, we have the exact same source filename in
+ # different directories (foo/src.s bar/src.s) which would lead
+ # us to try and create two src.o files. We detect this
+ # conflict here, and instead create src.o and src1.o.
+ set j 0
+ while { [lsearch $objfile_names $new_objfile] != -1 } {
+ incr j
+ set new_objfile \
+ [concat tmpdir/[file rootname [file tail [lindex $opt_val 0]]]${j}.o]
+ }
+ lappend objfile_names $new_objfile
}
default {
if [string length $opts($opt_name)] {
if { $opts(source) == "" } {
set sourcefiles [list ${file}.s]
set asflags [list ""]
+ set objfile_names [list tmpdir/[file tail ${file}].o]
} else {
set sourcefiles {}
foreach sf $opts(source) {
}
regsub "RUN_OBJCOPY" $sourceasflags "" sourceasflags
- set objfile "tmpdir/dump$i.o"
+ set objfile [lindex $objfile_names $i]
catch "exec rm -f $objfile" exec_output
lappend objfiles $objfile
set cmd "$AS $ASFLAGS $opts(as) $sourceasflags -o $objfile $sourcefile"
remote_file build delete "ld.tmp"
if { [lindex $cmdret 0] != 0 || ![string match "" $comp_output] } then {
- send_log "$comp_output\n"
+ send_log -- "$comp_output\n"
verbose "$comp_output" 3
set exitstat "succeeded"
if { [lindex $cmdret 0] != 0 \
|| ![string match "" $comp_output] } {
- send_log "$comp_output\n"
+ send_log -- "$comp_output\n"
verbose "$comp_output" 3
set exitstat "succeeded"
}
set check_ld(source) ""
+ set check_ld(terminal) 0
if { $opts(error) != "" \
|| $opts(warning) != "" \
|| $opts(error_output) != "" \
# Add -L$srcdir/$subdir so that the linker command can use
# linker scripts in the source directory.
- set cmd "$LD $LDFLAGS -L$srcdir/$subdir \
+ set cmd "$LD $ld_extra_opt $LDFLAGS -L$srcdir/$subdir \
$opts(ld) -o $objfile $objfiles $opts(ld_after_inputfiles)"
# If needed then check for, or add a -Map option.
} else {
verbose -log "$exitstat with: <$comp_output>, no expected output"
}
- send_log "$comp_output\n"
+ send_log -- "$comp_output\n"
verbose "$comp_output" 3
if { (($check_ld(source) == "") == ($comp_output == "")) \
}
}
} else {
- set objfile "tmpdir/dump0.o"
+ set objfile [lindex $objfiles 0]
}
# We must not have expected failure if we get here.
# in all other cases, any output from the linker during linking is
# treated as a sign of an error and FAILs the test.
#
-proc run_ld_link_tests { ldtests } {
+# args is an optional list of target triplets to be xfailed.
+#
+proc run_ld_link_tests { ldtests args } {
global ld
global as
global nm
global CFLAGS
global runtests
global exec_output
+ global ld_elf_shared_opt
+
+ if { [is_elf_format] && [check_shared_lib_support] } {
+ set ld_extra_opt "$ld_elf_shared_opt"
+ } else {
+ set ld_extra_opt ""
+ }
foreach testitem $ldtests {
set testname [lindex $testitem 0]
continue
}
+ foreach target $args {
+ setup_xfail $target
+ }
+
set ld_options [lindex $testitem 1]
set ld_after [lindex $testitem 2]
set as_options [lindex $testitem 3]
if { ![ar_simple_create $ar $ld_options $binfile "$objfiles $ld_after"] } {
set failed 1
}
- } elseif { ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles $ld_after"] } {
+ } elseif { ![ld_link $ld $binfile "$ld_extra_opt -L$srcdir/$subdir $ld_options $objfiles $ld_after"] } {
set maybe_failed 1
set ld_output "$exec_output"
}
}
}
-# targets_to_xfail is a list of target triplets to be xfailed.
# ldtests contains test-items with 3 items followed by 1 lists, 2 items
# and 3 optional items:
# 0:name
# 6:compiler flags (optional)
# 7:language (optional)
# 8:linker warning (optional)
+# args is an optional list of target triplets to be xfailed.
-proc run_ld_link_exec_tests { targets_to_xfail ldtests } {
+proc run_ld_link_exec_tests { ldtests args } {
global ld
global as
global srcdir
global CXXFLAGS
global errcnt
global exec_output
+ global board_cflags
+
+ # When using GCC as the linker driver, we need to specify board cflags when
+ # linking because cflags may contain linker options. For example when
+ # linker options are included in GCC spec files then we need the -specs
+ # option.
+ if [board_info [target_info name] exists cflags] {
+ set board_cflags " [board_info [target_info name] cflags]"
+ } else {
+ set board_cflags ""
+ }
foreach testitem $ldtests {
- foreach target $targets_to_xfail {
+ foreach target $args {
setup_xfail $target
}
set testname [lindex $testitem 0]
# incorrect section attributes and the assembler will warn
# them.
if { [ string match "c++" $lang ] } {
- ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
+ set cmd "$CXX -c $CXXFLAGS $cflags"
} else {
- ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
+ set cmd "$CC -c $CFLAGS $cflags"
+ }
+ if ![ld_compile $cmd $srcdir/$subdir/$src_file $objfile] {
+ set failed 1
+ break
}
}
+ if { $failed != 0 } {
+ unresolved $testname
+ continue
+ }
- # We have to use $CC to build PIE and shared library.
- if { [ string match "c" $lang ] } {
- set link_proc ld_simple_link
- set link_cmd $CC
- } elseif { [ string match "c++" $lang ] } {
- set link_proc ld_simple_link
+ if { [ string match "c++" $lang ] } {
+ set link_proc ld_link
set link_cmd $CXX
- } elseif { [ string match "-shared" $ld_options ] \
- || [ string match "-pie" $ld_options ] } {
- set link_proc ld_simple_link
- set link_cmd $CC
} else {
set link_proc ld_link
- set link_cmd $ld
+ set link_cmd $CC
}
if { $binfile eq "tmpdir/" } {
# compile only
pass $testname
continue;
- } elseif ![$link_proc $link_cmd $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
+ } elseif ![$link_proc $link_cmd $binfile "$board_cflags -L$srcdir/$subdir $ld_options $objfiles"] {
set failed 1
}
}
}
- if { $failed == 0 } {
+ if { $failed == 0 && [isnative] } {
send_log "Running: $binfile > $binfile.out\n"
verbose "Running: $binfile > $binfile.out"
catch "exec $binfile > $binfile.out" exec_output
if { $failed != 0 } {
fail $testname
+ } elseif ![isnative] {
+ unsupported $testname
} else {
set errcnt 0
pass $testname
# incorrect section attributes and the assembler will warn
# them.
if { [ string match "c++" $lang ] } {
- ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
+ set cmd "$CXX -c $CXXFLAGS $cflags"
} else {
- ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
+ set cmd "$CC -c $CFLAGS $cflags"
+ }
+ if ![ld_compile $cmd $srcdir/$subdir/$src_file $objfile] {
+ set failed 1
+ break
}
}
+ if { $failed != 0 } {
+ unresolved $testname
+ continue
+ }
# Clear error and warning counts.
reset_vars
# compile only
} elseif { [regexp ".*\\.a$" $binfile] } {
if { ![ar_simple_create $ar $ldflags $binfile "$objfiles"] } {
- fail $testname
set failed 1
}
} else {
- if { ![ld_simple_link $cc_cmd $binfile "$board_cflags -L$srcdir/$subdir $ldflags $objfiles"] } {
+ if { ![ld_link $cc_cmd $binfile "$board_cflags -L$srcdir/$subdir $ldflags $objfiles"] } {
set failed 1
}
set failed 1
}
}
-
- if { $failed == 1 } {
- fail $testname
- }
}
if { $failed == 0 } {
}
}
- if { $failed != 0 } {
+ if { $failed } {
fail $testname
- } elseif { $is_unresolved == 0 } {
- pass $testname
- } else {
+ } elseif { $is_unresolved } {
unresolved $testname
- continue
+ } else {
+ pass $testname
}
}
}
if {![info exists gc_sections_available_saved]} {
# Some targets don't support gc-sections despite whatever's
# advertised by ld's options.
- if { [istarget arc*-*-*]
- || [istarget d30v-*-*]
+ if { [istarget d30v-*-*]
|| [istarget dlx-*-*]
|| [istarget i960-*-*]
|| [istarget pj*-*-*]
+ || [istarget pru*-*-*]
|| [istarget alpha-*-*]
|| [istarget hppa*64-*-*]
|| [istarget i370-*-*]
proc check_shared_lib_support { } {
if {![istarget aarch64*-*-elf]
- && ![istarget arc*-*-*]
+ && ![istarget arc*-*-elf*]
&& ![istarget arm*-*-elf]
&& ![istarget avr-*-*]
&& ![istarget cr16-*-*]
&& ![istarget epiphany-*-*]
&& ![istarget fr30-*-*]
&& ![istarget frv-*-*]
+ && ![istarget ft32-*-*]
&& ![istarget h8300-*-*]
&& ![istarget i860-*-*]
&& ![istarget i960-*-*]
&& ![istarget nds32*-*-*]
&& ![istarget or1k*-*-*]
&& ![istarget pj-*-*]
+ && ![istarget pru-*-*]
&& ![istarget rl78-*-*]
&& ![istarget rx-*-*]
&& ![istarget spu-*-*]
&& ![istarget v850*-*-*]
&& ![istarget visium-*-*]
+ && ![istarget xc16x-*-elf]
&& ![istarget xgate-*-*]
&& ![istarget xstormy16-*-*]
&& ![istarget *-*-irix*]
return 0
}
+# Return true if target uses genelf.em (assuming it is ELF).
+proc is_generic_elf { } {
+ if { [istarget "d30v-*-*"]
+ || [istarget "dlx-*-*"]
+ || [istarget "fr30-*-*"]
+ || ([istarget "frv-*-*"] && ![istarget "frv-*-linux*"])
+ || [istarget "ft32-*-*"]
+ || [istarget "i860-*-*"]
+ || [istarget "i960-*-*"]
+ || [istarget "iq2000-*-*"]
+ || [istarget "mn10200-*-*"]
+ || [istarget "moxie-*-*"]
+ || [istarget "msp430-*-*"]
+ || [istarget "mt-*-*"]
+ || [istarget "pj*-*-*"] } {
+ return 1;
+ }
+ return 0;
+}
+
# Returns true if the target ld supports the plugin API.
proc check_plugin_api_available { } {
global plugin_api_available_saved
return $ld_sysroot_available_saved
}
+# Returns 1 if plugin is enabled in gcc. Returns 0 otherwise.
+proc check_gcc_plugin_enabled { } {
+ global CC
+
+ if {![info exists CC]} {
+ set CC [find_gcc]
+ }
+ if { $CC == ""} {
+ return 0
+ }
+ set state [remote_exec host $CC -v]
+ if { [lindex $state 0] != 0 } {
+ return 0;
+ }
+ for { set i 1 } { $i < [llength $state] } { incr i } {
+ set v [lindex $state $i]
+ if { [ string match "*--disable-plugin*" $v ] } {
+ verbose "plugin is disabled by $v"
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
# Returns true if the target compiler supports LTO
proc check_lto_available { } {
global lto_available_saved
global CC
if {![info exists lto_available_saved]} {
- if { [which $CC] == 0 } {
+ if { ![check_gcc_plugin_enabled] } {
set lto_available_saved 0
return 0
}
+ # This test will hide LTO bugs in ld. Since GCC 4.9 adds
+ # -ffat-lto-objects, we always run LTO tests on Linux with
+ # GCC 4.9 or newer.
+ if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
+ set lto_available_saved 1
+ return 1
+ }
# Check if gcc supports -flto -fuse-linker-plugin
set flags ""
if [board_info [target_info name] exists cflags] {
set f [open $src "w"]
puts $f "int main() { return 0; }"
close $f
- remote_download host $src
+ if [is_remote host] {
+ set src [remote_download host $src]
+ }
set lto_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -fuse-linker-plugin $src -o $output"]
remote_file host delete $src
remote_file host delete $output
global CC
if {![info exists lto_fat_available_saved]} {
- if { [which $CC] == 0 } {
+ if { ![check_gcc_plugin_enabled] } {
set lto_fat_available_saved 0
return 0
}
+ # This test will hide LTO bugs in ld. Since GCC 4.9 adds
+ # -ffat-lto-objects, we always run LTO tests on Linux with
+ # GCC 4.9 or newer.
+ if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
+ set lto_fat_available_saved 1
+ return 1
+ }
# Check if gcc supports -flto -fuse-linker-plugin
set flags ""
if [board_info [target_info name] exists cflags] {
set f [open $src "w"]
puts $f "int main() { return 0; }"
close $f
- remote_download host $src
+ if [is_remote host] {
+ set src [remote_download host $src]
+ }
set lto_fat_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -ffat-lto-objects -fuse-linker-plugin $src -o $output"]
remote_file host delete $src
remote_file host delete $output
global CC
if {![info exists lto_shared_available_saved]} {
- if { [which $CC] == 0 } {
+ if { ![check_gcc_plugin_enabled] } {
set lto_shared_available_saved 0
return 0
}
+ # This test will hide LTO bugs in ld. Since GCC 4.9 adds
+ # -ffat-lto-objects, we always run LTO tests on Linux with
+ # GCC 4.9 or newer.
+ if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
+ set lto_shared_available_saved 1
+ return 1
+ }
# Check if gcc supports -flto -fuse-linker-plugin -shared
set flags ""
if [board_info [target_info name] exists cflags] {
set f [open $src "w"]
puts $f ""
close $f
- remote_download host $src
+ if [is_remote host] {
+ set src [remote_download host $src]
+ }
set lto_shared_available_saved [run_host_cmd_yesno "$CC" "$flags -shared -fPIC -flto -fuse-linker-plugin $src -o $output"]
remote_file host delete $src
remote_file host delete $output
puts $f "void *foo (void) { return library_func1; }"
puts $f "__asm__(\".type library_func2, %gnu_indirect_function\");"
close $f
- remote_download host $src
+ if [is_remote host] {
+ set src [remote_download host $src]
+ }
set ifunc_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
if { $ifunc_available_saved == 1 } {
set ifunc_available_saved [run_host_cmd_yesno "$output" ""]
puts $f "static int library_func1 (void) {return 2; }"
puts $f "void *foo (void) { return library_func1; }"
close $f
- remote_download host $src
+ if [is_remote host] {
+ set src [remote_download host $src]
+ }
set ifunc_attribute_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
if { $ifunc_attribute_available_saved == 1 } {
set ifunc_attribute_available_saved [run_host_cmd_yesno "$output" ""]