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