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