Home | History | Annotate | Download | only in lib
      1 # Support routines for LD testsuite.
      2 #   Copyright (C) 1994-2014 Free Software Foundation, Inc.
      3 #
      4 # This file is part of the GNU Binutils.
      5 #
      6 # This file is free software; you can redistribute it and/or modify
      7 # it under the terms of the GNU General Public License as published by
      8 # the Free Software Foundation; either version 3 of the License, or
      9 # (at your option) any later version.
     10 #
     11 # This program is distributed in the hope that it will be useful,
     12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 # GNU General Public License for more details.
     15 #
     16 # You should have received a copy of the GNU General Public License
     17 # along with this program; if not, write to the Free Software
     18 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19 # MA 02110-1301, USA.
     20 
     21 proc load_common_lib { name } {
     22     global srcdir
     23     load_file $srcdir/../../binutils/testsuite/lib/$name
     24 }
     25 
     26 load_common_lib binutils-common.exp
     27 
     28 # Returns 1 if the gcc for the target is at least version MAJOR.MINOR
     29 # Returns 0 otherwise.
     30 #
     31 proc at_least_gcc_version { major minor } {
     32 
     33     if {![info exists CC]} {
     34 	set CC [find_gcc]
     35     }
     36     if { $CC == "" } {
     37       return 0
     38     }
     39     set state [remote_exec host $CC --version]
     40     set tmp "[lindex $state 1]\n"
     41     # Look for (eg) 4.6.1 in the version output.
     42     set ver_re "\[^\\.0-9\]+(\[1-9\]\[0-9\]*)\\.(\[0-9\]+)(?:\\.\[0-9\]+)?"
     43     regexp $ver_re $tmp fred maj min
     44     verbose "gcc version: $tmp"
     45     if { ![info exists maj] || ![info exists min] } then {
     46 	perror "can't decipher gcc version number, fix the framework!"
     47 	return 0
     48     }
     49     verbose "major gcc version is $maj, want at least $major"
     50     if { $maj == $major } then {
     51 	verbose "minor gcc version is $min, want at least $minor"
     52 	return [expr $min >= $minor]
     53     } else {
     54 	return [expr $maj > $major]
     55     }
     56 }
     57 
     58 # Extract and print the version number of ld.
     59 #
     60 proc default_ld_version { ld } {
     61     global host_triplet
     62 
     63     if { ![is_remote host] && [which $ld] == 0 } then {
     64 	perror "$ld does not exist"
     65 	exit 1
     66     }
     67 
     68     remote_exec host "$ld --version" "" "/dev/null" "ld.version"
     69     remote_upload host "ld.version"
     70     set tmp [prune_warnings [file_contents "ld.version"]]
     71     remote_file build delete "ld.version"
     72     remote_file host delete "ld.version"
     73 
     74     regexp "\[^\n\]* (cygnus-|)(\[-0-9.a-zA-Z-\]+)\[\r\n\].*" $tmp version cyg number
     75     if [info exists number] then {
     76 	clone_output "$ld $number\n"
     77     }
     78 }
     79 
     80 proc run_host_cmd { prog command } {
     81     global link_output
     82     global gcc_B_opt
     83     global ld_L_opt
     84 
     85     if { ![is_remote host] && [which "$prog"] == 0 } then {
     86 	perror "$prog does not exist"
     87 	return 0
     88     }
     89 
     90     # If we are compiling with gcc, we want to add gcc_B_opt and
     91     # ld_L_opt to flags.  However, if $prog already has -B options,
     92     # which might be the case when running gcc out of a build
     93     # directory, we want our -B options to come first.
     94     set gccexe $prog
     95     set gccparm [string first " " $gccexe]
     96     set gccflags ""
     97     if { $gccparm > 0 } then {
     98 	set gccflags [string range $gccexe $gccparm end]
     99 	set gccexe [string range $gccexe 0 $gccparm]
    100 	set prog $gccexe
    101     }
    102     set gccexe [string replace $gccexe 0 [string last "/" $gccexe] ""]
    103     if {[string match "*cc*" $gccexe] || [string match "*++*" $gccexe]} then {
    104 	set gccflags "$gcc_B_opt $gccflags $ld_L_opt"
    105     }
    106 
    107     verbose -log "$prog $gccflags $command"
    108     set status [remote_exec host [concat sh -c [list "$prog $gccflags $command 2>&1"]] "" "/dev/null" "ld.tmp"]
    109     remote_upload host "ld.tmp"
    110     set link_output [file_contents "ld.tmp"]
    111     regsub "\n$" $link_output "" link_output
    112     if { [lindex $status 0] != 0 && [string match "" $link_output] } then {
    113 	append link_output "child process exited abnormally"
    114     }
    115     remote_file build delete ld.tmp
    116     remote_file host delete ld.tmp
    117 
    118     if [string match "" $link_output] then {
    119 	return ""
    120     }
    121 
    122     verbose -log "$link_output"
    123     return "$link_output"
    124 }
    125 
    126 proc run_host_cmd_yesno { prog command } {
    127     global exec_output
    128 
    129     set exec_output [prune_warnings [run_host_cmd "$prog" "$command"]]
    130     if [string match "" $exec_output] then {
    131 	return 1;
    132     }
    133     return 0;
    134 }
    135 
    136 # Link an object using relocation.
    137 #
    138 proc default_ld_relocate { ld target objects } {
    139     global HOSTING_EMU
    140 
    141     remote_file host delete $target
    142     return [run_host_cmd_yesno "$ld" "$HOSTING_EMU -o $target -r $objects"]
    143 }
    144 
    145 # Check to see if ld is being invoked with a non-endian output format
    146 #
    147 proc is_endian_output_format { object_flags } {
    148 
    149     if {[string match "*-oformat binary*" $object_flags] ||      \
    150         [string match "*-oformat ieee*" $object_flags] ||        \
    151 	[string match "*-oformat ihex*" $object_flags] ||        \
    152 	[string match "*-oformat netbsd-core*" $object_flags] || \
    153 	[string match "*-oformat srec*" $object_flags] ||        \
    154 	[string match "*-oformat tekhex*" $object_flags] ||      \
    155 	[string match "*-oformat trad-core*" $object_flags] } then {
    156         return 0
    157     } else {
    158 	return 1
    159     }
    160 }
    161 
    162 # Look for big-endian or little-endian switches in the multlib
    163 # options and translate these into a -EB or -EL switch.  Note
    164 # we cannot rely upon proc process_multilib_options to do this
    165 # for us because for some targets the compiler does not support
    166 # -EB/-EL but it does support -mbig-endian/-mlittle-endian, and
    167 # the site.exp file will include the switch "-mbig-endian"
    168 # (rather than "big-endian") which is not detected by proc
    169 # process_multilib_options.
    170 #
    171 proc big_or_little_endian {} {
    172 
    173     if [board_info [target_info name] exists multilib_flags] {
    174 	set tmp_flags " [board_info [target_info name] multilib_flags]"
    175 
    176 	foreach x $tmp_flags {
    177 	    case $x in {
    178 		{*big*endian eb EB -eb -EB -mb -meb} {
    179 		    set flags " -EB"
    180 		    return $flags
    181 		}
    182 		{*little*endian el EL -el -EL -ml -mel} {
    183 		    set flags " -EL"
    184 		    return $flags
    185 		}
    186 	    }
    187 	}
    188     }
    189 
    190     set flags ""
    191     return $flags
    192 }
    193 
    194 # Link a program using ld.
    195 #
    196 proc default_ld_link { ld target objects } {
    197     global HOSTING_EMU
    198     global HOSTING_CRT0
    199     global HOSTING_SCRT0
    200     global HOSTING_LIBS
    201     global HOSTING_SLIBS
    202     global LIBS
    203     global host_triplet
    204     global link_output
    205     global exec_output
    206 
    207     if { [ string match "* -pie *" $objects ] } {
    208 	set objs "$HOSTING_SCRT0 $objects"
    209 	set libs "$LIBS $HOSTING_SLIBS"
    210     } else {
    211 	set objs "$HOSTING_CRT0 $objects"
    212 	set libs "$LIBS $HOSTING_LIBS"
    213     }
    214 
    215     if [is_endian_output_format $objects] then {
    216 	set flags [big_or_little_endian]
    217     } else {
    218 	set flags ""
    219     }
    220 
    221     remote_file host delete $target
    222 
    223     return [run_host_cmd_yesno "$ld" "$HOSTING_EMU $flags -o $target $objs $libs"]
    224 }
    225 
    226 # Link a program using ld, without including any libraries.
    227 #
    228 proc default_ld_simple_link { ld target objects } {
    229     global host_triplet
    230     global exec_output
    231 
    232     set flags ""
    233     if [is_endian_output_format $objects] then {
    234 	set flags [big_or_little_endian]
    235     }
    236 
    237     remote_file host delete $target
    238     set exec_output [run_host_cmd "$ld" "$flags -o $target $objects"]
    239     set exec_output [prune_warnings $exec_output]
    240 
    241     # We don't care if we get a warning about a non-existent start
    242     # symbol, since the default linker script might use ENTRY.
    243     regsub -all "(^|\n)(\[^\n\]*: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
    244 
    245     return [string match "" $exec_output]
    246 }
    247 
    248 # Compile an object using cc.
    249 #
    250 proc default_ld_compile { cc source object } {
    251     global CFLAGS
    252     global CXXFLAGS
    253     global srcdir
    254     global subdir
    255     global host_triplet
    256     global gcc_B_opt
    257 
    258     set cc_prog $cc
    259     if {[llength $cc_prog] > 1} then {
    260 	set cc_prog [lindex $cc_prog 0]
    261     }
    262     if {![is_remote host] && [which $cc_prog] == 0} then {
    263 	perror "$cc_prog does not exist"
    264 	return 0
    265     }
    266 
    267     remote_file build delete "$object"
    268     remote_file host delete "$object"
    269 
    270     set flags "$gcc_B_opt -I$srcdir/$subdir"
    271 
    272     # If we are compiling with gcc, we want to add gcc_B_opt to flags.
    273     # However, if $prog already has -B options, which might be the
    274     # case when running gcc out of a build directory, we want our -B
    275     # options to come first.
    276     set ccexe $cc
    277     set ccparm [string first " " $cc]
    278     set ccflags ""
    279     if { $ccparm > 0 } then {
    280 	set ccflags [string range $cc $ccparm end]
    281 	set ccexe [string range $cc 0 $ccparm]
    282 	set cc $ccexe
    283     }
    284 
    285     set ccexe [string replace $ccexe 0 [string last "/" $ccexe] ""]
    286     if {[string match "*++*" $ccexe]} {
    287 	append flags " $CXXFLAGS"
    288     } else {
    289 	append flags " $CFLAGS"
    290     }
    291 
    292     if [board_info [target_info name] exists cflags] {
    293         append flags " [board_info [target_info name] cflags]"
    294     }
    295 
    296     if [board_info [target_info name] exists multilib_flags] {
    297 	append flags " [board_info [target_info name] multilib_flags]"
    298     }
    299 
    300     set cmd "$cc $flags $ccflags -c $source -o $object"
    301     verbose -log "$cmd"
    302 
    303     set status [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
    304     remote_upload host "ld.tmp"
    305     set exec_output [file_contents "ld.tmp"]
    306     remote_file build delete "ld.tmp"
    307     remote_file host delete "ld.tmp"
    308     set exec_output [prune_warnings $exec_output]
    309     if [string match "" $exec_output] then {
    310 	if {![file exists $object]} then {
    311 	    regexp ".*/(\[^/\]*)$" $source all dobj
    312 	    regsub "\\.c" $dobj ".o" realobj
    313 	    verbose "looking for $realobj"
    314 	    if {[remote_file host exists $realobj]} then {
    315 		verbose -log "mv $realobj $object"
    316 		remote_upload "$realobj" "$object"
    317 	    } else {
    318 		perror "$object not found after compilation"
    319 		return 0
    320 	    }
    321 	}
    322 	return 1
    323     } else {
    324 	verbose -log "$exec_output"
    325 	perror "$source: compilation failed"
    326 	return 0
    327     }
    328 }
    329 
    330 # Assemble a file.
    331 #
    332 proc default_ld_assemble { as in_flags source object } {
    333     global ASFLAGS
    334     global host_triplet
    335     global srcdir
    336     global subdir
    337 
    338     if ![info exists ASFLAGS] { set ASFLAGS "" }
    339 
    340     set flags "[big_or_little_endian] -I$srcdir/$subdir"
    341     set exec_output [run_host_cmd "$as" "$flags $in_flags $ASFLAGS -o $object $source"]
    342     set exec_output [prune_warnings $exec_output]
    343     if [string match "" $exec_output] then {
    344 	return 1
    345     } else {
    346 	perror "$source: assembly failed"
    347 	return 0
    348     }
    349 }
    350 
    351 # Run nm on a file, putting the result in the array nm_output.
    352 #
    353 proc default_ld_nm { nm nmflags object } {
    354     global NMFLAGS
    355     global nm_output
    356     global host_triplet
    357 
    358     if {[info exists nm_output]} {
    359       unset nm_output
    360     }
    361 
    362     if ![info exists NMFLAGS] { set NMFLAGS "" }
    363 
    364     # Ensure consistent sorting of symbols
    365     if {[info exists env(LC_ALL)]} {
    366 	set old_lc_all $env(LC_ALL)
    367     }
    368     set env(LC_ALL) "C"
    369 
    370     verbose -log "$nm $NMFLAGS $nmflags $object >tmpdir/nm.out"
    371 
    372     set status [remote_exec host [concat sh -c [list "$nm $NMFLAGS $nmflags $object 2>ld.stderr"]] "" "/dev/null" "tmpdir/nm.out"]
    373     if {[info exists old_lc_all]} {
    374 	set env(LC_ALL) $old_lc_all
    375     } else {
    376 	unset env(LC_ALL)
    377     }
    378     remote_upload host "ld.stderr"
    379     remote_upload host "tmpdir/nm.out" "tmpdir/nm.out"
    380     set exec_output [prune_warnings [file_contents "ld.stderr"]]
    381     remote_file host delete "ld.stderr"
    382     remote_file build delete "ld.stderr"
    383     if [string match "" $exec_output] then {
    384 	set file [open tmpdir/nm.out r]
    385 	while { [gets $file line] != -1 } {
    386 	    verbose "$line" 2
    387 	    if [regexp "^(\[0-9a-fA-F\]+) \[a-zA-Z0-9\] \\.*(.+)$" $line whole value name] {
    388                 set name [string trimleft $name "_"]
    389 		verbose "Setting nm_output($name) to 0x$value" 2
    390 		set nm_output($name) 0x$value
    391 	    }
    392 	}
    393 	close $file
    394 	return 1
    395     } else {
    396 	verbose -log "$exec_output"
    397 	perror "$object: nm failed"
    398 	return 0
    399     }
    400 }
    401 
    402 # Define various symbols needed when not linking against all
    403 # target libs.
    404 proc ld_simple_link_defsyms {} {
    405 
    406     set flags "--defsym __stack_chk_fail=0"
    407 
    408     # ARM targets call __gccmain
    409     if {[istarget arm*-*-*]} {
    410         append flags " --defsym __gccmain=0"
    411     }
    412 
    413     # Windows targets need __main, some prefixed with underscore.
    414     if {[istarget *-*-cygwin* ] || [istarget *-*-mingw*]} {
    415         append flags " --defsym __main=0 --defsym ___main=0"
    416     }
    417 
    418     # PowerPC EABI code calls __eabi.
    419     if {[istarget powerpc*-*-eabi*] || [istarget powerpc*-*-rtems*]} {
    420 	append flags " --defsym __eabi=0"
    421     }
    422 
    423     # mn10200 code calls __truncsipsi2_d0_d2.
    424     if {[istarget mn10200*-*-*]} then {
    425 	append flags " --defsym __truncsipsi2_d0_d2=0"
    426     }
    427 
    428     # m6811/m6812 code has references to soft registers.
    429     if {[istarget m6811-*-*] || [istarget m6812-*-*] || [istarget m68hc1*-*-*]} {
    430 	append flags " --defsym _.frame=0 --defsym _.d1=0 --defsym _.d2=0"
    431 	append flags " --defsym _.d3=0 --defsym _.d4=0"
    432 	append flags " --defsym _.tmp=0 --defsym _.xy=0 --defsym _.z=0"
    433     }
    434 
    435     # Some OpenBSD targets have ProPolice and reference __guard and
    436     # __stack_smash_handler.
    437     if [istarget *-*-openbsd*] {
    438 	append flags " --defsym __guard=0"
    439 	append flags " --defsym __stack_smash_handler=0"
    440     }
    441 
    442     return $flags
    443 }
    444 
    445 # run_dump_test FILE (optional:) EXTRA_OPTIONS
    446 # Copied from gas testsuite, tweaked and further extended.
    447 #
    448 # Assemble a .s file, then run some utility on it and check the output.
    449 #
    450 # There should be an assembly language file named FILE.s in the test
    451 # suite directory, and a pattern file called FILE.d.  `run_dump_test'
    452 # will assemble FILE.s, run some tool like `objdump', `objcopy', or
    453 # `nm' on the .o file to produce textual output, and then analyze that
    454 # with regexps.  The FILE.d file specifies what program to run, and
    455 # what to expect in its output.
    456 #
    457 # The FILE.d file begins with zero or more option lines, which specify
    458 # flags to pass to the assembler, the program to run to dump the
    459 # assembler's output, and the options it wants.  The option lines have
    460 # the syntax:
    461 #
    462 #         # OPTION: VALUE
    463 #
    464 # OPTION is the name of some option, like "name" or "objdump", and
    465 # VALUE is OPTION's value.  The valid options are described below.
    466 # Whitespace is ignored everywhere, except within VALUE.  The option
    467 # list ends with the first line that doesn't match the above syntax
    468 # (hmm, not great for error detection).
    469 #
    470 # The optional EXTRA_OPTIONS argument to `run_dump_test' is a list of
    471 # two-element lists.  The first element of each is an option name, and
    472 # the second additional arguments to be added on to the end of the
    473 # option list as given in FILE.d.  (If omitted, no additional options
    474 # are added.)
    475 #
    476 # The interesting options are:
    477 #
    478 #   name: TEST-NAME
    479 #	The name of this test, passed to DejaGNU's `pass' and `fail'
    480 #       commands.  If omitted, this defaults to FILE, the root of the
    481 #       .s and .d files' names.
    482 #
    483 #   as: FLAGS
    484 #	When assembling, pass FLAGS to the assembler.
    485 #       If assembling several files, you can pass different assembler
    486 #       options in the "source" directives.  See below.
    487 #
    488 #   ld: FLAGS
    489 #       Link assembled files using FLAGS, in the order of the "source"
    490 #       directives, when using multiple files.
    491 #
    492 #   ld_after_inputfiles: FLAGS
    493 #       Similar to "ld", but put after all input files.
    494 #
    495 #   objcopy_objects: FLAGS
    496 #	Run objcopy with the specified flags after assembling any source
    497 #	that has the special marker RUN_OBJCOPY in the source specific
    498 #	flags.
    499 #
    500 #   objcopy_linked_file: FLAGS
    501 #	Run objcopy on the linked file with the specified flags.
    502 #	This lets you transform the linked file using objcopy, before the
    503 #	result is analyzed by an analyzer program specified below (which
    504 #	may in turn *also* be objcopy).
    505 #
    506 #   PROG: PROGRAM-NAME
    507 #       The name of the program to run to analyze the .o file produced
    508 #       by the assembler or the linker output.  This can be omitted;
    509 #       run_dump_test will guess which program to run by seeing which of
    510 #       the flags options below is present.
    511 #
    512 #   objdump: FLAGS
    513 #   nm: FLAGS
    514 #   objcopy: FLAGS
    515 #	Use the specified program to analyze the assembler or linker
    516 #       output file, and pass it FLAGS, in addition to the output name.
    517 #	Note that they are run with LC_ALL=C in the environment to give
    518 #	consistent sorting of symbols.
    519 #
    520 #   source: SOURCE [FLAGS]
    521 #	Assemble the file SOURCE.s using the flags in the "as" directive
    522 #       and the (optional) FLAGS.  If omitted, the source defaults to
    523 #       FILE.s.
    524 #       This is useful if several .d files want to share a .s file.
    525 #       More than one "source" directive can be given, which is useful
    526 #       when testing linking.
    527 #
    528 #   dump: DUMP
    529 #	Match against DUMP.d.  If omitted, this defaults to FILE.d.  This
    530 #	is useful if several .d files differ by options only.  Options are
    531 #	always read from FILE.d.
    532 #
    533 #   xfail: TARGET
    534 #       The test is expected to fail on TARGET.  This may occur more than
    535 #       once.
    536 #
    537 #   target: TARGET
    538 #       Only run the test for TARGET.  This may occur more than once; the
    539 #       target being tested must match at least one.  You may provide target
    540 #       name "cfi" for any target supporting the CFI statements.
    541 #
    542 #   notarget: TARGET
    543 #       Do not run the test for TARGET.  This may occur more than once;
    544 #       the target being tested must not match any of them.
    545 #
    546 #   error: REGEX
    547 #	An error with message matching REGEX must be emitted for the test
    548 #	to pass.  The PROG, objdump, nm and objcopy options have no
    549 #	meaning and need not supplied if this is present.  Multiple "error"
    550 #	directives append to the expected linker error message.
    551 #
    552 #   warning: REGEX
    553 #	Expect a linker warning matching REGEX.  It is an error to issue
    554 #	both "error" and "warning".  Multiple "warning" directives
    555 #	append to the expected linker warning message.
    556 #
    557 # Each option may occur at most once unless otherwise mentioned.
    558 #
    559 # After the option lines come regexp lines.  `run_dump_test' calls
    560 # `regexp_diff' to compare the output of the dumping tool against the
    561 # regexps in FILE.d.  `regexp_diff' is defined in binutils-common.exp;
    562 # see further comments there.
    563 #
    564 proc run_dump_test { name {extra_options {}} } {
    565     global subdir srcdir
    566     global OBJDUMP NM AS OBJCOPY READELF LD
    567     global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS LDFLAGS
    568     global host_triplet runtests
    569     global env verbose
    570 
    571     if [string match "*/*" $name] {
    572 	set file $name
    573 	set name [file tail $name]
    574     } else {
    575 	set file "$srcdir/$subdir/$name"
    576     }
    577 
    578     if ![runtest_file_p $runtests $name] then {
    579 	return
    580     }
    581 
    582     set opt_array [slurp_options "${file}.d"]
    583     if { $opt_array == -1 } {
    584 	perror "error reading options from $file.d"
    585 	unresolved $subdir/$name
    586 	return
    587     }
    588     set dumpfile tmpdir/dump.out
    589     set run_ld 0
    590     set run_objcopy 0
    591     set opts(as) {}
    592     set opts(ld) {}
    593     set opts(ld_after_inputfiles) {}
    594     set opts(xfail) {}
    595     set opts(target) {}
    596     set opts(notarget) {}
    597     set opts(objdump) {}
    598     set opts(nm) {}
    599     set opts(objcopy) {}
    600     set opts(readelf) {}
    601     set opts(name) {}
    602     set opts(PROG) {}
    603     set opts(source) {}
    604     set opts(dump) {}
    605     set opts(error) {}
    606     set opts(warning) {}
    607     set opts(objcopy_linked_file) {}
    608     set opts(objcopy_objects) {}
    609 
    610     foreach i $opt_array {
    611 	set opt_name [lindex $i 0]
    612 	set opt_val [lindex $i 1]
    613 	if ![info exists opts($opt_name)] {
    614 	    perror "unknown option $opt_name in file $file.d"
    615 	    unresolved $subdir/$name
    616 	    return
    617 	}
    618 
    619 	switch -- $opt_name {
    620 	    xfail {}
    621 	    target {}
    622 	    notarget {}
    623 	    warning {}
    624 	    error {}
    625 	    source {
    626 		# Move any source-specific as-flags to a separate list to
    627 		# simplify processing.
    628 		if { [llength $opt_val] > 1 } {
    629 		    lappend asflags [lrange $opt_val 1 end]
    630 		    set opt_val [lindex $opt_val 0]
    631 		} else {
    632 		    lappend asflags {}
    633 		}
    634 	    }
    635 	    default {
    636 		if [string length $opts($opt_name)] {
    637 		    perror "option $opt_name multiply set in $file.d"
    638 		    unresolved $subdir/$name
    639 		    return
    640 		}
    641 
    642 		# A single "# ld:" with no options should do the right thing.
    643 		if { $opt_name == "ld" } {
    644 		    set run_ld 1
    645 		}
    646 		# Likewise objcopy_linked_file.
    647 		if { $opt_name == "objcopy_linked_file" } {
    648 		    set run_objcopy 1
    649 		}
    650 	    }
    651 	}
    652 	if { $opt_name == "as" || $opt_name == "ld" } {
    653 	    set opt_val [subst $opt_val]
    654 	}
    655 
    656 	# Append differently whether it's a message (without space) or
    657 	# an option or list (with space).
    658 	switch -- $opt_name {
    659 	    warning -
    660 	    error {
    661 		append opts($opt_name) $opt_val
    662 	    }
    663 	    default {
    664 		set opts($opt_name) [concat $opts($opt_name) $opt_val]
    665 	    }
    666 	}
    667     }
    668 
    669     foreach i $extra_options {
    670 	set opt_name [lindex $i 0]
    671 	set opt_val [lindex $i 1]
    672 	if ![info exists opts($opt_name)] {
    673 	    perror "unknown option $opt_name given in extra_opts"
    674 	    unresolved $subdir/$name
    675 	    return
    676 	}
    677 	# Add extra option to end of existing option, adding space
    678 	# if necessary.
    679 	if { ![regexp "warning|error" $opt_name]
    680 	     && [string length $opts($opt_name)] } {
    681 	    append opts($opt_name) " "
    682 	}
    683 	append opts($opt_name) $opt_val
    684     }
    685 
    686     foreach opt { as ld } {
    687 	regsub {\[big_or_little_endian\]} $opts($opt) \
    688 	    [big_or_little_endian] opts($opt)
    689     }
    690 
    691     # Decide early whether we should run the test for this target.
    692     if { [llength $opts(target)] > 0 } {
    693 	set targmatch 0
    694 	foreach targ $opts(target) {
    695 	    if [istarget $targ] {
    696 		set targmatch 1
    697 		break
    698 	    }
    699 	}
    700 	if { $targmatch == 0 } {
    701 	    return
    702 	}
    703     }
    704     foreach targ $opts(notarget) {
    705 	if [istarget $targ] {
    706 	    return
    707 	}
    708     }
    709 
    710     set program ""
    711     # It's meaningless to require an output-testing method when we
    712     # expect an error.
    713     if { $opts(error) == "" } {
    714 	if {$opts(PROG) != ""} {
    715 	    switch -- $opts(PROG) {
    716 		objdump	{ set program objdump }
    717 		nm	{ set program nm }
    718 		objcopy	{ set program objcopy }
    719 		readelf	{ set program readelf }
    720 		default
    721 		{ perror "unrecognized program option $opts(PROG) in $file.d"
    722 		  unresolved $subdir/$name
    723 		  return }
    724 	    }
    725 	} else {
    726 	# Guess which program to run, by seeing which option was specified.
    727 	    foreach p {objdump objcopy nm readelf} {
    728 		if {$opts($p) != ""} {
    729 		    if {$program != ""} {
    730 			perror "ambiguous dump program in $file.d"
    731 			unresolved $subdir/$name
    732 			return
    733 		    } else {
    734 			set program $p
    735 		    }
    736 		}
    737 	    }
    738 	}
    739 	if { $program == "" && $opts(warning) == "" } {
    740 	    perror "dump program unspecified in $file.d"
    741 	    unresolved $subdir/$name
    742 	    return
    743 	}
    744     }
    745 
    746     if { $opts(name) == "" } {
    747 	set testname "$subdir/$name"
    748     } else {
    749 	set testname $opts(name)
    750     }
    751 
    752     if { $opts(source) == "" } {
    753 	set sourcefiles [list ${file}.s]
    754 	set asflags [list ""]
    755     } else {
    756 	set sourcefiles {}
    757 	foreach sf $opts(source) {
    758 	    if { [string match "/*" $sf] } {
    759 		lappend sourcefiles "$sf"
    760 	    } else {
    761 		lappend sourcefiles "$srcdir/$subdir/$sf"
    762 	    }
    763 	}
    764     }
    765 
    766     if { $opts(dump) == "" } {
    767 	set dfile ${file}.d
    768     } else {
    769 	set dfile $srcdir/$subdir/$opts(dump)
    770     }
    771 
    772     if { [string match "*--compress-debug-sections*" $opts(as)] \
    773 	 && ![is_zlib_supported] } {
    774 	unsupported $testname
    775 	return
    776     }
    777 
    778     # Time to setup xfailures.
    779     foreach targ $opts(xfail) {
    780 	setup_xfail $targ
    781     }
    782 
    783     # Assemble each file.
    784     set objfiles {}
    785     for { set i 0 } { $i < [llength $sourcefiles] } { incr i } {
    786 	set sourcefile [lindex $sourcefiles $i]
    787 	set sourceasflags [lindex $asflags $i]
    788 	set run_objcopy_objects 0
    789 
    790 	if { [string match "*RUN_OBJCOPY*" $sourceasflags] } {
    791 	    set run_objcopy_objects 1
    792 	}
    793 	regsub "RUN_OBJCOPY" $sourceasflags "" sourceasflags
    794 
    795 	set objfile "tmpdir/dump$i.o"
    796 	catch "exec rm -f $objfile" exec_output
    797 	lappend objfiles $objfile
    798 	set cmd "$AS $ASFLAGS $opts(as) $sourceasflags -o $objfile $sourcefile"
    799 
    800 	send_log "$cmd\n"
    801 	set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
    802 	remote_upload host "ld.tmp"
    803 	set comp_output [prune_warnings [file_contents "ld.tmp"]]
    804 	remote_file host delete "ld.tmp"
    805 	remote_file build delete "ld.tmp"
    806 
    807 	if { [lindex $cmdret 0] != 0 || ![string match "" $comp_output] } then {
    808 	    send_log "$comp_output\n"
    809 	    verbose "$comp_output" 3
    810 
    811 	    set exitstat "succeeded"
    812 	    if { $cmdret != 0 } { set exitstat "failed" }
    813 	    verbose -log "$exitstat with: <$comp_output>"
    814 	    fail $testname
    815 	    return
    816 	}
    817 
    818 	if { $run_objcopy_objects } {
    819 	    set cmd "$OBJCOPY $opts(objcopy_objects) $objfile"
    820 
    821 	    send_log "$cmd\n"
    822 	    set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] \
    823 			"" "/dev/null" "objcopy.tmp"]
    824 	    remote_upload host "objcopy.tmp"
    825 	    set comp_output [prune_warnings [file_contents "objcopy.tmp"]]
    826 	    remote_file host delete "objcopy.tmp"
    827 	    remote_file build delete "objcopy.tmp"
    828 
    829 	    if { [lindex $cmdret 0] != 0 \
    830 		  || ![string match "" $comp_output] } {
    831 		send_log "$comp_output\n"
    832 		verbose "$comp_output" 3
    833 
    834 		set exitstat "succeeded"
    835 		if { $cmdret != 0 } { set exitstat "failed" }
    836 		verbose -log "$exitstat with: <$comp_output>"
    837 		fail $testname
    838 		return
    839 	    }
    840 	}
    841     }
    842 
    843     set expmsg $opts(error)
    844     if { $opts(warning) != "" } {
    845 	if { $expmsg != "" } {
    846 	    perror "$testname: mixing error and warning test-directives"
    847 	    return
    848 	}
    849 	set expmsg $opts(warning)
    850     }
    851 
    852     # Perhaps link the file(s).
    853     if { $run_ld } {
    854 	set objfile "tmpdir/dump"
    855 	catch "exec rm -f $objfile" exec_output
    856 
    857 	# Add -L$srcdir/$subdir so that the linker command can use
    858 	# linker scripts in the source directory.
    859 	set cmd "$LD $LDFLAGS -L$srcdir/$subdir \
    860 		   $opts(ld) -o $objfile $objfiles $opts(ld_after_inputfiles)"
    861 
    862 	send_log "$cmd\n"
    863 	set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
    864 	remote_upload host "ld.tmp"
    865 	set comp_output [file_contents "ld.tmp"]
    866 	remote_file host delete "ld.tmp"
    867 	remote_file build delete "ld.tmp"
    868 	set cmdret [lindex $cmdret 0]
    869 
    870 	if { $cmdret == 0 && $run_objcopy } {
    871 	    set infile $objfile
    872 	    set objfile "tmpdir/dump1"
    873 	    remote_file host delete $objfile
    874 
    875 	    # Note that we don't use OBJCOPYFLAGS here; any flags must be
    876 	    # explicitly specified.
    877 	    set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile"
    878 
    879 	    send_log "$cmd\n"
    880 	    set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
    881 	    remote_upload host "ld.tmp"
    882 	    append comp_output [file_contents "ld.tmp"]
    883 	    remote_file host delete "ld.tmp"
    884 	    remote_file build delete "ld.tmp"
    885 	    set cmdret [lindex $cmdret 0]
    886 	}
    887 
    888 	regsub "\n$" $comp_output "" comp_output
    889 	if { $cmdret != 0 || $comp_output != "" || $expmsg != "" } then {
    890 	    set exitstat "succeeded"
    891 	    if { $cmdret != 0 } { set exitstat "failed" }
    892 	    verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>"
    893 	    send_log "$comp_output\n"
    894 	    verbose "$comp_output" 3
    895 
    896 	    if { ($expmsg == "") == ($comp_output == "") \
    897 		    && [regexp $expmsg $comp_output] \
    898 		    && (($cmdret == 0) == ($opts(error) == "")) } {
    899 		# We have the expected output from ld.
    900 		if { $opts(error) != "" || $program == "" } {
    901 		    pass $testname
    902 		    return
    903 		}
    904 	    } else {
    905 		verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>"
    906 		fail $testname
    907 		return
    908 	    }
    909 	}
    910     } else {
    911 	set objfile "tmpdir/dump0.o"
    912     }
    913 
    914     # We must not have expected failure if we get here.
    915     if { $opts(error) != "" } {
    916 	fail $testname
    917 	return
    918     }
    919 
    920     set progopts1 $opts($program)
    921     eval set progopts \$[string toupper $program]FLAGS
    922     eval set binary \$[string toupper $program]
    923 
    924     if { ![is_remote host] && [which $binary] == 0 } {
    925 	untested $testname
    926 	return
    927     }
    928 
    929     if { $progopts1 == "" } { set $progopts1 "-r" }
    930     verbose "running $binary $progopts $progopts1" 3
    931 
    932     # Objcopy, unlike the other two, won't send its output to stdout,
    933     # so we have to run it specially.
    934     set cmd "$binary $progopts $progopts1 $objfile > $dumpfile"
    935     if { $program == "objcopy" } {
    936 	set cmd "$binary $progopts $progopts1 $objfile $dumpfile"
    937     }
    938 
    939     # Ensure consistent sorting of symbols
    940     if {[info exists env(LC_ALL)]} {
    941 	set old_lc_all $env(LC_ALL)
    942     }
    943     set env(LC_ALL) "C"
    944     send_log "$cmd\n"
    945     set cmdret [remote_exec host [concat sh -c [list "$cmd 2>ld.tmp"]] "" "/dev/null"]
    946     set cmdret [lindex $cmdret 0]
    947     remote_upload host "ld.tmp"
    948     set comp_output [prune_warnings [file_contents "ld.tmp"]]
    949     remote_file host delete "ld.tmp"
    950     remote_file build delete "ld.tmp"
    951     if {[info exists old_lc_all]} {
    952 	set env(LC_ALL) $old_lc_all
    953     } else {
    954 	unset env(LC_ALL)
    955     }
    956     if { $cmdret != 0 || $comp_output != "" } {
    957 	send_log "exited abnormally with $cmdret, output:$comp_output\n"
    958 	fail $testname
    959 	return
    960     }
    961 
    962     if { $verbose > 2 } then { verbose "output is [file_contents $dumpfile]" 3 }
    963     if { [regexp_diff $dumpfile "${dfile}"] } then {
    964 	fail $testname
    965 	if { $verbose == 2 } then { verbose "output is [file_contents $dumpfile]" 2 }
    966 	return
    967     }
    968 
    969     pass $testname
    970 }
    971 
    972 proc slurp_options { file } {
    973     # If options_regsub(foo) is set to {a b}, then the contents of a
    974     # "#foo:" line will have regsub -all applied to replace a with b.
    975     global options_regsub
    976 
    977     if [catch { set f [open $file r] } x] {
    978 	#perror "couldn't open `$file': $x"
    979 	perror "$x"
    980 	return -1
    981     }
    982     set opt_array {}
    983     # whitespace expression
    984     set ws  {[ 	]*}
    985     set nws {[^ 	]*}
    986     # whitespace is ignored anywhere except within the options list;
    987     # option names are alphabetic plus underscore only.
    988     set pat "^#${ws}(\[a-zA-Z_\]*)$ws:${ws}(.*)$ws\$"
    989     while { [gets $f line] != -1 } {
    990 	set line [string trim $line]
    991 	# Whitespace here is space-tab.
    992 	if [regexp $pat $line xxx opt_name opt_val] {
    993 	    # match!
    994 	    if [info exists options_regsub($opt_name)] {
    995 		set subst $options_regsub($opt_name)
    996 		regsub -all -- [lindex $subst 0] $opt_val [lindex $subst 1] \
    997 		    opt_val
    998 	    }
    999 	    lappend opt_array [list $opt_name $opt_val]
   1000 	} else {
   1001 	    break
   1002 	}
   1003     }
   1004     close $f
   1005     return $opt_array
   1006 }
   1007 
   1008 proc file_contents { filename } {
   1009     set file [open $filename r]
   1010     set contents [read $file]
   1011     close $file
   1012     return $contents
   1013 }
   1014 
   1015 proc set_file_contents { filename contents } {
   1016     set file [open $filename w]
   1017     puts $file "$contents"
   1018     close $file
   1019 }
   1020 
   1021 # Create an archive using ar
   1022 #
   1023 proc ar_simple_create { ar aropts target objects } {
   1024     remote_file host delete $target
   1025 
   1026     set exec_output [run_host_cmd "$ar" "$aropts -rc $target $objects"]
   1027     set exec_output [prune_warnings $exec_output]
   1028 
   1029     if [string match "" $exec_output] then {
   1030 	send_log "$exec_output\n"
   1031 	return 1
   1032     } else {
   1033 	return 0
   1034     }
   1035 }
   1036 
   1037 # List contains test-items with 3 items followed by 2 lists, one item and
   1038 # one optional item:
   1039 #  0:name
   1040 #  1:ld/ar leading options, placed before object files
   1041 #  2:ld/ar trailing options, placed after object files
   1042 #  3:assembler options
   1043 #  4:filenames of assembler files
   1044 #  5:list of actions, options and expected outputs.
   1045 #  6:name of output file
   1046 #  7:compiler flags (optional)
   1047 #
   1048 # Actions: { command command-line-options file-containg-expected-output-regexps }
   1049 # Commands:
   1050 #   objdump: Apply objdump options on result.
   1051 #   nm: Apply nm options on result.
   1052 #   readelf: Apply readelf options on result.
   1053 #   ld: Don't apply anything on result.  Compare output during linking with
   1054 #     the file containing regexps (which is the second arg, not the third).
   1055 #     Note that this *must* be the first action if it is to be used at all;
   1056 #     in all other cases, any output from the linker during linking is
   1057 #     treated as a sign of an error and FAILs the test.
   1058 #
   1059 proc run_ld_link_tests { ldtests } {
   1060     global ld
   1061     global as
   1062     global nm
   1063     global ar
   1064     global objdump
   1065     global READELF
   1066     global srcdir
   1067     global subdir
   1068     global env
   1069     global CC
   1070     global CFLAGS
   1071     global runtests
   1072     global exec_output
   1073 
   1074     foreach testitem $ldtests {
   1075 	set testname [lindex $testitem 0]
   1076 
   1077 	if ![runtest_file_p $runtests $testname] then {
   1078 	    continue
   1079 	}
   1080 
   1081 	set ld_options [lindex $testitem 1]
   1082 	set ld_after [lindex $testitem 2]
   1083 	set as_options [lindex $testitem 3]
   1084 	set src_files  [lindex $testitem 4]
   1085 	set actions [lindex $testitem 5]
   1086 	set binfile tmpdir/[lindex $testitem 6]
   1087 	set cflags [lindex $testitem 7]
   1088 	set objfiles {}
   1089 	set is_unresolved 0
   1090 	set failed 0
   1091 	set maybe_failed 0
   1092 	set ld_output ""
   1093 
   1094 #	verbose -log "Testname is $testname"
   1095 #	verbose -log "ld_options is $ld_options"
   1096 #	verbose -log "ld_after is $ld_after"
   1097 #	verbose -log "as_options is $as_options"
   1098 #	verbose -log "src_files is $src_files"
   1099 #	verbose -log "actions is $actions"
   1100 #	verbose -log "binfile is $binfile"
   1101 
   1102 	# Assemble each file in the test.
   1103 	foreach src_file $src_files {
   1104 	    set fileroot "[file rootname [file tail $src_file]]"
   1105 	    set objfile "tmpdir/$fileroot.o"
   1106 	    lappend objfiles $objfile
   1107 
   1108 	    if { [file extension $src_file] == ".c" } {
   1109 		set as_file "tmpdir/$fileroot.s"
   1110 		if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
   1111 		    set is_unresolved 1
   1112 		    break
   1113 		}
   1114 	    } else {
   1115 		set as_file "$srcdir/$subdir/$src_file"
   1116 	    }
   1117 	    if ![ld_assemble $as "$as_options $as_file" $objfile] {
   1118 		set is_unresolved 1
   1119 		break
   1120 	    }
   1121 	}
   1122 
   1123 	# Catch assembler errors.
   1124 	if { $is_unresolved } {
   1125 	    unresolved $testname
   1126 	    continue
   1127 	}
   1128 
   1129 	if { $binfile eq "tmpdir/" } {
   1130 	    # compile only
   1131 	} elseif { [regexp ".*\\.a$" $binfile] } {
   1132 	    if { ![ar_simple_create $ar $ld_options $binfile "$objfiles $ld_after"] } {
   1133 		set failed 1
   1134 	    }
   1135 	} elseif { ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles $ld_after"] } {
   1136 	    set maybe_failed 1
   1137 	    set ld_output "$exec_output"
   1138 	}
   1139 
   1140 	if { !$failed } {
   1141 	    foreach actionlist $actions {
   1142 		set action [lindex $actionlist 0]
   1143 		set progopts [lindex $actionlist 1]
   1144 
   1145 		# There are actions where we run regexp_diff on the
   1146 		# output, and there are other actions (presumably).
   1147 		# Handling of the former look the same.
   1148 		set dump_prog ""
   1149 		switch -- $action {
   1150 		    objdump
   1151 		        { set dump_prog $objdump }
   1152 		    nm
   1153 		        { set dump_prog $nm }
   1154 		    readelf
   1155 		        { set dump_prog $READELF }
   1156 		    ld
   1157 		        { set dump_prog "ld" }
   1158 		    default
   1159 			{
   1160 			    perror "Unrecognized action $action"
   1161 			    set is_unresolved 1
   1162 			    break
   1163 			}
   1164 		    }
   1165 
   1166 		if { $action == "ld" } {
   1167 		    set regexpfile $progopts
   1168 		    verbose "regexpfile is $srcdir/$subdir/$regexpfile"
   1169 		    set_file_contents "tmpdir/ld.messages" "$ld_output"
   1170 		    verbose "ld.messages has '[file_contents tmpdir/ld.messages]'"
   1171 		    if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$regexpfile"] } then {
   1172 			verbose "output is $ld_output" 2
   1173 			set failed 1
   1174 			break
   1175 		    }
   1176 		    set maybe_failed 0
   1177 		} elseif { !$maybe_failed && $dump_prog != "" } {
   1178 		    set dumpfile [lindex $actionlist 2]
   1179 		    set binary $dump_prog
   1180 
   1181 		    # Ensure consistent sorting of symbols
   1182 		    if {[info exists env(LC_ALL)]} {
   1183 			set old_lc_all $env(LC_ALL)
   1184 		    }
   1185 		    set env(LC_ALL) "C"
   1186 		    set cmd "$binary $progopts $binfile"
   1187     		    set status [remote_exec host [concat sh -c [list "$cmd >dump.out 2>ld.stderr"]] "" "/dev/null"]
   1188 		    send_log "$cmd\n"
   1189     		    remote_upload host "ld.stderr"
   1190     		    set comp_output [prune_warnings [file_contents "ld.stderr"]]
   1191     		    remote_file host delete "ld.stderr"
   1192     		    remote_file build delete "ld.stderr"
   1193 
   1194 		    if {[info exists old_lc_all]} {
   1195 			set env(LC_ALL) $old_lc_all
   1196 		    } else {
   1197 			unset env(LC_ALL)
   1198 		    }
   1199 
   1200 		    if ![string match "" $comp_output] then {
   1201 			send_log "$comp_output\n"
   1202 			set failed 1
   1203 			break
   1204 		    }
   1205 
   1206 		    remote_upload host "dump.out"
   1207 
   1208 		    if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
   1209 			verbose "output is [file_contents "dump.out"]" 2
   1210 			set failed 1
   1211 		   	remote_file build delete "dump.out"
   1212 		   	remote_file host delete "dump.out"
   1213 			break
   1214 		    }
   1215 		    remote_file build delete "dump.out"
   1216 		    remote_file host delete "dump.out"
   1217 		}
   1218 	    }
   1219 	}
   1220 
   1221 	if { $is_unresolved } {
   1222 	    unresolved $testname
   1223 	} elseif { $maybe_failed || $failed } {
   1224 	    fail $testname
   1225 	} else {
   1226 	    pass $testname
   1227 	}
   1228     }
   1229 }
   1230 
   1231 # This definition is taken from an unreleased version of DejaGnu.  Once
   1232 # that version gets released, and has been out in the world for a few
   1233 # months at least, it may be safe to delete this copy.
   1234 if ![string length [info proc prune_warnings]] {
   1235     #
   1236     # prune_warnings -- delete various system verbosities from TEXT
   1237     #
   1238     # An example is:
   1239     # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
   1240     #
   1241     # Sites with particular verbose os's may wish to override this in site.exp.
   1242     #
   1243     proc prune_warnings { text } {
   1244 	# This is from sun4's.  Do it for all machines for now.
   1245 	# The "\\1" is to try to preserve a "\n" but only if necessary.
   1246 	regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
   1247 
   1248 	# It might be tempting to get carried away and delete blank lines, etc.
   1249 	# Just delete *exactly* what we're ask to, and that's it.
   1250 	return $text
   1251     }
   1252 }
   1253 
   1254 # targets_to_xfail is a list of target triplets to be xfailed.
   1255 # ldtests contains test-items with 3 items followed by 1 lists, 2 items
   1256 # and 3 optional items:
   1257 #   0:name
   1258 #   1:ld options
   1259 #   2:assembler options
   1260 #   3:filenames of source files
   1261 #   4:name of output file
   1262 #   5:expected output
   1263 #   6:compiler flags (optional)
   1264 #   7:language (optional)
   1265 #   8:linker warning (optional)
   1266 
   1267 proc run_ld_link_exec_tests { targets_to_xfail ldtests } {
   1268     global ld
   1269     global as
   1270     global srcdir
   1271     global subdir
   1272     global env
   1273     global CC
   1274     global CXX
   1275     global CFLAGS
   1276     global CXXFLAGS
   1277     global errcnt
   1278     global exec_output
   1279 
   1280     foreach testitem $ldtests {
   1281 	foreach target $targets_to_xfail {
   1282 	    setup_xfail $target
   1283 	}
   1284 	set testname [lindex $testitem 0]
   1285 	set ld_options [lindex $testitem 1]
   1286 	set as_options [lindex $testitem 2]
   1287 	set src_files  [lindex $testitem 3]
   1288 	set binfile tmpdir/[lindex $testitem 4]
   1289 	set expfile [lindex $testitem 5]
   1290 	set cflags [lindex $testitem 6]
   1291 	set lang [lindex $testitem 7]
   1292 	set warning [lindex $testitem 8]
   1293 	set objfiles {}
   1294 	set failed 0
   1295 
   1296 #	verbose -log "Testname is $testname"
   1297 #	verbose -log "ld_options is $ld_options"
   1298 #	verbose -log "as_options is $as_options"
   1299 #	verbose -log "src_files is $src_files"
   1300 #	verbose -log "binfile is $binfile"
   1301 
   1302 	# Assemble each file in the test.
   1303 	foreach src_file $src_files {
   1304 	    set fileroot "[file rootname [file tail $src_file]]"
   1305 	    set objfile "tmpdir/$fileroot.o"
   1306 	    lappend objfiles $objfile
   1307 
   1308 	    # We ignore warnings since some compilers may generate
   1309 	    # incorrect section attributes and the assembler will warn
   1310 	    # them.
   1311 	    if { [ string match "c++" $lang ] } {
   1312 		ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
   1313 	    } else {
   1314 		ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
   1315 	    }
   1316 	}
   1317 
   1318 	# We have to use $CC to build PIE and shared library.
   1319 	if { [ string match "c" $lang ] } {
   1320 	    set link_proc ld_simple_link
   1321 	    set link_cmd $CC
   1322 	} elseif { [ string match "c++" $lang ] } {
   1323 	    set link_proc ld_simple_link
   1324 	    set link_cmd $CXX
   1325 	} elseif { [ string match "-shared" $ld_options ] \
   1326 		   || [ string match "-pie" $ld_options ] } {
   1327 	    set link_proc ld_simple_link
   1328 	    set link_cmd $CC
   1329 	} else {
   1330 	    set link_proc ld_link
   1331 	    set link_cmd $ld
   1332 	}
   1333 
   1334 	if { $binfile eq "tmpdir/" } {
   1335 	    # compile only
   1336 	    pass $testname
   1337 	    continue;
   1338 	} elseif ![$link_proc $link_cmd $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
   1339 	    set failed 1
   1340 	}
   1341 
   1342 	# Check if exec_output is expected.
   1343 	if { $warning != "" } then {
   1344 	    verbose -log "returned with: <$exec_output>, expected: <$warning>"
   1345 	    if { [regexp $warning $exec_output] } then {
   1346 		set failed 0
   1347 	    } else {
   1348 		set failed 1
   1349 	    }
   1350 	}
   1351 
   1352 	if { $failed == 0 } {
   1353 	    send_log "Running: $binfile > $binfile.out\n"
   1354 	    verbose "Running: $binfile > $binfile.out"
   1355 	    catch "exec $binfile > $binfile.out" exec_output
   1356 
   1357 	    if ![string match "" $exec_output] then {
   1358 		send_log "$exec_output\n"
   1359 		verbose "$exec_output" 1
   1360 		set failed 1
   1361 	    } else {
   1362 		send_log "diff $binfile.out $srcdir/$subdir/$expfile\n"
   1363 		verbose "diff $binfile.out $srcdir/$subdir/$expfile"
   1364 		catch "exec diff $binfile.out $srcdir/$subdir/$expfile" exec_output
   1365 		set exec_output [prune_warnings $exec_output]
   1366 
   1367 		if ![string match "" $exec_output] then {
   1368 		    send_log "$exec_output\n"
   1369 		    verbose "$exec_output" 1
   1370 		    set failed 1
   1371 		}
   1372 	    }
   1373 	}
   1374 
   1375 	if { $failed != 0 } {
   1376 	    fail $testname
   1377 	} else {
   1378 	    set errcnt 0
   1379 	    pass $testname
   1380 	}
   1381     }
   1382 }
   1383 
   1384 # List contains test-items with 3 items followed by 2 lists, one item and
   1385 # one optional item:
   1386 #  0:name
   1387 #  1:ld or ar options
   1388 #  2:compile options
   1389 #  3:filenames of source files
   1390 #  4:action and options.
   1391 #  5:name of output file
   1392 #  6:language (optional)
   1393 #  7:linker warnings (optional)
   1394 #
   1395 # Actions:
   1396 # objdump: Apply objdump options on result.  Compare with regex (last arg).
   1397 # nm: Apply nm options on result.  Compare with regex (last arg).
   1398 # readelf: Apply readelf options on result.  Compare with regex (last arg).
   1399 #
   1400 proc run_cc_link_tests { ldtests } {
   1401     global nm
   1402     global objdump
   1403     global READELF
   1404     global srcdir
   1405     global subdir
   1406     global env
   1407     global CC
   1408     global CXX
   1409     global CFLAGS
   1410     global CXXFLAGS
   1411     global ar
   1412     global exec_output
   1413     global board_cflags
   1414 
   1415     if [board_info [target_info name] exists cflags] {
   1416         set board_cflags " [board_info [target_info name] cflags]"
   1417     } else {
   1418 	set board_cflags ""
   1419     }
   1420 
   1421     foreach testitem $ldtests {
   1422 	set testname [lindex $testitem 0]
   1423 	set ldflags [lindex $testitem 1]
   1424 	set cflags [lindex $testitem 2]
   1425 	set src_files  [lindex $testitem 3]
   1426 	set actions [lindex $testitem 4]
   1427 	set binfile tmpdir/[lindex $testitem 5]
   1428 	set lang [lindex $testitem 6]
   1429 	set warnings [lindex $testitem 7]
   1430 	set objfiles {}
   1431 	set is_unresolved 0
   1432 	set failed 0
   1433 
   1434 	#verbose -log "testname  is $testname"
   1435 	#verbose -log "ldflags   is $ldflags"
   1436 	#verbose -log "cflags    is $cflags"
   1437 	#verbose -log "src_files is $src_files"
   1438 	#verbose -log "actions   is $actions"
   1439 	#verbose -log "binfile   is $binfile"
   1440 	#verbose -log "lang      is $lang"
   1441 	#verbose -log "warnings  is $warnings"
   1442 
   1443 	# Compile each file in the test.
   1444 	foreach src_file $src_files {
   1445 	    set fileroot "[file rootname [file tail $src_file]]"
   1446 	    set objfile "tmpdir/$fileroot.o"
   1447 	    lappend objfiles $objfile
   1448 
   1449 	    # We ignore warnings since some compilers may generate
   1450 	    # incorrect section attributes and the assembler will warn
   1451 	    # them.
   1452 	    if { [ string match "c++" $lang ] } {
   1453 		ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
   1454 	    } else {
   1455 		ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
   1456 	    }
   1457 	}
   1458 
   1459 	# Clear error and warning counts.
   1460 	reset_vars
   1461 
   1462 	if { [ string match "c++" $lang ] } {
   1463 	    set cc_cmd $CXX
   1464 	} else {
   1465 	    set cc_cmd $CC
   1466 	}
   1467 
   1468 	if { $binfile eq "tmpdir/" } {
   1469 	    # compile only
   1470 	} elseif { [regexp ".*\\.a$" $binfile] } {
   1471 	    if { ![ar_simple_create $ar $ldflags $binfile "$objfiles"] } {
   1472 		fail $testname
   1473 		set failed 1
   1474 	    }
   1475 	} else {
   1476 	    if { ![ld_simple_link $cc_cmd $binfile "$board_cflags -L$srcdir/$subdir $ldflags $objfiles"] } {
   1477 		set failed 1
   1478 	    }
   1479 
   1480 	    # Check if exec_output is expected.
   1481 	    if { $warnings != "" } then {
   1482 		verbose -log "returned with: <$exec_output>, expected: <$warnings>"
   1483 		if { [regexp $warnings $exec_output] } then {
   1484 		    set failed 0
   1485 		} else {
   1486 		    set failed 1
   1487 		}
   1488 	    }
   1489 
   1490 	    if { $failed == 1 } {
   1491 		fail $testname
   1492 	    }
   1493 	}
   1494 
   1495 	if { $failed == 0 } {
   1496 	    foreach actionlist $actions {
   1497 		set action [lindex $actionlist 0]
   1498 		set progopts [lindex $actionlist 1]
   1499 
   1500 		# There are actions where we run regexp_diff on the
   1501 		# output, and there are other actions (presumably).
   1502 		# Handling of the former look the same.
   1503 		set dump_prog ""
   1504 		switch -- $action {
   1505 		    objdump
   1506 		        { set dump_prog $objdump }
   1507 		    nm
   1508 		        { set dump_prog $nm }
   1509 		    readelf
   1510 		        { set dump_prog $READELF }
   1511 		    default
   1512 			{
   1513 			    perror "Unrecognized action $action"
   1514 			    set is_unresolved 1
   1515 			    break
   1516 			}
   1517 		    }
   1518 
   1519 		if { $dump_prog != "" } {
   1520 		    set dumpfile [lindex $actionlist 2]
   1521 		    set binary $dump_prog
   1522 
   1523 		    # Ensure consistent sorting of symbols
   1524 		    if {[info exists env(LC_ALL)]} {
   1525 			set old_lc_all $env(LC_ALL)
   1526 		    }
   1527 		    set env(LC_ALL) "C"
   1528 		    set cmd "$binary $progopts $binfile > dump.out"
   1529 		    send_log "$cmd\n"
   1530 		    catch "exec $cmd" comp_output
   1531 		    if {[info exists old_lc_all]} {
   1532 			set env(LC_ALL) $old_lc_all
   1533 		    } else {
   1534 			unset env(LC_ALL)
   1535 		    }
   1536 		    set comp_output [prune_warnings $comp_output]
   1537 
   1538 		    if ![string match "" $comp_output] then {
   1539 			send_log "$comp_output\n"
   1540 			set failed 1
   1541 			break
   1542 		    }
   1543 
   1544 		    if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
   1545 			verbose "output is [file_contents "dump.out"]" 2
   1546 			set failed 1
   1547 			break
   1548 		    }
   1549 		}
   1550 	    }
   1551 	}
   1552 
   1553 	if { $failed != 0 } {
   1554 	    fail $testname
   1555 	} elseif { $is_unresolved == 0 } {
   1556 	    pass $testname
   1557 	} else {
   1558 	    unresolved $testname
   1559 	    continue
   1560 	}
   1561     }
   1562 }
   1563 
   1564 # Returns true if --gc-sections is supported on the target.
   1565 
   1566 proc check_gc_sections_available { } {
   1567     global gc_sections_available_saved
   1568     global ld
   1569 
   1570     if {![info exists gc_sections_available_saved]} {
   1571 	# Some targets don't support gc-sections despite whatever's
   1572 	# advertised by ld's options.
   1573 	if {   [istarget arc-*-*]
   1574 	    || [istarget d30v-*-*]
   1575 	    || [istarget dlx-*-*]
   1576 	    || [istarget i960-*-*]
   1577 	    || [istarget pj*-*-*]
   1578 	    || [istarget alpha-*-*]
   1579 	    || [istarget hppa*64-*-*]
   1580 	    || [istarget i370-*-*]
   1581 	    || [istarget i860-*-*]
   1582 	    || [istarget ia64-*-*]
   1583 	    || [istarget mep-*-*]
   1584 	    || [istarget mn10200-*-*]
   1585 	    || [istarget *-*-cygwin]
   1586 	    || [istarget *-*-mingw*] } {
   1587 	    set gc_sections_available_saved 0
   1588 	    return 0
   1589 	}
   1590 
   1591 	# elf2flt uses -q (--emit-relocs), which is incompatible with
   1592 	# --gc-sections.
   1593 	if { [board_info target exists ldflags]
   1594 	     && [regexp " -elf2flt\[ =\]" " [board_info target ldflags] "] } {
   1595 	    set gc_sections_available_saved 0
   1596 	    return 0
   1597 	}
   1598 
   1599 	# Check if the ld used by gcc supports --gc-sections.
   1600 	# FIXME: this test is useless since ld --help always says
   1601 	# --gc-sections is available
   1602 	set ld_output [remote_exec host $ld "--help"]
   1603 	if { [ string first "--gc-sections" $ld_output ] >= 0 } {
   1604 	    set gc_sections_available_saved 1
   1605 	} else {
   1606 	    set gc_sections_available_saved 0
   1607 	}
   1608     }
   1609     return $gc_sections_available_saved
   1610 }
   1611 
   1612 # Returns true if -shared is supported on the target
   1613 # Only used and accurate for ELF targets at the moment
   1614 
   1615 proc check_shared_lib_support { } {
   1616     if {![istarget aarch64*-*-elf]
   1617 	 && ![istarget arc-*-*]
   1618 	 && ![istarget arm*-*-elf]
   1619 	 && ![istarget avr-*-*]
   1620 	 && ![istarget cr16-*-*]
   1621 	 && ![istarget cris*-*-elf]
   1622 	 && ![istarget crx-*-*]
   1623 	 && ![istarget d10v-*-*]
   1624 	 && ![istarget d30v-*-*]
   1625 	 && ![istarget dlx-*-*]
   1626 	 && ![istarget epiphany-*-*]
   1627 	 && ![istarget fr30-*-*]
   1628 	 && ![istarget frv-*-*]
   1629 	 && ![istarget h8300-*-*]
   1630 	 && ![istarget i860-*-*]
   1631 	 && ![istarget i960-*-*]
   1632 	 && ![istarget ip2k-*-*]
   1633 	 && ![istarget iq2000-*-*]
   1634 	 && ![istarget lm32-*-*]
   1635 	 && ![istarget m32c-*-*]
   1636 	 && ![istarget m32r-*-*]
   1637 	 && ![istarget m6811-*-*]
   1638 	 && ![istarget m6812-*-*]
   1639 	 && ![istarget m68hc1*-*-*]
   1640 	 && ![istarget mcore*-*-*]
   1641 	 && ![istarget mep-*-*]
   1642 	 && ![istarget microblaze-*-*]
   1643 	 && ![istarget mips*-*-elf]
   1644 	 && ![istarget mn10200-*-*]
   1645 	 && ![istarget moxie-*-*]
   1646 	 && ![istarget msp430-*-*]
   1647 	 && ![istarget mt-*-*]
   1648 	 && ![istarget nds32*-*-*]
   1649 	 && ![istarget or1k*-*-*]
   1650 	 && ![istarget pj-*-*]
   1651 	 && ![istarget rl78-*-*]
   1652 	 && ![istarget rx-*-*]
   1653 	 && ![istarget spu-*-*]
   1654 	 && ![istarget v850*-*-*]
   1655 	 && ![istarget xstormy16-*-*]
   1656 	 && ![istarget *-*-irix*]
   1657 	 && ![istarget *-*-rtems] } {
   1658 	return 1
   1659     }
   1660     return 0
   1661 }
   1662 
   1663 # Returns true if the target ld supports the plugin API.
   1664 proc check_plugin_api_available { } {
   1665     global plugin_api_available_saved
   1666     global ld
   1667     if {![info exists plugin_api_available_saved]} {
   1668 	# Check if the ld used by gcc supports --plugin.
   1669 	set ld_output [remote_exec host $ld "--help"]
   1670 	if { [ string first "-plugin PLUGIN" $ld_output ] >= 0 } {
   1671 	    set plugin_api_available_saved 1
   1672 	} else {
   1673 	    set plugin_api_available_saved 0
   1674 	}
   1675     }
   1676     return $plugin_api_available_saved
   1677 }
   1678 
   1679 # Sets ld_sysroot to the current sysroot (empty if not supported) and
   1680 # returns true if the target ld supports sysroot.
   1681 proc check_sysroot_available { } {
   1682     global ld_sysroot_available_saved ld ld_sysroot
   1683     if {![info exists ld_sysroot_available_saved]} {
   1684 	# Check if ld supports --sysroot *other* than empty.
   1685 	set ld_sysroot [string trimright [lindex [remote_exec host $ld "--print-sysroot"] 1]]
   1686 	if { $ld_sysroot == "" } {
   1687 	    set ld_sysroot_available_saved 0
   1688 	} else {
   1689 	    set ld_sysroot_available_saved 1
   1690 	}
   1691     }
   1692     return $ld_sysroot_available_saved
   1693 }
   1694 
   1695 # Returns true if the target compiler supports LTO
   1696 proc check_lto_available { } {
   1697     global lto_available_saved
   1698     global CC
   1699 
   1700     if {![info exists lto_available_saved]} {
   1701         if { [which $CC] == 0 } {
   1702 	    set lto_available_saved 0
   1703 	    return 0
   1704 	}
   1705 	# Check if gcc supports -flto -fuse-linker-plugin
   1706 	set flags ""
   1707 	if [board_info [target_info name] exists cflags] {
   1708 	    append flags " [board_info [target_info name] cflags]"
   1709 	}
   1710 	if [board_info [target_info name] exists ldflags] {
   1711 	    append flags " [board_info [target_info name] ldflags]"
   1712 	}
   1713 
   1714 	set basename "tmpdir/lto[pid]"
   1715 	set src ${basename}.c
   1716 	set output ${basename}.out
   1717 	set f [open $src "w"]
   1718 	puts $f "int main() { return 0; }"
   1719 	close $f
   1720 	remote_download host $src
   1721 	set lto_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -fuse-linker-plugin $src -o $output"]
   1722 	remote_file host delete $src
   1723 	remote_file host delete $output
   1724 	file delete $src
   1725     }
   1726     return $lto_available_saved
   1727 }
   1728 
   1729 # Returns true if the target compiler supports LTO  -ffat-lto-objects
   1730 proc check_lto_fat_available { } {
   1731     global lto_fat_available_saved
   1732     global CC
   1733 
   1734     if {![info exists lto_fat_available_saved]} {
   1735         if { [which $CC] == 0 } {
   1736 	    set lto_fat_available_saved 0
   1737 	    return 0
   1738 	}
   1739 	# Check if gcc supports -flto -fuse-linker-plugin
   1740 	set flags ""
   1741 	if [board_info [target_info name] exists cflags] {
   1742 	    append flags " [board_info [target_info name] cflags]"
   1743 	}
   1744 	if [board_info [target_info name] exists ldflags] {
   1745 	    append flags " [board_info [target_info name] ldflags]"
   1746 	}
   1747 
   1748 	set basename "tmpdir/lto[pid]"
   1749 	set src ${basename}.c
   1750 	set output ${basename}.out
   1751 	set f [open $src "w"]
   1752 	puts $f "int main() { return 0; }"
   1753 	close $f
   1754 	remote_download host $src
   1755 	set lto_fat_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -ffat-lto-objects -fuse-linker-plugin $src -o $output"]
   1756 	remote_file host delete $src
   1757 	remote_file host delete $output
   1758 	file delete $src
   1759     }
   1760     return $lto_fat_available_saved
   1761 }
   1762 
   1763 # Returns true if the target compiler supports LTO and -shared
   1764 proc check_lto_shared_available { } {
   1765     global lto_shared_available_saved
   1766     global CC
   1767 
   1768     if {![info exists lto_shared_available_saved]} {
   1769         if { [which $CC] == 0 } {
   1770 	    set lto_shared_available_saved 0
   1771 	    return 0
   1772 	}
   1773 	# Check if gcc supports -flto -fuse-linker-plugin -shared
   1774 	set flags ""
   1775 	if [board_info [target_info name] exists cflags] {
   1776 	    append flags " [board_info [target_info name] cflags]"
   1777 	}
   1778 	if [board_info [target_info name] exists ldflags] {
   1779 	    append flags " [board_info [target_info name] ldflags]"
   1780 	}
   1781 
   1782 	set basename "tmpdir/lto_shared[pid]"
   1783 	set src ${basename}.c
   1784 	set output ${basename}.so
   1785 	set f [open $src "w"]
   1786 	puts $f ""
   1787 	close $f
   1788 	remote_download host $src
   1789 	set lto_shared_available_saved [run_host_cmd_yesno "$CC" "$flags -shared -fPIC -flto -fuse-linker-plugin $src -o $output"]
   1790 	remote_file host delete $src
   1791 	remote_file host delete $output
   1792 	file delete $src
   1793     }
   1794     return $lto_shared_available_saved
   1795 }
   1796 
   1797 # Check if the assembler supports CFI statements.
   1798 
   1799 proc check_as_cfi { } {
   1800     global check_as_cfi_result
   1801     global as
   1802     if [info exists check_as_cfi_result] {
   1803 	return $check_as_cfi_result
   1804     }
   1805     set as_file "tmpdir/check_as_cfi.s"
   1806     set as_fh [open $as_file w 0666]
   1807     puts $as_fh "# Generated file. DO NOT EDIT"
   1808     puts $as_fh "\t.cfi_startproc"
   1809     puts $as_fh "\t.cfi_endproc"
   1810     close $as_fh
   1811     remote_download host $as_file
   1812     verbose -log "Checking CFI support:"
   1813     rename "perror" "check_as_cfi_perror"
   1814     proc perror { args } { }
   1815     set success [ld_assemble $as $as_file "/dev/null"]
   1816     rename "perror" ""
   1817     rename "check_as_cfi_perror" "perror"
   1818     #remote_file host delete $as_file
   1819     set check_as_cfi_result $success
   1820     return $success
   1821 }
   1822 
   1823 # Provide virtual target "cfi" for targets supporting CFI.
   1824 
   1825 rename "istarget" "istarget_ld"
   1826 proc istarget { target } {
   1827     if {$target == "cfi"} {
   1828 	return [check_as_cfi]
   1829     }
   1830     return [istarget_ld $target]
   1831 }
   1832