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