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