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