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