X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=ld%2Ftestsuite%2Flib%2Fld-lib.exp;h=7e671558ca71b6143901c92b5621edeb368ac433;hb=32769083d1b6b1cb325409b3c9b99c06026f70d7;hp=1833bdd2f039b467a5a2f0701f4201a589db7e0e;hpb=7dd36a6f1ca92cd4ca4776064c604cda7755bc44;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/testsuite/lib/ld-lib.exp b/ld/testsuite/lib/ld-lib.exp index 1833bdd2f0..7e671558ca 100644 --- a/ld/testsuite/lib/ld-lib.exp +++ b/ld/testsuite/lib/ld-lib.exp @@ -1,5 +1,5 @@ # Support routines for LD testsuite. -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2019 Free Software Foundation, Inc. # # This file is part of the GNU Binutils. # @@ -185,38 +185,6 @@ proc is_endian_output_format { object_flags } { } } -# Look for big-endian or little-endian switches in the multlib -# options and translate these into a -EB or -EL switch. Note -# we cannot rely upon proc process_multilib_options to do this -# for us because for some targets the compiler does not support -# -EB/-EL but it does support -mbig-endian/-mlittle-endian, and -# the site.exp file will include the switch "-mbig-endian" -# (rather than "big-endian") which is not detected by proc -# process_multilib_options. -# -proc big_or_little_endian {} { - - if [board_info [target_info name] exists multilib_flags] { - set tmp_flags " [board_info [target_info name] multilib_flags]" - - foreach x $tmp_flags { - case $x in { - {*big*endian eb EB -eb -EB -mb -meb} { - set flags " -EB" - return $flags - } - {*little*endian el EL -el -EL -ml -mel} { - set flags " -EL" - return $flags - } - } - } - } - - set flags "" - return $flags -} - # Link a program using ld # proc default_ld_link { ld target objects } { @@ -441,759 +409,6 @@ proc ld_link_defsyms {} { return $flags } -# run_dump_test FILE (optional:) EXTRA_OPTIONS -# Copied from gas testsuite, tweaked and further extended. -# -# Assemble a .s file, then run some utility on it and check the output. -# -# There should be an assembly language file named FILE.s in the test -# suite directory, and a pattern file called FILE.d. `run_dump_test' -# will assemble FILE.s, run some tool like `objdump', `objcopy', or -# `nm' on the .o file to produce textual output, and then analyze that -# with regexps. The FILE.d file specifies what program to run, and -# what to expect in its output. -# -# The FILE.d file begins with zero or more option lines, which specify -# flags to pass to the assembler, the program to run to dump the -# assembler's output, and the options it wants. The option lines have -# the syntax: -# -# # OPTION: VALUE -# -# OPTION is the name of some option, like "name" or "objdump", and -# VALUE is OPTION's value. The valid options are described below. -# Whitespace is ignored everywhere, except within VALUE. The option -# list ends with the first line that doesn't match the above syntax -# (hmm, not great for error detection). -# -# The optional EXTRA_OPTIONS argument to `run_dump_test' is a list of -# two-element lists. The first element of each is an option name, and -# the second additional arguments to be added on to the end of the -# option list as given in FILE.d. (If omitted, no additional options -# are added.) -# -# The interesting options are: -# -# name: TEST-NAME -# The name of this test, passed to DejaGNU's `pass' and `fail' -# commands. If omitted, this defaults to FILE, the root of the -# .s and .d files' names. -# -# as: FLAGS -# When assembling, pass FLAGS to the assembler. -# If assembling several files, you can pass different assembler -# options in the "source" directives. See below. -# -# ld: FLAGS -# Link assembled files using FLAGS, in the order of the "source" -# directives, when using multiple files. -# -# ld_after_inputfiles: FLAGS -# Similar to "ld", but put after all input files. -# -# objcopy_objects: FLAGS -# Run objcopy with the specified flags after assembling any source -# that has the special marker RUN_OBJCOPY in the source specific -# flags. -# -# objcopy_linked_file: FLAGS -# Run objcopy on the linked file with the specified flags. -# This lets you transform the linked file using objcopy, before the -# result is analyzed by an analyzer program specified below (which -# may in turn *also* be objcopy). -# -# PROG: PROGRAM-NAME -# The name of the program to run to analyze the .o file produced -# by the assembler or the linker output. This can be omitted; -# run_dump_test will guess which program to run by seeing which of -# the flags options below is present. -# -# readelf: FLAGS -# objdump: FLAGS -# nm: FLAGS -# objcopy: FLAGS -# Use the specified program to analyze the assembler or linker -# output file, and pass it FLAGS, in addition to the output name. -# Note that they are run with LC_ALL=C in the environment to give -# consistent sorting of symbols. -# -# source: SOURCE [FLAGS] -# Assemble the file SOURCE.s using the flags in the "as" directive -# and the (optional) FLAGS. If omitted, the source defaults to -# FILE.s. -# This is useful if several .d files want to share a .s file. -# More than one "source" directive can be given, which is useful -# when testing linking. -# -# dump: DUMP -# Match against DUMP.d. If omitted, this defaults to FILE.d. This -# is useful if several .d files differ by options only. Options are -# always read from FILE.d. -# -# xfail: TARGET -# The test is expected to fail on TARGET. This may occur more than -# once. -# -# target: TARGET -# Only run the test for TARGET. -# You may provide target name "cfi" for any target supporting the -# CFI statements. You may provide target name "shared" for any -# target supporting shared libraries. Otherwise TARGET is called -# as a TCL procedure if surrounded by square brackets, or passed -# to "istarget" if not. -# This may occur more than once; the target being tested must match -# at least one. Otherwise the test will be marked unsupported. -# -# alltargets: TARGET -# Only run the test for TARGET. -# The syntax for TARGET is as with 'target'. -# This may occur more than once; the target being tested must match -# all of them. Otherwise the test will be marked unsupported. -# -# notarget: TARGET -# Do not run the test for TARGET. -# The syntax for TARGET is as with 'target'. -# This may occur more than once; the target being tested must not -# match any of them. Otherwise the test will be marked unsupported. -# -# skip: TARGET -# anyskip: TARGET -# noskip: TARGET -# These are exactly the same as "notarget", "alltargets" and -# "target" respectively, except that they do nothing at all if the -# check fails. They should only be used in groups, to construct a -# single test which is run on all targets but with variant options -# or expected output on some targets. (For example, see -# gas/arm/inst.d and gas/arm/wince_inst.d.) -# -# error: REGEX -# An error with message matching REGEX must be emitted for the test -# to pass. The PROG, readelf, objdump, nm and objcopy options have -# no meaning and need not be supplied if this is present. Multiple -# "error" directives append to the expected linker error message. -# -# error_output: FILE -# Means the same as 'error', except the regular expression lines -# are contains in FILE. -# -# warning: REGEX -# Expect a linker warning matching REGEX. It is an error to issue -# both "error" and "warning". Multiple "warning" directives -# append to the expected linker warning message. -# -# warning_output: FILE -# Means the same as 'warning', except the regular expression -# lines are contains in FILE. -# -# map: FILE -# Adding this option will cause the linker to generate a linker -# map file, using the -Map=MAPFILE command line option. If -# there is no -Map=MAPFILE in the 'ld: FLAGS' then one will be -# added to the linker command line. The contents of the -# generated MAPFILE are then compared against the regexp lines -# in FILE using `regexp_diff' (see below for details). -# -# Each option may occur at most once unless otherwise mentioned. -# -# After the option lines come regexp lines. `run_dump_test' calls -# `regexp_diff' to compare the output of the dumping tool against the -# regexps in FILE.d. `regexp_diff' is defined in binutils-common.exp; -# see further comments there. -# -proc run_dump_test { name {extra_options {}} } { - global subdir srcdir - global OBJDUMP NM AS OBJCOPY READELF LD - 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 name [file tail $name] - } else { - set file "$srcdir/$subdir/$name" - } - - if ![runtest_file_p $runtests $name] then { - return - } - - set opt_array [slurp_options "${file}.d"] - if { $opt_array == -1 } { - perror "error reading options from $file.d" - unresolved $subdir/$name - return - } - 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) {} - set opts(xfail) {} - set opts(target) {} - set opts(alltargets) {} - set opts(notarget) {} - set opts(skip) {} - set opts(anyskip) {} - set opts(noskip) {} - set opts(objdump) {} - set opts(nm) {} - set opts(objcopy) {} - set opts(readelf) {} - set opts(name) {} - set opts(PROG) {} - set opts(source) {} - set opts(dump) {} - set opts(error) {} - set opts(warning) {} - set opts(error_output) {} - set opts(warning_output) {} - set opts(objcopy_linked_file) {} - set opts(objcopy_objects) {} - set opts(map) {} - - foreach i $opt_array { - set opt_name [lindex $i 0] - set opt_val [lindex $i 1] - if ![info exists opts($opt_name)] { - perror "unknown option $opt_name in file $file.d" - unresolved $subdir/$name - return - } - - switch -- $opt_name { - xfail {} - target {} - alltargets {} - notarget {} - skip {} - anyskip {} - noskip {} - warning {} - error {} - source { - # Move any source-specific as-flags to a separate list to - # simplify processing. - if { [llength $opt_val] > 1 } { - lappend asflags [lrange $opt_val 1 end] - set opt_val [lindex $opt_val 0] - } 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)] { - perror "option $opt_name multiply set in $file.d" - unresolved $subdir/$name - return - } - - # A single "# ld:" with no options should do the right thing. - if { $opt_name == "ld" } { - set run_ld 1 - } - # Likewise objcopy_linked_file. - if { $opt_name == "objcopy_linked_file" } { - set run_objcopy 1 - } - } - } - if { $opt_name == "as" || $opt_name == "ld" } { - set opt_val [subst $opt_val] - } - - # Append differently whether it's a message (without space) or - # an option or list (with space). - switch -- $opt_name { - warning - - error { - append opts($opt_name) $opt_val - } - default { - set opts($opt_name) [concat $opts($opt_name) $opt_val] - } - } - } - - foreach i $extra_options { - set opt_name [lindex $i 0] - set opt_val [lindex $i 1] - if ![info exists opts($opt_name)] { - perror "unknown option $opt_name given in extra_opts" - unresolved $subdir/$name - return - } - # Add extra option to end of existing option, adding space - # if necessary. - if { ![regexp "warning|error" $opt_name] - && [string length $opts($opt_name)] } { - append opts($opt_name) " " - } - append opts($opt_name) $opt_val - } - - foreach opt { as ld } { - regsub {\[big_or_little_endian\]} $opts($opt) \ - [big_or_little_endian] opts($opt) - } - - if { $opts(name) == "" } { - set testname "$subdir/$name" - } else { - set testname $opts(name) - } - - # Decide early whether we should run the test for this target. - if { [llength $opts(noskip)] > 0 } { - set targmatch 0 - foreach targ $opts(noskip) { - if [match_target $targ] { - set targmatch 1 - break - } - } - if { $targmatch == 0 } { - return - } - } - foreach targ $opts(anyskip) { - if ![match_target $targ] { - return - } - } - foreach targ $opts(skip) { - if [match_target $targ] { - return - } - } - if { [llength $opts(target)] > 0 } { - set targmatch 0 - foreach targ $opts(target) { - if [match_target $targ] { - set targmatch 1 - break - } - } - if { $targmatch == 0 } { - unsupported $testname - return - } - } - foreach targ $opts(alltargets) { - if ![match_target $targ] { - unsupported $testname - return - } - } - foreach targ $opts(notarget) { - if [match_target $targ] { - unsupported $testname - return - } - } - - set program "" - # It's meaningless to require an output-testing method when we - # expect an error. - if { $opts(error) == "" && $opts(error_output) == "" } { - if {$opts(PROG) != ""} { - switch -- $opts(PROG) { - objdump { set program objdump } - nm { set program nm } - objcopy { set program objcopy } - readelf { set program readelf } - default - { perror "unrecognized program option $opts(PROG) in $file.d" - unresolved $testname - return } - } - } else { - # Guess which program to run, by seeing which option was specified. - foreach p {objdump objcopy nm readelf} { - if {$opts($p) != ""} { - if {$program != ""} { - perror "ambiguous dump program in $file.d" - unresolved $testname - return - } else { - set program $p - } - } - } - } - if { $program == "" \ - && $opts(map) == "" \ - && $opts(warning) == "" \ - && $opts(warning_output) == "" \ - && $opts(error) == "" \ - && $opts(error_output) == "" } { - perror "dump program unspecified in $file.d" - unresolved $testname - return - } - } - - 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) { - if { [string match "/*" $sf] } { - lappend sourcefiles "$sf" - } else { - lappend sourcefiles "$srcdir/$subdir/$sf" - } - } - } - - if { $opts(dump) == "" } { - set dfile ${file}.d - } else { - set dfile $srcdir/$subdir/$opts(dump) - } - - # Time to setup xfailures. - foreach targ $opts(xfail) { - setup_xfail $targ - } - - # Assemble each file. - set objfiles {} - for { set i 0 } { $i < [llength $sourcefiles] } { incr i } { - set sourcefile [lindex $sourcefiles $i] - set sourceasflags [lindex $asflags $i] - set run_objcopy_objects 0 - - if { [string match "*RUN_OBJCOPY*" $sourceasflags] } { - set run_objcopy_objects 1 - } - regsub "RUN_OBJCOPY" $sourceasflags "" sourceasflags - - 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" - - send_log "$cmd\n" - set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"] - remote_upload host "ld.tmp" - set comp_output [prune_warnings [file_contents "ld.tmp"]] - remote_file host delete "ld.tmp" - remote_file build delete "ld.tmp" - - if { [lindex $cmdret 0] != 0 || ![string match "" $comp_output] } then { - send_log -- "$comp_output\n" - verbose "$comp_output" 3 - - set exitstat "succeeded" - if { $cmdret != 0 } { set exitstat "failed" } - verbose -log "$exitstat with: <$comp_output>" - fail $testname - return - } - - if { $run_objcopy_objects } { - set cmd "$OBJCOPY $opts(objcopy_objects) $objfile" - - send_log "$cmd\n" - set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] \ - "" "/dev/null" "objcopy.tmp"] - remote_upload host "objcopy.tmp" - set comp_output [prune_warnings [file_contents "objcopy.tmp"]] - remote_file host delete "objcopy.tmp" - remote_file build delete "objcopy.tmp" - - if { [lindex $cmdret 0] != 0 \ - || ![string match "" $comp_output] } { - send_log -- "$comp_output\n" - verbose "$comp_output" 3 - - set exitstat "succeeded" - if { $cmdret != 0 } { set exitstat "failed" } - verbose -log "$exitstat with: <$comp_output>" - fail $testname - return - } - } - } - - if { (($opts(warning) != "") && ($opts(error) != "")) \ - || (($opts(warning) != "") && ($opts(error_output) != "")) \ - || (($opts(warning) != "") && ($opts(warning_output) != "")) \ - || (($opts(error) != "") && ($opts(warning_output) != "")) \ - || (($opts(error) != "") && ($opts(error_output) != "")) \ - || (($opts(warning_output) != "") && ($opts(error_output) != "")) } { - perror "$testname: bad mix of warning, error, warning_output, and error_output test-directives" - unresolved $testname - return - } - - set check_ld(source) "" - set check_ld(terminal) 0 - if { $opts(error) != "" \ - || $opts(warning) != "" \ - || $opts(error_output) != "" \ - || $opts(warning_output) != "" } { - - if { $opts(error) != "" || $opts(error_output) != "" } { - set check_ld(terminal) 1 - } else { - set check_ld(terminal) 0 - } - - if { $opts(error) != "" || $opts(warning) != "" } { - set check_ld(source) "regex" - if { $opts(error) != "" } { - set check_ld(regex) $opts(error) - } else { - set check_ld(regex) $opts(warning) - } - } else { - set check_ld(source) "file" - if { $opts(error_output) != "" } { - set check_ld(file) $opts(error_output) - } else { - set check_ld(file) $opts(warning_output) - } - } - } - - # Perhaps link the file(s). - if { $run_ld } { - set objfile "tmpdir/dump" - catch "exec rm -f $objfile" exec_output - - # Add -L$srcdir/$subdir so that the linker command can use - # linker scripts in the source directory. - 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. - set mapfile "" - if { $opts(map) != "" } then { - if { [regexp -- "-Map=(\[^ \]+)" $cmd all mapfile] } then { - # Found existing mapfile option - verbose -log "Existing mapfile '$mapfile' found" - } else { - # No mapfile option. - set mapfile "tmpdir/dump.map" - verbose -log "Adding mapfile '$mapfile'" - set cmd "$cmd -Map=$mapfile" - } - } - - send_log "$cmd\n" - set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"] - remote_upload host "ld.tmp" - set comp_output [file_contents "ld.tmp"] - remote_file host delete "ld.tmp" - remote_file build delete "ld.tmp" - set cmdret [lindex $cmdret 0] - - if { $cmdret == 0 && $run_objcopy } { - set infile $objfile - set objfile "tmpdir/dump1" - remote_file host delete $objfile - - # Note that we don't use OBJCOPYFLAGS here; any flags must be - # explicitly specified. - set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile" - - send_log "$cmd\n" - set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"] - remote_upload host "ld.tmp" - append comp_output [file_contents "ld.tmp"] - remote_file host delete "ld.tmp" - remote_file build delete "ld.tmp" - set cmdret [lindex $cmdret 0] - } - - regsub "\n$" $comp_output "" comp_output - if { $cmdret != 0 || $comp_output != "" || $check_ld(source) != "" } then { - set exitstat "succeeded" - if { $cmdret != 0 } { set exitstat "failed" } - - if { $check_ld(source) == "regex" } { - verbose -log "$exitstat with: <$comp_output>, expected: <$check_ld(regex)>" - } elseif { $check_ld(source) == "file" } { - verbose -log "$exitstat with: <$comp_output>, expected in file $check_ld(file)" - set_file_contents "tmpdir/ld.messages" "$comp_output" - } else { - verbose -log "$exitstat with: <$comp_output>, no expected output" - } - send_log -- "$comp_output\n" - verbose "$comp_output" 3 - - if { (($check_ld(source) == "") == ($comp_output == "")) \ - && (($cmdret == 0) == ($check_ld(terminal) == 0)) \ - && ((($check_ld(source) == "regex") \ - && ($check_ld(regex) == "") == ($comp_output == "") \ - && [regexp -- $check_ld(regex) $comp_output]) \ - || (($check_ld(source) == "file") \ - && (![regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$check_ld(file)"]))) } { - # We have the expected output from ld. - if { $check_ld(terminal) || $program == "" } { - pass $testname - return - } - } else { - fail $testname - return - } - } - - if { $opts(map) != "" } then { - # Check the map file matches. - set map_pattern_file $srcdir/$subdir/$opts(map) - verbose -log "Compare '$mapfile' against '$map_pattern_file'" - if { [regexp_diff $mapfile $map_pattern_file] } then { - fail "$testname (map file check)" - } else { - pass "$testname (map file check)" - } - - if { $program == "" } then { - return - } - } - } else { - set objfile [lindex $objfiles 0] - } - - # We must not have expected failure if we get here. - if { $opts(error) != "" } { - fail $testname - return - } - - set progopts1 $opts($program) - eval set progopts \$[string toupper $program]FLAGS - eval set binary \$[string toupper $program] - - if { ![is_remote host] && [which $binary] == 0 } { - untested $testname - return - } - - if { $progopts1 == "" } { set $progopts1 "-r" } - verbose "running $binary $progopts $progopts1" 3 - - # Objcopy, unlike the other two, won't send its output to stdout, - # so we have to run it specially. - set cmd "$binary $progopts $progopts1 $objfile > $dumpfile" - if { $program == "objcopy" } { - set cmd "$binary $progopts $progopts1 $objfile $dumpfile" - } - - # Ensure consistent sorting of symbols - if {[info exists env(LC_ALL)]} { - set old_lc_all $env(LC_ALL) - } - set env(LC_ALL) "C" - send_log "$cmd\n" - set cmdret [remote_exec host [concat sh -c [list "$cmd 2>ld.tmp"]] "" "/dev/null"] - set cmdret [lindex $cmdret 0] - remote_upload host "ld.tmp" - set comp_output [prune_warnings [file_contents "ld.tmp"]] - remote_file host delete "ld.tmp" - remote_file build delete "ld.tmp" - if {[info exists old_lc_all]} { - set env(LC_ALL) $old_lc_all - } else { - unset env(LC_ALL) - } - if { $cmdret != 0 || $comp_output != "" } { - send_log "exited abnormally with $cmdret, output:$comp_output\n" - fail $testname - return - } - - if { $verbose > 2 } then { verbose "output is [file_contents $dumpfile]" 3 } - if { [regexp_diff $dumpfile "${dfile}"] } then { - fail $testname - if { $verbose == 2 } then { verbose "output is [file_contents $dumpfile]" 2 } - return - } - - pass $testname -} - -proc slurp_options { file } { - # If options_regsub(foo) is set to {a b}, then the contents of a - # "#foo:" line will have regsub -all applied to replace a with b. - global options_regsub - - if [catch { set f [open $file r] } x] { - #perror "couldn't open `$file': $x" - perror "$x" - return -1 - } - set opt_array {} - # whitespace expression - set ws {[ ]*} - set nws {[^ ]*} - # whitespace is ignored anywhere except within the options list; - # option names are alphabetic plus underscore only. - set pat "^#${ws}(\[a-zA-Z_\]*)$ws:${ws}(.*)$ws\$" - while { [gets $f line] != -1 } { - set line [string trim $line] - # Whitespace here is space-tab. - if [regexp $pat $line xxx opt_name opt_val] { - # match! - if [info exists options_regsub($opt_name)] { - set subst $options_regsub($opt_name) - regsub -all -- [lindex $subst 0] $opt_val [lindex $subst 1] \ - opt_val - } - lappend opt_array [list $opt_name $opt_val] - } else { - break - } - } - close $f - return $opt_array -} - -proc file_contents { filename } { - set file [open $filename r] - set contents [read $file] - close $file - return $contents -} - -proc set_file_contents { filename contents } { - set file [open $filename w] - puts $file "$contents" - close $file -} - # Create an archive using ar # proc ar_simple_create { ar aropts target objects } { @@ -1264,7 +479,10 @@ proc run_ld_link_tests { ldtests args } { } foreach target $args { - setup_xfail $target + if [match_target $target] { + setup_xfail "*-*-*" + break + } } set ld_options [lindex $testitem 1] @@ -1457,9 +675,6 @@ proc run_ld_link_exec_tests { ldtests args } { } foreach testitem $ldtests { - foreach target $args { - setup_xfail $target - } set testname [lindex $testitem 0] set ld_options [lindex $testitem 1] set as_options [lindex $testitem 2] @@ -1473,6 +688,18 @@ proc run_ld_link_exec_tests { ldtests args } { set objfiles {} set failed 0 + if { ![check_compiler_available] } { + unsupported $testname + continue + } + + foreach target $args { + if [match_target $target] { + setup_xfail "*-*-*" + break + } + } + # verbose -log "Testname is $testname" # verbose -log "ld_options is $ld_options" # verbose -log "as_options is $as_options" @@ -1625,6 +852,11 @@ proc run_cc_link_tests { ldtests } { set check_ld(terminal) 0 set check_ld(source) "" + if { ![check_compiler_available] } { + unsupported $testname + continue + } + #verbose -log "testname is $testname" #verbose -log "ldflags is $ldflags" #verbose -log "cflags is $cflags" @@ -1820,6 +1052,7 @@ proc check_gc_sections_available { } { # Some targets don't support gc-sections despite whatever's # advertised by ld's options. if { [istarget alpha-*-*] + || [istarget bpf-*-*] || [istarget d30v-*-*] || [istarget dlx-*-*] || [istarget hppa*64-*-*] @@ -1828,6 +1061,7 @@ proc check_gc_sections_available { } { || [istarget mn10200-*-*] || [istarget pj*-*-*] || [istarget pru*-*-*] + || [istarget s12z-*-*] || [istarget xgate-*-*] } { set gc_sections_available_saved 0 return 0 @@ -1854,25 +1088,20 @@ proc check_gc_sections_available { } { return $gc_sections_available_saved } -# Returns true if -shared is supported on the target - -proc check_shared_lib_support { } { - global shared_available_saved - global ld - - if {![info exists shared_available_saved]} { - set ld_output [remote_exec host $ld "-shared"] - if { [ string first "not supported" $ld_output ] >= 0 } { - set shared_available_saved 0 - } else { - set shared_available_saved 1 - } +# Return true if target uses the generic_link_hash_table linker. +proc is_generic { } { + if { [istarget "d30v-*-*"] + || [istarget "dlx-*-*"] + || [istarget "pj*-*-*"] + || [istarget "s12z-*-*"] + || [istarget "xgate-*-*"] } { + return 1 } - return $shared_available_saved + return 0 } -# Return true if target uses genelf.em (assuming it is ELF). -proc is_generic_elf { } { +# Return true if target uses genelf.em. +proc uses_genelf { } { if { [istarget "d30v-*-*"] || [istarget "dlx-*-*"] || [istarget "fr30-*-*"] @@ -1880,14 +1109,14 @@ proc is_generic_elf { } { || [istarget "ft32-*-*"] || [istarget "iq2000-*-*"] || [istarget "mn10200-*-*"] - || [istarget "moxie-*-*"] || [istarget "msp430-*-*"] || [istarget "mt-*-*"] || [istarget "pj*-*-*"] + || [istarget "s12z-*-*"] || [istarget "xgate-*-*"] } { - return 1; + return 1 } - return 0; + return 0 } proc is_underscore_target { } { @@ -1941,6 +1170,49 @@ proc check_sysroot_available { } { return $ld_sysroot_available_saved } +# Return true if we can build a program with the compiler. +# On some targets, CC might be defined, but libraries and startup +# code might be missing or require special options that the ld test +# harness doesn't know about. + +proc check_compiler_available { } { + global compiler_available_saved + global CC + + if {![info exists compiler_available_saved]} { + if { [which $CC] == 0 } { + set compiler_available_saved 0 + return 0 + } + + set flags "" + if [board_info [target_info name] exists cflags] { + append flags " [board_info [target_info name] cflags]" + } + if [board_info [target_info name] exists ldflags] { + append flags " [board_info [target_info name] ldflags]" + } + + set basename "tmpdir/compiler[pid]" + set src ${basename}.c + set output ${basename}.out + set f [open $src "w"] + puts $f "int main (void)" + puts $f "{" + puts $f " return 0; " + puts $f "}" + close $f + if [is_remote host] { + set src [remote_download host $src] + } + set compiler_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"] + remote_file host delete $src + remote_file host delete $output + file delete $src + } + return $compiler_available_saved +} + # Returns 1 if plugin is enabled in gcc. Returns 0 otherwise. proc check_gcc_plugin_enabled { } { global CC @@ -2128,7 +1400,7 @@ proc check_ifunc_available { } { global CC if {![info exists ifunc_available_saved]} { - if { [which $CC] == 0 } { + if { ![check_compiler_available] } { set ifunc_available_saved 0 return 0 } @@ -2177,7 +1449,7 @@ proc check_ifunc_attribute_available { } { global CC if {![info exists ifunc_attribute_available_saved]} { - if { [which $CC] == 0 } { + if { ![check_compiler_available] } { set ifunc_attribute_available_saved 0 return 0 } @@ -2217,19 +1489,6 @@ proc check_ifunc_attribute_available { } { return $ifunc_attribute_available_saved } -# Provide virtual target "cfi" for targets supporting CFI. - -rename "istarget" "istarget_ld" -proc istarget { target } { - if {$target == "cfi"} { - return [check_as_cfi] - } - if {$target == "shared"} { - return [check_shared_lib_support] - } - return [istarget_ld $target] -} - # Return true if libdl is supported. proc check_libdl_available { } { @@ -2237,7 +1496,7 @@ proc check_libdl_available { } { global CC if {![info exists libdl_available_saved]} { - if { [which $CC] == 0 } { + if { ![check_compiler_available] } { set libdl_available_saved 0 return 0 } @@ -2273,7 +1532,7 @@ proc check_gnu2_tls_available { } { global GNU2_CFLAGS if {![info exists gnu2_tls_available_saved]} { - if { [which $CC] == 0 || "$GNU2_CFLAGS" == "" } { + if { ![check_compiler_available] || "$GNU2_CFLAGS" == "" } { set gnu2_tls_available_saved 0 return 0 }