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