bfd/
[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 #   ld_after_inputfiles: FLAGS
568 #       Similar to "ld", but put after all input files.
569 #
570 #   objcopy_linked_file: FLAGS
571 #       Run objcopy on the linked file with the specified flags.
572 #       This lets you transform the linked file using objcopy, before the
573 #       result is analyzed by an analyzer program specified below (which
574 #       may in turn *also* be objcopy).
575 #
576 #   PROG: PROGRAM-NAME
577 #       The name of the program to run to analyze the .o file produced
578 #       by the assembler or the linker output.  This can be omitted;
579 #       run_dump_test will guess which program to run by seeing which of
580 #       the flags options below is present.
581 #
582 #   objdump: FLAGS
583 #   nm: FLAGS
584 #   objcopy: FLAGS
585 #       Use the specified program to analyze the assembler or linker
586 #       output file, and pass it FLAGS, in addition to the output name.
587 #       Note that they are run with LC_ALL=C in the environment to give
588 #       consistent sorting of symbols.
589 #
590 #   source: SOURCE [FLAGS]
591 #       Assemble the file SOURCE.s using the flags in the "as" directive
592 #       and the (optional) FLAGS.  If omitted, the source defaults to
593 #       FILE.s.
594 #       This is useful if several .d files want to share a .s file.
595 #       More than one "source" directive can be given, which is useful
596 #       when testing linking.
597 #
598 #   xfail: TARGET
599 #       The test is expected to fail on TARGET.  This may occur more than
600 #       once.
601 #
602 #   target: TARGET
603 #       Only run the test for TARGET.  This may occur more than once; the
604 #       target being tested must match at least one.  You may provide target
605 #       name "cfi" for any target supporting the CFI statements.
606 #
607 #   notarget: TARGET
608 #       Do not run the test for TARGET.  This may occur more than once;
609 #       the target being tested must not match any of them.
610 #
611 #   error: REGEX
612 #       An error with message matching REGEX must be emitted for the test
613 #       to pass.  The PROG, objdump, nm and objcopy options have no
614 #       meaning and need not supplied if this is present.
615 #
616 #   warning: REGEX
617 #       Expect a linker warning matching REGEX.  It is an error to issue
618 #       both "error" and "warning".
619 #
620 # Each option may occur at most once unless otherwise mentioned.
621 #
622 # After the option lines come regexp lines.  `run_dump_test' calls
623 # `regexp_diff' to compare the output of the dumping tool against the
624 # regexps in FILE.d.  `regexp_diff' is defined later in this file; see
625 # further comments there.
626 #
627 proc run_dump_test { name } {
628     global subdir srcdir
629     global OBJDUMP NM AS OBJCOPY READELF LD
630     global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS LDFLAGS
631     global host_triplet runtests
632     global env
633
634     if [string match "*/*" $name] {
635         set file $name
636         set name [file tail $name]
637     } else {
638         set file "$srcdir/$subdir/$name"
639     }
640
641     if ![runtest_file_p $runtests $name] then {
642         return
643     }
644
645     set opt_array [slurp_options "${file}.d"]
646     if { $opt_array == -1 } {
647         perror "error reading options from $file.d"
648         unresolved $subdir/$name
649         return
650     }
651     set dumpfile tmpdir/dump.out
652     set run_ld 0
653     set run_objcopy 0
654     set opts(as) {}
655     set opts(ld) {}
656     set opts(ld_after_inputfiles) {}
657     set opts(xfail) {}
658     set opts(target) {}
659     set opts(notarget) {}
660     set opts(objdump) {}
661     set opts(nm) {}
662     set opts(objcopy) {}
663     set opts(readelf) {}
664     set opts(name) {}
665     set opts(PROG) {}
666     set opts(source) {}
667     set opts(error) {}
668     set opts(warning) {}
669     set opts(objcopy_linked_file) {}
670     set asflags(${file}.s) {}
671
672     foreach i $opt_array {
673         set opt_name [lindex $i 0]
674         set opt_val [lindex $i 1]
675         if ![info exists opts($opt_name)] {
676             perror "unknown option $opt_name in file $file.d"
677             unresolved $subdir/$name
678             return
679         }
680
681         switch -- $opt_name {
682             xfail {}
683             target {}
684             notarget {}
685             source {
686                 # Move any source-specific as-flags to a separate array to
687                 # simplify processing.
688                 if { [llength $opt_val] > 1 } {
689                     set asflags([lindex $opt_val 0]) [lrange $opt_val 1 end]
690                     set opt_val [lindex $opt_val 0]
691                 } else {
692                     set asflags($opt_val) {}
693                 }
694             }
695             default {
696                 if [string length $opts($opt_name)] {
697                     perror "option $opt_name multiply set in $file.d"
698                     unresolved $subdir/$name
699                     return
700                 }
701
702                 # A single "# ld:" with no options should do the right thing.
703                 if { $opt_name == "ld" } {
704                     set run_ld 1
705                 }
706                 # Likewise objcopy_linked_file.
707                 if { $opt_name == "objcopy_linked_file" } {
708                     set run_objcopy 1
709                 }
710             }
711         }
712         if { $opt_name == "as" || $opt_name == "ld" } {
713             set opt_val [subst $opt_val]
714         }
715         set opts($opt_name) [concat $opts($opt_name) $opt_val]
716     }
717     foreach opt { as ld } {
718         regsub {\[big_or_little_endian\]} $opts($opt) \
719             [big_or_little_endian] opts($opt)
720     }
721
722     # Decide early whether we should run the test for this target.
723     if { [llength $opts(target)] > 0 } {
724         set targmatch 0
725         foreach targ $opts(target) {
726             if [istarget $targ] {
727                 set targmatch 1
728                 break
729             }
730         }
731         if { $targmatch == 0 } {
732             return
733         }
734     }
735     foreach targ $opts(notarget) {
736         if [istarget $targ] {
737             return
738         }
739     }
740
741     set program ""
742     # It's meaningless to require an output-testing method when we
743     # expect an error.
744     if { $opts(error) == "" } {
745         if {$opts(PROG) != ""} {
746             switch -- $opts(PROG) {
747                 objdump { set program objdump }
748                 nm      { set program nm }
749                 objcopy { set program objcopy }
750                 readelf { set program readelf }
751                 default
752                 { perror "unrecognized program option $opts(PROG) in $file.d"
753                   unresolved $subdir/$name
754                   return }
755             }
756         } else {
757         # Guess which program to run, by seeing which option was specified.
758             foreach p {objdump objcopy nm readelf} {
759                 if {$opts($p) != ""} {
760                     if {$program != ""} {
761                         perror "ambiguous dump program in $file.d"
762                         unresolved $subdir/$name
763                         return
764                     } else {
765                         set program $p
766                     }
767                 }
768             }
769         }
770         if { $program == "" && $opts(warning) == "" } {
771             perror "dump program unspecified in $file.d"
772             unresolved $subdir/$name
773             return
774         }
775     }
776
777     if { $opts(name) == "" } {
778         set testname "$subdir/$name"
779     } else {
780         set testname $opts(name)
781     }
782
783     if { $opts(source) == "" } {
784         set sourcefiles [list ${file}.s]
785     } else {
786         set sourcefiles {}
787         foreach sf $opts(source) {
788             if { [string match "/*" $sf] } {
789                 lappend sourcefiles "$sf"
790             } else {
791                 lappend sourcefiles "$srcdir/$subdir/$sf"
792             }
793             # Must have asflags indexed on source name.
794             set asflags($srcdir/$subdir/$sf) $asflags($sf)
795         }
796     }
797
798     # Time to setup xfailures.
799     foreach targ $opts(xfail) {
800         setup_xfail $targ
801     }
802
803     # Assemble each file.
804     set objfiles {}
805     for { set i 0 } { $i < [llength $sourcefiles] } { incr i } {
806         set sourcefile [lindex $sourcefiles $i]
807
808         set objfile "tmpdir/dump$i.o"
809         catch "exec rm -f $objfile" exec_output
810         lappend objfiles $objfile
811         set cmd "$AS $ASFLAGS $opts(as) $asflags($sourcefile) -o $objfile $sourcefile"
812
813         send_log "$cmd\n"
814         set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
815         remote_upload host "ld.tmp"
816         set comp_output [prune_warnings [file_contents "ld.tmp"]]
817         remote_file host delete "ld.tmp"
818         remote_file build delete "ld.tmp"
819
820         if { [lindex $cmdret 0] != 0 || ![string match "" $comp_output] } then {
821             send_log "$comp_output\n"
822             verbose "$comp_output" 3
823
824             set exitstat "succeeded"
825             if { $cmdret != 0 } { set exitstat "failed" }
826             verbose -log "$exitstat with: <$comp_output>"
827             fail $testname
828             return
829         }
830     }
831
832     set expmsg $opts(error)
833     if { $opts(warning) != "" } {
834         if { $expmsg != "" } {
835             perror "$testname: mixing error and warning test-directives"
836             return
837         }
838         set expmsg $opts(warning)
839     }
840
841     # Perhaps link the file(s).
842     if { $run_ld } {
843         set objfile "tmpdir/dump"
844         catch "exec rm -f $objfile" exec_output
845
846         # Add -L$srcdir/$subdir so that the linker command can use
847         # linker scripts in the source directory.
848         set cmd "$LD $LDFLAGS -L$srcdir/$subdir \
849                    $opts(ld) -o $objfile $objfiles $opts(ld_after_inputfiles)"
850
851         send_log "$cmd\n"
852         set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
853         remote_upload host "ld.tmp"
854         set comp_output [file_contents "ld.tmp"]
855         remote_file host delete "ld.tmp"
856         remote_file build delete "ld.tmp"
857         set cmdret [lindex $cmdret 0]
858
859         if { $cmdret == 0 && $run_objcopy } {
860             set infile $objfile
861             set objfile "tmpdir/dump1"
862             remote_file host delete $objfile
863
864             # Note that we don't use OBJCOPYFLAGS here; any flags must be
865             # explicitly specified.
866             set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile"
867
868             send_log "$cmd\n"
869             set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
870             remote_upload host "ld.tmp"
871             append comp_output [file_contents "ld.tmp"]
872             remote_file host delete "ld.tmp"
873             remote_file build delete "ld.tmp"
874             set cmdret [lindex $cmdret 0]
875         }
876
877         regsub "\n$" $comp_output "" comp_output
878         if { $cmdret != 0 || $comp_output != "" || $expmsg != "" } then {
879             set exitstat "succeeded"
880             if { $cmdret != 0 } { set exitstat "failed" }
881             verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>"
882             send_log "$comp_output\n"
883             verbose "$comp_output" 3
884
885             if { [regexp $expmsg $comp_output] \
886                     && (($cmdret == 0) == ($opts(warning) != "")) } {
887                 # We have the expected output from ld.
888                 if { $opts(error) != "" || $program == "" } {
889                     pass $testname
890                     return
891                 }
892             } else {
893                 verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>"
894                 fail $testname
895                 return
896             }
897         }
898     } else {
899         set objfile "tmpdir/dump0.o"
900     }
901
902     # We must not have expected failure if we get here.
903     if { $opts(error) != "" } {
904         fail $testname
905         return
906     }
907
908     set progopts1 $opts($program)
909     eval set progopts \$[string toupper $program]FLAGS
910     eval set binary \$[string toupper $program]
911
912     if { ![is_remote host] && [which $binary] == 0 } {
913         untested $testname
914         return
915     }
916
917     if { $progopts1 == "" } { set $progopts1 "-r" }
918     verbose "running $binary $progopts $progopts1" 3
919
920     # Objcopy, unlike the other two, won't send its output to stdout,
921     # so we have to run it specially.
922     set cmd "$binary $progopts $progopts1 $objfile > $dumpfile"
923     if { $program == "objcopy" } {
924         set cmd "$binary $progopts $progopts1 $objfile $dumpfile"
925     }
926
927     # Ensure consistent sorting of symbols
928     if {[info exists env(LC_ALL)]} {
929         set old_lc_all $env(LC_ALL)
930     }
931     set env(LC_ALL) "C"
932     send_log "$cmd\n"
933     set cmdret [remote_exec host [concat sh -c [list "$cmd 2>ld.tmp"]] "" "/dev/null"]
934     remote_upload host "ld.tmp"
935     set comp_output [prune_warnings [file_contents "ld.tmp"]]
936     remote_file host delete "ld.tmp"
937     remote_file build delete "ld.tmp"
938     if {[info exists old_lc_all]} {
939         set env(LC_ALL) $old_lc_all
940     } else {
941         unset env(LC_ALL)
942     }
943     if ![string match "" $comp_output] then {
944         send_log "$comp_output\n"
945         fail $testname
946         return
947     }
948
949     verbose_eval {[file_contents $dumpfile]} 3
950     if { [regexp_diff $dumpfile "${file}.d"] } then {
951         fail $testname
952         verbose "output is [file_contents $dumpfile]" 2
953         return
954     }
955
956     pass $testname
957 }
958
959 proc slurp_options { file } {
960     if [catch { set f [open $file r] } x] {
961         #perror "couldn't open `$file': $x"
962         perror "$x"
963         return -1
964     }
965     set opt_array {}
966     # whitespace expression
967     set ws  {[  ]*}
968     set nws {[^         ]*}
969     # whitespace is ignored anywhere except within the options list;
970     # option names are alphabetic plus underscore only.
971     set pat "^#${ws}(\[a-zA-Z_\]*)$ws:${ws}(.*)$ws\$"
972     while { [gets $f line] != -1 } {
973         set line [string trim $line]
974         # Whitespace here is space-tab.
975         if [regexp $pat $line xxx opt_name opt_val] {
976             # match!
977             lappend opt_array [list $opt_name $opt_val]
978         } else {
979             break
980         }
981     }
982     close $f
983     return $opt_array
984 }
985
986 # regexp_diff, copied from gas, based on simple_diff above.
987 #       compares two files line-by-line
988 #       file1 contains strings, file2 contains regexps and #-comments
989 #       blank lines are ignored in either file
990 #       returns non-zero if differences exist
991 #
992 proc regexp_diff { file_1 file_2 } {
993
994     set eof -1
995     set end_1 0
996     set end_2 0
997     set differences 0
998     set diff_pass 0
999
1000     if [file exists $file_1] then {
1001         set file_a [open $file_1 r]
1002     } else {
1003         warning "$file_1 doesn't exist"
1004         return 1
1005     }
1006
1007     if [file exists $file_2] then {
1008         set file_b [open $file_2 r]
1009     } else {
1010         fail "$file_2 doesn't exist"
1011         close $file_a
1012         return 1
1013     }
1014
1015     verbose " Regexp-diff'ing: $file_1 $file_2" 2
1016
1017     while { 1 } {
1018         set line_a ""
1019         set line_b ""
1020         while { [string length $line_a] == 0 } {
1021             if { [gets $file_a line_a] == $eof } {
1022                 set end_1 1
1023                 break
1024             }
1025         }
1026         while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
1027             if [ string match "#pass" $line_b ] {
1028                 set end_2 1
1029                 set diff_pass 1
1030                 break
1031             } elseif [ string match "#..." $line_b ] {
1032                 if { [gets $file_b line_b] == $eof } {
1033                     set end_2 1
1034                     set diff_pass 1
1035                     break
1036                 }
1037                 verbose "looking for \"^$line_b$\"" 3
1038                 while { ![regexp "^$line_b$" "$line_a"] } {
1039                     verbose "skipping    \"$line_a\"" 3
1040                     if { [gets $file_a line_a] == $eof } {
1041                         set end_1 1
1042                         break
1043                     }
1044                 }
1045                 break
1046             }
1047             if { [gets $file_b line_b] == $eof } {
1048                 set end_2 1
1049                 break
1050             }
1051         }
1052
1053         if { $diff_pass } {
1054             break
1055         } elseif { $end_1 && $end_2 } {
1056             break
1057         } elseif { $end_1 } {
1058             send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
1059             verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
1060             set differences 1
1061             break
1062         } elseif { $end_2 } {
1063             send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
1064             verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
1065             set differences 1
1066             break
1067         } else {
1068             verbose "regexp \"^$line_b$\"\nline   \"$line_a\"" 3
1069             if ![regexp "^$line_b$" "$line_a"] {
1070                 send_log "regexp_diff match failure\n"
1071                 send_log "regexp \"^$line_b$\"\nline   \"$line_a\"\n"
1072                 set differences 1
1073             }
1074         }
1075     }
1076
1077     if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
1078         send_log "$file_1 and $file_2 are different lengths\n"
1079         verbose "$file_1 and $file_2 are different lengths" 3
1080         set differences 1
1081     }
1082
1083     close $file_a
1084     close $file_b
1085
1086     return $differences
1087 }
1088
1089 proc file_contents { filename } {
1090     set file [open $filename r]
1091     set contents [read $file]
1092     close $file
1093     return $contents
1094 }
1095
1096 # Create an archive using ar
1097 #
1098 proc ar_simple_create { ar target objects } {
1099     remote_file host delete $target
1100
1101     set exec_output [run_host_cmd "$ar" "rc $target $objects"]
1102     set exec_output [prune_warnings $exec_output]
1103
1104     if [string match "" $exec_output] then {
1105         send_log "$exec_output\n"
1106         return 1
1107     } else {
1108         return 0
1109     }
1110 }
1111
1112 # List contains test-items with 3 items followed by 2 lists, one item and
1113 # one optional item:
1114 # 0:name 1:ld options 2:assembler options
1115 # 3:filenames of assembler files 4: action and options. 5: name of output file
1116 # 6:compiler flags (optional)
1117 #
1118 # Actions:
1119 # objdump: Apply objdump options on result.  Compare with regex (last arg).
1120 # nm: Apply nm options on result.  Compare with regex (last arg).
1121 # readelf: Apply readelf options on result.  Compare with regex (last arg).
1122 #
1123 proc run_ld_link_tests { ldtests } {
1124     global ld
1125     global as
1126     global nm
1127     global ar
1128     global objdump
1129     global READELF
1130     global srcdir
1131     global subdir
1132     global env
1133     global CC
1134     global CFLAGS
1135
1136     foreach testitem $ldtests {
1137         set testname [lindex $testitem 0]
1138         set ld_options [lindex $testitem 1]
1139         set as_options [lindex $testitem 2]
1140         set src_files  [lindex $testitem 3]
1141         set actions [lindex $testitem 4]
1142         set binfile tmpdir/[lindex $testitem 5]
1143         set cflags [lindex $testitem 6]
1144         set objfiles {}
1145         set is_unresolved 0
1146         set failed 0
1147
1148 #       verbose -log "Testname is $testname"
1149 #       verbose -log "ld_options is $ld_options"
1150 #       verbose -log "as_options is $as_options"
1151 #       verbose -log "src_files is $src_files"
1152 #       verbose -log "actions is $actions"
1153 #       verbose -log "binfile is $binfile"
1154
1155         # Assemble each file in the test.
1156         foreach src_file $src_files {
1157             set objfile "tmpdir/[file rootname $src_file].o"
1158             lappend objfiles $objfile
1159
1160             if { [file extension $src_file] == ".c" } {
1161                 set as_file "tmpdir/[file rootname $src_file].s"
1162                 if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
1163                     set is_unresolved 1
1164                     break
1165                 }
1166             } else {
1167                 set as_file "$srcdir/$subdir/$src_file"
1168             }
1169             if ![ld_assemble $as "$as_options $as_file" $objfile] {
1170                 set is_unresolved 1
1171                 break
1172             }
1173         }
1174
1175         # Catch assembler errors.
1176         if { $is_unresolved != 0 } {
1177             unresolved $testname
1178             continue
1179         }
1180
1181         if [regexp ".*a$" $binfile] then {
1182             if ![ar_simple_create $ar $binfile "$objfiles"] {
1183                 fail $testname
1184                 set failed 1
1185             } else {
1186                 set failed 0
1187             }
1188         } elseif ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
1189             fail $testname
1190             set failed 1
1191         } else {
1192             set failed 0
1193         }
1194
1195         if { $failed == 0 } {
1196             foreach actionlist $actions {
1197                 set action [lindex $actionlist 0]
1198                 set progopts [lindex $actionlist 1]
1199
1200                 # There are actions where we run regexp_diff on the
1201                 # output, and there are other actions (presumably).
1202                 # Handling of the former look the same.
1203                 set dump_prog ""
1204                 switch -- $action {
1205                     objdump
1206                         { set dump_prog $objdump }
1207                     nm
1208                         { set dump_prog $nm }
1209                     readelf
1210                         { set dump_prog $READELF }
1211                     default
1212                         {
1213                             perror "Unrecognized action $action"
1214                             set is_unresolved 1
1215                             break
1216                         }
1217                     }
1218
1219                 if { $dump_prog != "" } {
1220                     set dumpfile [lindex $actionlist 2]
1221                     set binary $dump_prog
1222
1223                     # Ensure consistent sorting of symbols
1224                     if {[info exists env(LC_ALL)]} {
1225                         set old_lc_all $env(LC_ALL)
1226                     }
1227                     set env(LC_ALL) "C"
1228                     set cmd "$binary $progopts $binfile"
1229                     set status [remote_exec host [concat sh -c [list "$cmd >dump.out 2>ld.stderr"]] "" "/dev/null"]
1230                     send_log "$cmd\n"
1231                     remote_upload host "ld.stderr"
1232                     set comp_output [prune_warnings [file_contents "ld.stderr"]]
1233                     remote_file host delete "ld.stderr"
1234                     remote_file build delete "ld.stderr"
1235                     
1236                     if {[info exists old_lc_all]} {
1237                         set env(LC_ALL) $old_lc_all
1238                     } else {
1239                         unset env(LC_ALL)
1240                     }
1241
1242                     if ![string match "" $comp_output] then {
1243                         send_log "$comp_output\n"
1244                         set failed 1
1245                         break
1246                     }
1247
1248                     remote_upload host "dump.out"
1249
1250                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1251                         verbose "output is [file_contents "dump.out"]" 2
1252                         set failed 1
1253                         remote_file build delete "dump.out"
1254                         remote_file host delete "dump.out"
1255                         break
1256                     }
1257                     remote_file build delete "dump.out"
1258                     remote_file host delete "dump.out"
1259                 }
1260             }
1261
1262             if { $failed != 0 } {
1263                 fail $testname
1264             } else { if { $is_unresolved == 0 } {
1265                 pass $testname
1266             } }
1267         }
1268
1269         # Catch action errors.
1270         if { $is_unresolved != 0 } {
1271             unresolved $testname
1272             continue
1273         }
1274     }
1275 }
1276
1277
1278 proc verbose_eval { expr { level 1 } } {
1279     global verbose
1280     if $verbose>$level then { eval verbose "$expr" $level }
1281 }
1282
1283 # This definition is taken from an unreleased version of DejaGnu.  Once
1284 # that version gets released, and has been out in the world for a few
1285 # months at least, it may be safe to delete this copy.
1286 if ![string length [info proc prune_warnings]] {
1287     #
1288     # prune_warnings -- delete various system verbosities from TEXT
1289     #
1290     # An example is:
1291     # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
1292     #
1293     # Sites with particular verbose os's may wish to override this in site.exp.
1294     #
1295     proc prune_warnings { text } {
1296         # This is from sun4's.  Do it for all machines for now.
1297         # The "\\1" is to try to preserve a "\n" but only if necessary.
1298         regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
1299
1300         # It might be tempting to get carried away and delete blank lines, etc.
1301         # Just delete *exactly* what we're ask to, and that's it.
1302         return $text
1303     }
1304 }
1305
1306 # targets_to_xfail is a list of target triplets to be xfailed.
1307 # ldtests contains test-items with 3 items followed by 1 lists, 2 items
1308 # and 3 optional items:
1309 #   0:name
1310 #   1:ld options
1311 #   2:assembler options
1312 #   3:filenames of source files
1313 #   4:name of output file
1314 #   5:expected output
1315 #   6:compiler flags (optional)
1316 #   7:language (optional)
1317 #   8:linker warning (optional)
1318
1319 proc run_ld_link_exec_tests { targets_to_xfail ldtests } {
1320     global ld
1321     global as
1322     global srcdir
1323     global subdir
1324     global env
1325     global CC
1326     global CXX
1327     global CFLAGS
1328     global CXXFLAGS
1329     global errcnt
1330     global exec_output
1331
1332     foreach testitem $ldtests {
1333         foreach target $targets_to_xfail {
1334             setup_xfail $target
1335         }
1336         set testname [lindex $testitem 0]
1337         set ld_options [lindex $testitem 1]
1338         set as_options [lindex $testitem 2]
1339         set src_files  [lindex $testitem 3]
1340         set binfile tmpdir/[lindex $testitem 4]
1341         set expfile [lindex $testitem 5]
1342         set cflags [lindex $testitem 6]
1343         set lang [lindex $testitem 7]
1344         set warning [lindex $testitem 8]
1345         set objfiles {}
1346         set failed 0
1347
1348 #       verbose -log "Testname is $testname"
1349 #       verbose -log "ld_options is $ld_options"
1350 #       verbose -log "as_options is $as_options"
1351 #       verbose -log "src_files is $src_files"
1352 #       verbose -log "actions is $actions"
1353 #       verbose -log "binfile is $binfile"
1354
1355         # Assemble each file in the test.
1356         foreach src_file $src_files {
1357             set objfile "tmpdir/[file rootname $src_file].o"
1358             lappend objfiles $objfile
1359
1360             # We ignore warnings since some compilers may generate
1361             # incorrect section attributes and the assembler will warn
1362             # them.
1363             if { [ string match "c++" $lang ] } {
1364                 ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1365             } else {
1366                 ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1367             }
1368
1369             # We have to use $CC to build PIE and shared library.
1370             if { [ string match "c" $lang ] } {
1371                 set link_proc ld_simple_link
1372                 set link_cmd $CC
1373             } elseif { [ string match "c++" $lang ] } {
1374                 set link_proc ld_simple_link
1375                 set link_cmd $CXX
1376             } elseif { [ string match "-shared" $ld_options ] \
1377                  || [ string match "-pie" $ld_options ] } {
1378                 set link_proc ld_simple_link
1379                 set link_cmd $CC
1380             } else {
1381                 set link_proc ld_link
1382                 set link_cmd $ld
1383             }
1384
1385             if ![$link_proc $link_cmd $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
1386                 set failed 1
1387             } else {
1388                 set failed 0
1389             }
1390
1391             # Check if exec_output is expected.
1392             if { $warning != "" } then {
1393                 verbose -log "returned with: <$exec_output>, expected: <$warning>"
1394                 if { [regexp $warning $exec_output] } then {
1395                     set failed 0
1396                 } else {
1397                     set failed 1
1398                 }
1399             }
1400
1401             if { $failed == 0 } {
1402                 send_log "Running: $binfile > $binfile.out\n"
1403                 verbose "Running: $binfile > $binfile.out"
1404                 catch "exec $binfile > $binfile.out" exec_output
1405             
1406                 if ![string match "" $exec_output] then {
1407                     send_log "$exec_output\n"
1408                     verbose "$exec_output" 1
1409                     set failed 1
1410                 } else {
1411                     send_log "diff $binfile.out $srcdir/$subdir/$expfile\n"
1412                     verbose "diff $binfile.out $srcdir/$subdir/$expfile"
1413                     catch "exec diff $binfile.out $srcdir/$subdir/$expfile" exec_output
1414                     set exec_output [prune_warnings $exec_output]
1415
1416                     if ![string match "" $exec_output] then {
1417                         send_log "$exec_output\n"
1418                         verbose "$exec_output" 1
1419                         set failed 1
1420                     }
1421                 }
1422             }
1423
1424             if { $failed != 0 } {
1425                 fail $testname
1426             } else {
1427                 set errcnt 0
1428                 pass $testname
1429             }
1430         }
1431     }
1432 }
1433
1434 # List contains test-items with 3 items followed by 2 lists, one item and
1435 # one optional item:
1436 #  0:name
1437 #  1:link options
1438 #  2:compile options
1439 #  3:filenames of source files
1440 #  4:action and options.
1441 #  5:name of output file
1442 #  6:language (optional)
1443 #
1444 # Actions:
1445 # objdump: Apply objdump options on result.  Compare with regex (last arg).
1446 # nm: Apply nm options on result.  Compare with regex (last arg).
1447 # readelf: Apply readelf options on result.  Compare with regex (last arg).
1448 #
1449 proc run_cc_link_tests { ldtests } {
1450     global nm
1451     global objdump
1452     global READELF
1453     global srcdir
1454     global subdir
1455     global env
1456     global CC
1457     global CXX
1458     global CFLAGS
1459     global CXXFLAGS
1460     global ar
1461
1462     foreach testitem $ldtests {
1463         set testname [lindex $testitem 0]
1464         set ldflags [lindex $testitem 1]
1465         set cflags [lindex $testitem 2]
1466         set src_files  [lindex $testitem 3]
1467         set actions [lindex $testitem 4]
1468         set binfile tmpdir/[lindex $testitem 5]
1469         set lang [lindex $testitem 6]
1470         set objfiles {}
1471         set is_unresolved 0
1472         set failed 0
1473
1474         # Compile each file in the test.
1475         foreach src_file $src_files {
1476             set objfile "tmpdir/[file rootname $src_file].o"
1477             lappend objfiles $objfile
1478
1479             # We ignore warnings since some compilers may generate
1480             # incorrect section attributes and the assembler will warn
1481             # them.
1482             if { [ string match "c++" $lang ] } {
1483                 ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1484             } else {
1485                 ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1486             }
1487         }
1488
1489         # Clear error and warning counts.
1490         reset_vars
1491
1492         if { [ string match "c++" $lang ] } {
1493             set cc_cmd $CXX
1494         } else {
1495             set cc_cmd $CC
1496         }
1497
1498         if [regexp ".*a$" $binfile] then {
1499             if ![ar_simple_create $ar $binfile "$objfiles"] {
1500                 fail $testname
1501                 set failed 1
1502             } else {
1503                 set failed 0
1504             }
1505         } elseif ![ld_simple_link $cc_cmd $binfile "-L$srcdir/$subdir $ldflags $objfiles"] {
1506             fail $testname
1507             set failed 1
1508         } else {
1509             set failed 0
1510         }
1511
1512         if { $failed == 0 } {
1513             foreach actionlist $actions {
1514                 set action [lindex $actionlist 0]
1515                 set progopts [lindex $actionlist 1]
1516
1517                 # There are actions where we run regexp_diff on the
1518                 # output, and there are other actions (presumably).
1519                 # Handling of the former look the same.
1520                 set dump_prog ""
1521                 switch -- $action {
1522                     objdump
1523                         { set dump_prog $objdump }
1524                     nm
1525                         { set dump_prog $nm }
1526                     readelf
1527                         { set dump_prog $READELF }
1528                     default
1529                         {
1530                             perror "Unrecognized action $action"
1531                             set is_unresolved 1
1532                             break
1533                         }
1534                     }
1535
1536                 if { $dump_prog != "" } {
1537                     set dumpfile [lindex $actionlist 2]
1538                     set binary $dump_prog
1539
1540                     # Ensure consistent sorting of symbols
1541                     if {[info exists env(LC_ALL)]} {
1542                         set old_lc_all $env(LC_ALL)
1543                     }
1544                     set env(LC_ALL) "C"
1545                     set cmd "$binary $progopts $binfile > dump.out"
1546                     send_log "$cmd\n"
1547                     catch "exec $cmd" comp_output
1548                     if {[info exists old_lc_all]} {
1549                         set env(LC_ALL) $old_lc_all
1550                     } else {
1551                         unset env(LC_ALL)
1552                     }
1553                     set comp_output [prune_warnings $comp_output]
1554
1555                     if ![string match "" $comp_output] then {
1556                         send_log "$comp_output\n"
1557                         set failed 1
1558                         break
1559                     }
1560
1561                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1562                         verbose "output is [file_contents "dump.out"]" 2
1563                         set failed 1
1564                         break
1565                     }
1566                 }
1567             }
1568
1569             if { $failed != 0 } {
1570                 fail $testname
1571             } else { if { $is_unresolved == 0 } {
1572                 pass $testname
1573             } }
1574         }
1575
1576         # Catch action errors.
1577         if { $is_unresolved != 0 } {
1578             unresolved $testname
1579             continue
1580         }
1581     }
1582 }
1583
1584 # Returns true if --gc-sections is supported on the target.
1585
1586 proc check_gc_sections_available { } {
1587     global gc_sections_available_saved
1588     global ld
1589     
1590     if {![info exists gc_sections_available_saved]} {
1591         # Some targets don't support gc-sections despite whatever's
1592         # advertised by ld's options.
1593         if { [istarget alpha*-*-*]
1594              || [istarget ia64-*-*] } {
1595             set gc_sections_available_saved 0
1596             return 0
1597         }
1598
1599         # elf2flt uses -q (--emit-relocs), which is incompatible with
1600         # --gc-sections.
1601         if { [board_info target exists ldflags]
1602              && [regexp " -elf2flt\[ =\]" " [board_info target ldflags] "] } {
1603             set gc_sections_available_saved 0
1604             return 0
1605         }
1606
1607         # Check if the ld used by gcc supports --gc-sections.
1608         set ld_output [remote_exec host $ld "--help"]
1609         if { [ string first "--gc-sections" $ld_output ] >= 0 } {
1610             set gc_sections_available_saved 1
1611         } else {
1612             set gc_sections_available_saved 0
1613         }
1614     }
1615     return $gc_sections_available_saved
1616 }
1617
1618 # Check if the assembler supports CFI statements.
1619
1620 proc check_as_cfi { } {
1621     global check_as_cfi_result
1622     global as
1623     if [info exists check_as_cfi_result] {
1624         return $check_as_cfi_result
1625     }
1626     set as_file "tmpdir/check_as_cfi.s"
1627     set as_fh [open $as_file w 0666]
1628     puts $as_fh "# Generated file. DO NOT EDIT"
1629     puts $as_fh "\t.cfi_startproc"
1630     puts $as_fh "\t.cfi_endproc"
1631     close $as_fh
1632     remote_download host $as_file
1633     verbose -log "Checking CFI support:"
1634     rename "perror" "check_as_cfi_perror"
1635     proc perror { args } { }
1636     set success [ld_assemble $as $as_file "/dev/null"]
1637     rename "perror" ""
1638     rename "check_as_cfi_perror" "perror"
1639     #remote_file host delete $as_file
1640     set check_as_cfi_result $success
1641     return $success
1642 }
1643
1644 # Provide virtual target "cfi" for targets supporting CFI.
1645
1646 rename "istarget" "istarget_ld"
1647 proc istarget { target } {
1648     if {$target == "cfi"} {
1649         return [check_as_cfi]
1650     }
1651     return [istarget_ld $target]
1652 }