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