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