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