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