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