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