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