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