Use better test for usable compiler in ld testsuite.
[external/binutils.git] / ld / testsuite / lib / ld-lib.exp
1 # Support routines for LD testsuite.
2 #   Copyright (C) 1994-2019 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     global gcc_ld_B_opt_tested
89     global ld
90
91     if { ![is_remote host] && [which "$prog"] == 0 } then {
92         perror "$prog does not exist"
93         return 0
94     }
95
96     # If we are compiling with gcc, we want to add gcc_B_opt and
97     # ld_L_opt to flags.  However, if $prog already has -B options,
98     # which might be the case when running gcc out of a build
99     # directory, we want our -B options to come first.
100     set gccexe $prog
101     set gccparm [string first " " $gccexe]
102     set gccflags ""
103     if { $gccparm > 0 } then {
104         set gccflags [string range $gccexe $gccparm end]
105         set gccexe [string range $gccexe 0 $gccparm]
106         set prog $gccexe
107     }
108     set gccexe [string replace $gccexe 0 [string last "/" $gccexe] ""]
109     if {[string match "*cc*" $gccexe] || [string match "*++*" $gccexe]} then {
110         set gccflags "$gcc_B_opt $gccflags $ld_L_opt"
111         if {![info exists gcc_ld_B_opt_tested]} {
112             set gcc_ld_B_opt_tested 1
113             set ld_version_message [run_host_cmd "$ld" "--version"]
114             set gcc_ld_version_message [run_host_cmd "$prog" "$gccflags -Wl,--version"]
115             if {[string first $ld_version_message $gcc_ld_version_message] < 0} {
116                 perror "************************************************************************"
117                 perror "Your compiler driver ignores -B when choosing ld."
118                 perror "You will not be testing the new ld in many of the following tests."
119                 set gcc_ld_version [run_host_cmd "$prog" "$gccflags --print-prog-name=ld"]
120                 if {![string match "" $gcc_ld_version] && ![string match "ld" $gcc_ld_version]} {
121                 
122                     perror "It seems you will be testing $gcc_ld_version instead."
123                 }
124                 perror "************************************************************************"
125             }
126         }
127     }
128
129     verbose -log "$prog $gccflags $command"
130     set status [remote_exec host [concat sh -c [list "$prog $gccflags $command 2>&1"]] "" "/dev/null" "ld.tmp"]
131     remote_upload host "ld.tmp"
132     set link_output [file_contents "ld.tmp"]
133     regsub "\n$" $link_output "" link_output
134     if { [lindex $status 0] != 0 && [string match "" $link_output] } then {
135         append link_output "child process exited abnormally"
136     }
137     remote_file build delete ld.tmp
138     remote_file host delete ld.tmp
139
140     if [string match "" $link_output] then {
141         return ""
142     }
143
144     verbose -log "$link_output"
145     return "$link_output"
146 }
147
148 proc run_host_cmd_yesno { prog command } {
149     global exec_output
150     global errcnt warncnt
151
152     set exec_output [prune_warnings [run_host_cmd "$prog" "$command"]]
153     # Ignore error and warning.
154     set errcnt 0
155     set warncnt 0
156     if [string match "" $exec_output] then {
157         return 1;
158     }
159     return 0;
160 }
161
162 # Link an object using relocation.
163 #
164 proc default_ld_relocate { ld target objects } {
165     global HOSTING_EMU
166
167     remote_file host delete $target
168     return [run_host_cmd_yesno "$ld" "$HOSTING_EMU -o $target -r $objects"]
169 }
170
171 # Check to see if ld is being invoked with a non-endian output format
172 #
173 proc is_endian_output_format { object_flags } {
174
175     if {[string match "*-oformat binary*" $object_flags] ||      \
176         [string match "*-oformat ieee*" $object_flags] ||        \
177         [string match "*-oformat ihex*" $object_flags] ||        \
178         [string match "*-oformat netbsd-core*" $object_flags] || \
179         [string match "*-oformat srec*" $object_flags] ||        \
180         [string match "*-oformat tekhex*" $object_flags] ||      \
181         [string match "*-oformat trad-core*" $object_flags] } then {
182         return 0
183     } else {
184         return 1
185     }
186 }
187
188 # Link a program using ld
189 #
190 proc default_ld_link { ld target objects } {
191     global host_triplet
192     global exec_output
193
194     set flags ""
195     if [is_endian_output_format $objects] then {
196         set flags [big_or_little_endian]
197     }
198
199     remote_file host delete $target
200     set exec_output [run_host_cmd "$ld" "$flags -o $target $objects"]
201     set exec_output [prune_warnings $exec_output]
202
203     # We don't care if we get a warning about a non-existent start
204     # symbol, since the default linker script might use ENTRY.
205     regsub -all "(^|\n)(\[^\n\]*: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
206
207     return [string match "" $exec_output]
208 }
209
210 # Compile an object using cc.
211 #
212 proc default_ld_compile { cc source object } {
213     global CFLAGS
214     global CXXFLAGS
215     global srcdir
216     global subdir
217     global host_triplet
218     global gcc_B_opt
219
220     set cc_prog $cc
221     if {[llength $cc_prog] > 1} then {
222         set cc_prog [lindex $cc_prog 0]
223     }
224     if {![is_remote host] && [which $cc_prog] == 0} then {
225         perror "$cc_prog does not exist"
226         return 0
227     }
228
229     remote_file build delete "$object"
230     remote_file host delete "$object"
231
232     set flags "$gcc_B_opt -I$srcdir/$subdir"
233
234     # If we are compiling with gcc, we want to add gcc_B_opt to flags.
235     # However, if $prog already has -B options, which might be the
236     # case when running gcc out of a build directory, we want our -B
237     # options to come first.
238     set ccexe $cc
239     set ccparm [string first " " $cc]
240     set ccflags ""
241     if { $ccparm > 0 } then {
242         set ccflags [string range $cc $ccparm end]
243         set ccexe [string range $cc 0 $ccparm]
244         set cc $ccexe
245     }
246
247     set ccexe [string replace $ccexe 0 [string last "/" $ccexe] ""]
248     if {[string match "*++*" $ccexe]} {
249         append flags " $CXXFLAGS"
250     } else {
251         append flags " $CFLAGS"
252     }
253
254     if [board_info [target_info name] exists cflags] {
255         append flags " [board_info [target_info name] cflags]"
256     }
257
258     if [board_info [target_info name] exists multilib_flags] {
259         append flags " [board_info [target_info name] multilib_flags]"
260     }
261
262     set cmd "$cc $flags $ccflags -c $source -o $object"
263     verbose -log "$cmd"
264
265     set status [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
266     remote_upload host "ld.tmp"
267     set exec_output [file_contents "ld.tmp"]
268     remote_file build delete "ld.tmp"
269     remote_file host delete "ld.tmp"
270     set exec_output [prune_warnings $exec_output]
271     # Versions of gcc up to and including pre-release gcc-7, at least on
272     # some targets, generate .section directives with incorrect type.
273     # Ignore warnings from the assembler about this.
274     regsub -all "(^|\n)\[^\n\]*: ignoring incorrect section type \[^\n\]*" $exec_output "" exec_output
275     regsub -all "^\[^\n\]*: Assembler messages:\n" $exec_output "" exec_output
276     if [string match "" $exec_output] then {
277         if {![file exists $object]} then {
278             regexp ".*/(\[^/\]*)$" $source all dobj
279             regsub "\\.c" $dobj ".o" realobj
280             verbose "looking for $realobj"
281             if {[remote_file host exists $realobj]} then {
282                 verbose -log "mv $realobj $object"
283                 remote_upload "$realobj" "$object"
284             } else {
285                 perror "$object not found after compilation"
286                 return 0
287             }
288         }
289         return 1
290     } else {
291         verbose -log "$exec_output"
292         perror "$source: compilation failed"
293         return 0
294     }
295 }
296
297 # Assemble a file.
298 #
299 proc default_ld_assemble { as in_flags source object } {
300     global ASFLAGS
301     global host_triplet
302     global srcdir
303     global subdir
304
305     if ![info exists ASFLAGS] { set ASFLAGS "" }
306
307     set flags "[big_or_little_endian] -I$srcdir/$subdir"
308     set exec_output [run_host_cmd "$as" "$flags $in_flags $ASFLAGS -o $object $source"]
309     set exec_output [prune_warnings $exec_output]
310     if [string match "" $exec_output] then {
311         return 1
312     } else {
313         perror "$source: assembly failed"
314         return 0
315     }
316 }
317
318 # Run nm on a file, putting the result in the array nm_output.
319 #
320 proc default_ld_nm { nm nmflags object } {
321     global NMFLAGS
322     global nm_output
323     global host_triplet
324
325     if {[info exists nm_output]} {
326       unset nm_output
327     }
328
329     if ![info exists NMFLAGS] { set NMFLAGS "" }
330
331     # Ensure consistent sorting of symbols
332     if {[info exists env(LC_ALL)]} {
333         set old_lc_all $env(LC_ALL)
334     }
335     set env(LC_ALL) "C"
336
337     verbose -log "$nm $NMFLAGS $nmflags $object >tmpdir/nm.out"
338
339     set status [remote_exec host [concat sh -c [list "$nm $NMFLAGS $nmflags $object 2>ld.stderr"]] "" "/dev/null" "tmpdir/nm.out"]
340     if {[info exists old_lc_all]} {
341         set env(LC_ALL) $old_lc_all
342     } else {
343         unset env(LC_ALL)
344     }
345     remote_upload host "ld.stderr"
346     remote_upload host "tmpdir/nm.out" "tmpdir/nm.out"
347     set exec_output [prune_warnings [file_contents "ld.stderr"]]
348     remote_file host delete "ld.stderr"
349     remote_file build delete "ld.stderr"
350     if [string match "" $exec_output] then {
351         set file [open tmpdir/nm.out r]
352         while { [gets $file line] != -1 } {
353             verbose "$line" 2
354             if [regexp "^(\[0-9a-fA-F\]+) \[a-zA-Z0-9\] \\.*(.+)$" $line whole value name] {
355                 set name [string trimleft $name "_"]
356                 verbose "Setting nm_output($name) to 0x$value" 2
357                 set nm_output($name) 0x$value
358             }
359         }
360         close $file
361         return 1
362     } else {
363         verbose -log "$exec_output"
364         perror "$object: nm failed"
365         return 0
366     }
367 }
368
369 # Define various symbols needed when not linking against all
370 # target libs.
371 proc ld_link_defsyms {} {
372
373     set flags "--defsym __stack_chk_fail=0"
374
375     # ARM targets call __gccmain
376     if {[istarget arm*-*-*]} {
377         append flags " --defsym __gccmain=0"
378     }
379
380     # Windows targets need __main, some prefixed with underscore.
381     if {[istarget *-*-cygwin* ] || [istarget *-*-mingw*]} {
382         append flags " --defsym __main=0 --defsym ___main=0"
383     }
384
385     # PowerPC EABI code calls __eabi.
386     if {[istarget powerpc*-*-eabi*] || [istarget powerpc*-*-rtems*]} {
387         append flags " --defsym __eabi=0"
388     }
389
390     # mn10200 code calls __truncsipsi2_d0_d2.
391     if {[istarget mn10200*-*-*]} then {
392         append flags " --defsym __truncsipsi2_d0_d2=0"
393     }
394
395     # m6811/m6812 code has references to soft registers.
396     if {[istarget m6811-*-*] || [istarget m6812-*-*] || [istarget m68hc1*-*-*]} {
397         append flags " --defsym _.frame=0 --defsym _.d1=0 --defsym _.d2=0"
398         append flags " --defsym _.d3=0 --defsym _.d4=0"
399         append flags " --defsym _.tmp=0 --defsym _.xy=0 --defsym _.z=0"
400     }
401
402     # Some OpenBSD targets have ProPolice and reference __guard and
403     # __stack_smash_handler.
404     if [istarget *-*-openbsd*] {
405         append flags " --defsym __guard=0"
406         append flags " --defsym __stack_smash_handler=0"
407     }
408
409     return $flags
410 }
411
412 # Create an archive using ar
413 #
414 proc ar_simple_create { ar aropts target objects } {
415     remote_file host delete $target
416
417     set exec_output [run_host_cmd "$ar" "-rc $aropts $target $objects"]
418     set exec_output [prune_warnings $exec_output]
419
420     if [string match "" $exec_output] then {
421         send_log "$exec_output\n"
422         return 1
423     } else {
424         return 0
425     }
426 }
427
428 # List contains test-items with 3 items followed by 2 lists, one item and
429 # one optional item:
430 #  0:name
431 #  1:ld/ar leading options, placed before object files
432 #  2:ld/ar trailing options, placed after object files
433 #  3:assembler options
434 #  4:filenames of assembler files
435 #  5:list of actions, options and expected outputs.
436 #  6:name of output file
437 #  7:compiler flags (optional)
438 #
439 # Actions: { command command-line-options file-containg-expected-output-regexps }
440 # Commands:
441 #   objdump: Apply objdump options on result.
442 #   nm: Apply nm options on result.
443 #   readelf: Apply readelf options on result.
444 #   ld: Don't apply anything on result.  Compare output during linking with
445 #     the file containing regexps (which is the second arg, not the third).
446 #     Note that this *must* be the first action if it is to be used at all;
447 #     in all other cases, any output from the linker during linking is
448 #     treated as a sign of an error and FAILs the test.
449 #
450 # args is an optional list of target triplets to be xfailed.
451 #
452 proc run_ld_link_tests { ldtests args } {
453     global ld
454     global as
455     global nm
456     global ar
457     global objdump
458     global READELF
459     global srcdir
460     global subdir
461     global env
462     global CC
463     global CFLAGS
464     global runtests
465     global exec_output
466     global ld_elf_shared_opt
467
468     if { [is_elf_format] && [check_shared_lib_support] } {
469         set ld_extra_opt "$ld_elf_shared_opt"
470     } else {
471         set ld_extra_opt ""
472     }
473
474     foreach testitem $ldtests {
475         set testname [lindex $testitem 0]
476
477         if ![runtest_file_p $runtests $testname] then {
478             continue
479         }
480
481         foreach target $args {
482             setup_xfail $target
483         }
484
485         set ld_options [lindex $testitem 1]
486         set ld_after [lindex $testitem 2]
487         set as_options [lindex $testitem 3]
488         set src_files  [lindex $testitem 4]
489         set actions [lindex $testitem 5]
490         set binfile tmpdir/[lindex $testitem 6]
491         set cflags [lindex $testitem 7]
492         set objfiles {}
493         set is_unresolved 0
494         set failed 0
495         set maybe_failed 0
496         set ld_output ""
497
498 #       verbose -log "Testname is $testname"
499 #       verbose -log "ld_options is $ld_options"
500 #       verbose -log "ld_after is $ld_after"
501 #       verbose -log "as_options is $as_options"
502 #       verbose -log "src_files is $src_files"
503 #       verbose -log "actions is $actions"
504 #       verbose -log "binfile is $binfile"
505
506         # Assemble each file in the test.
507         foreach src_file $src_files {
508             set fileroot "[file rootname [file tail $src_file]]"
509             set objfile "tmpdir/$fileroot.o"
510             lappend objfiles $objfile
511
512             if { [file extension $src_file] == ".c" } {
513                 set as_file "tmpdir/$fileroot.s"
514                 if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
515                     set is_unresolved 1
516                     break
517                 }
518             } else {
519                 set as_file "$srcdir/$subdir/$src_file"
520             }
521             if ![ld_assemble $as "$as_options $as_file" $objfile] {
522                 set is_unresolved 1
523                 break
524             }
525         }
526
527         # Catch assembler errors.
528         if { $is_unresolved } {
529             unresolved $testname
530             continue
531         }
532
533         if { $binfile eq "tmpdir/" } {
534             # compile only
535         } elseif { [regexp ".*\\.a$" $binfile] } {
536             if { ![ar_simple_create $ar $ld_options $binfile "$objfiles $ld_after"] } {
537                 set failed 1
538             }
539         } elseif { ![ld_link $ld $binfile "$ld_extra_opt -L$srcdir/$subdir $ld_options $objfiles $ld_after"] } {
540             set maybe_failed 1
541             set ld_output "$exec_output"
542         }
543
544         if { !$failed } {
545             foreach actionlist $actions {
546                 set action [lindex $actionlist 0]
547                 set progopts [lindex $actionlist 1]
548
549                 # There are actions where we run regexp_diff on the
550                 # output, and there are other actions (presumably).
551                 # Handling of the former look the same.
552                 set dump_prog ""
553                 switch -- $action {
554                     objdump
555                         { set dump_prog $objdump }
556                     nm
557                         { set dump_prog $nm }
558                     readelf
559                         { set dump_prog $READELF }
560                     ld
561                         { set dump_prog "ld" }
562                     default
563                         {
564                             perror "Unrecognized action $action"
565                             set is_unresolved 1
566                             break
567                         }
568                     }
569
570                 if { $action == "ld" } {
571                     set regexpfile $progopts
572                     verbose "regexpfile is $srcdir/$subdir/$regexpfile"
573                     set_file_contents "tmpdir/ld.messages" "$ld_output"
574                     verbose "ld.messages has '[file_contents tmpdir/ld.messages]'"
575                     if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$regexpfile"] } then {
576                         verbose "output is $ld_output" 2
577                         set failed 1
578                         break
579                     }
580                     set maybe_failed 0
581                 } elseif { !$maybe_failed && $dump_prog != "" } {
582                     set dumpfile [lindex $actionlist 2]
583                     set binary $dump_prog
584
585                     # Ensure consistent sorting of symbols
586                     if {[info exists env(LC_ALL)]} {
587                         set old_lc_all $env(LC_ALL)
588                     }
589                     set env(LC_ALL) "C"
590                     set cmd "$binary $progopts $binfile"
591                     set status [remote_exec host [concat sh -c [list "$cmd >dump.out 2>ld.stderr"]] "" "/dev/null"]
592                     send_log "$cmd\n"
593                     remote_upload host "ld.stderr"
594                     set comp_output [prune_warnings [file_contents "ld.stderr"]]
595                     remote_file host delete "ld.stderr"
596                     remote_file build delete "ld.stderr"
597
598                     if {[info exists old_lc_all]} {
599                         set env(LC_ALL) $old_lc_all
600                     } else {
601                         unset env(LC_ALL)
602                     }
603
604                     if ![string match "" $comp_output] then {
605                         send_log "$comp_output\n"
606                         set failed 1
607                         break
608                     }
609
610                     remote_upload host "dump.out"
611
612                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
613                         verbose "output is [file_contents "dump.out"]" 2
614                         set failed 1
615                         remote_file build delete "dump.out"
616                         remote_file host delete "dump.out"
617                         break
618                     }
619                     remote_file build delete "dump.out"
620                     remote_file host delete "dump.out"
621                 }
622             }
623         }
624
625         if { $is_unresolved } {
626             unresolved $testname
627         } elseif { $maybe_failed || $failed } {
628             fail $testname
629         } else {
630             pass $testname
631         }
632     }
633 }
634
635 # ldtests contains test-items with 3 items followed by 1 lists, 2 items
636 # and 3 optional items:
637 #   0:name
638 #   1:ld leading options, placed before object files
639 #   2:assembler options
640 #   3:filenames of source files
641 #   4:name of output file
642 #   5:expected output
643 #   6:compiler flags (optional)
644 #   7:language (optional)
645 #   8:linker warning (optional)
646 #   9:ld trailing options, placed after object files (optional)
647 # args is an optional list of target triplets to be xfailed.
648
649 proc run_ld_link_exec_tests { ldtests args } {
650     global ld
651     global as
652     global srcdir
653     global subdir
654     global env
655     global CC
656     global CXX
657     global CFLAGS
658     global CXXFLAGS
659     global errcnt
660     global exec_output
661     global board_cflags
662     global STATIC_LDFLAGS
663
664     # When using GCC as the linker driver, we need to specify board cflags when
665     # linking because cflags may contain linker options.  For example when
666     # linker options are included in GCC spec files then we need the -specs
667     # option.
668     if [board_info [target_info name] exists cflags] {
669         set board_cflags " [board_info [target_info name] cflags]"
670     } else {
671         set board_cflags ""
672     }
673
674     foreach testitem $ldtests {
675         foreach target $args {
676             setup_xfail $target
677         }
678         set testname [lindex $testitem 0]
679         set ld_options [lindex $testitem 1]
680         set as_options [lindex $testitem 2]
681         set src_files  [lindex $testitem 3]
682         set binfile tmpdir/[lindex $testitem 4]
683         set expfile [lindex $testitem 5]
684         set cflags [lindex $testitem 6]
685         set lang [lindex $testitem 7]
686         set warning [lindex $testitem 8]
687         set ld_after [lindex $testitem 9]
688         set objfiles {}
689         set failed 0
690
691         if { ![check_compiler_available] } {
692             unsupported $testname
693             continue
694         }
695
696 #       verbose -log "Testname is $testname"
697 #       verbose -log "ld_options is $ld_options"
698 #       verbose -log "as_options is $as_options"
699 #       verbose -log "src_files is $src_files"
700 #       verbose -log "binfile is $binfile"
701
702         # Assemble each file in the test.
703         foreach src_file $src_files {
704             set fileroot "[file rootname [file tail $src_file]]"
705             set objfile "tmpdir/$fileroot.o"
706             lappend objfiles $objfile
707
708             if { [ string match "c++" $lang ] } {
709                 set cmd "$CXX -c $CXXFLAGS $cflags"
710             } else {
711                 set cmd "$CC -c $CFLAGS $cflags"
712             }
713             if ![ld_compile $cmd $srcdir/$subdir/$src_file $objfile] {
714                 set failed 1
715                 break
716             }
717         }
718         if { $failed != 0 } {
719             unresolved $testname
720             continue
721         }
722
723         if { [ string match "asm" $lang ] } {
724             set link_proc ld_link
725             set link_cmd $ld
726         } elseif { [ string match "c++" $lang ] } {
727             set link_proc ld_link
728             set link_cmd $CXX
729         } else {
730             set link_proc ld_link
731             set link_cmd $CC
732         }
733
734         if { $binfile eq "tmpdir/" } {
735             # compile only
736             pass $testname
737             continue;
738         } else {
739             if { [string match "" $STATIC_LDFLAGS] \
740                  && [regexp -- ".* \[-\]+static .*" " $board_cflags $ld_options $objfiles $ld_after "] } {
741                 untested $testname
742                 continue
743             }
744             if ![$link_proc $link_cmd $binfile "$board_cflags -L$srcdir/$subdir $ld_options $objfiles $ld_after"] {
745                 set failed 1
746             }
747         }
748
749         # Check if exec_output is expected.
750         if { $warning != "" } then {
751             verbose -log "returned with: <$exec_output>, expected: <$warning>"
752             if { [regexp $warning $exec_output] } then {
753                 set failed 0
754             } else {
755                 set failed 1
756             }
757         }
758
759         if { $failed == 0 && [isnative] } {
760             send_log "Running: $binfile > $binfile.out\n"
761             verbose "Running: $binfile > $binfile.out"
762             catch "exec $binfile > $binfile.out" exec_output
763
764             if ![string match "" $exec_output] then {
765                 send_log "$exec_output\n"
766                 verbose "$exec_output" 1
767                 set failed 1
768             } else {
769                 send_log "diff $binfile.out $srcdir/$subdir/$expfile\n"
770                 verbose "diff $binfile.out $srcdir/$subdir/$expfile"
771                 catch "exec diff $binfile.out $srcdir/$subdir/$expfile" exec_output
772                 set exec_output [prune_warnings $exec_output]
773
774                 if ![string match "" $exec_output] then {
775                     send_log "$exec_output\n"
776                     verbose "$exec_output" 1
777                     set failed 1
778                 }
779             }
780         }
781
782         if { $failed != 0 } {
783             fail $testname
784         } elseif ![isnative] {
785             unsupported $testname
786         } else {
787             set errcnt 0
788             pass $testname
789         }
790     }
791 }
792
793 # List contains test-items with 3 items followed by 2 lists, one item and
794 # one optional item:
795 #  0:name
796 #  1:ld or ar options
797 #  2:compile options
798 #  3:filenames of source files
799 #  4:action and options.
800 #  5:name of output file
801 #  6:language (optional)
802 #
803 # Actions:
804 # objdump: Apply objdump options on result.  Compare with regex (last arg).
805 # nm: Apply nm options on result.  Compare with regex (last arg).
806 # readelf: Apply readelf options on result.  Compare with regex (last arg).
807 # warning: Check linker output against regex (last arg).
808 # error: Like 'warning' but checking output in error case.
809 # warning_output: Check linker output against regex in a file (last arg).
810 # error_output: Like 'warning_output' but checking output in error case.
811 #
812 proc run_cc_link_tests { ldtests } {
813     global nm
814     global objdump
815     global READELF
816     global srcdir
817     global subdir
818     global env
819     global CC
820     global CXX
821     global CFLAGS
822     global CXXFLAGS
823     global ar
824     global exec_output
825     global board_cflags
826     global STATIC_LDFLAGS
827
828     if [board_info [target_info name] exists cflags] {
829         set board_cflags " [board_info [target_info name] cflags]"
830     } else {
831         set board_cflags ""
832     }
833
834     foreach testitem $ldtests {
835         set testname [lindex $testitem 0]
836         set ldflags [lindex $testitem 1]
837         set cflags [lindex $testitem 2]
838         set src_files  [lindex $testitem 3]
839         set actions [lindex $testitem 4]
840         set binfile tmpdir/[lindex $testitem 5]
841         set lang [lindex $testitem 6]
842         set objfiles {}
843         set is_unresolved 0
844         set failed 0
845         set check_ld(terminal) 0
846         set check_ld(source) ""
847
848         if { ![check_compiler_available] } {
849             unsupported $testname
850             continue
851         }
852
853         #verbose -log "testname  is $testname"
854         #verbose -log "ldflags   is $ldflags"
855         #verbose -log "cflags    is $cflags"
856         #verbose -log "src_files is $src_files"
857         #verbose -log "actions   is $actions"
858         #verbose -log "binfile   is $binfile"
859         #verbose -log "lang      is $lang"
860
861         foreach actionlist $actions {
862             set action [lindex $actionlist 0]
863             set progopts [lindex $actionlist 1]
864
865             # Find actions related to error/warning processing.
866             switch -- $action {
867                 error
868                 {
869                     set check_ld(source) "regexp"
870                     set check_ld(regexp) $progopts
871                     set check_ld(terminal) 1
872                 }
873                 warning
874                 {
875                     set check_ld(source) "regexp"
876                     set check_ld(regexp) $progopts
877                 }
878                 error_output
879                 {
880                     set check_ld(source) "file"
881                     set check_ld(file) $progopts
882                     set check_ld(terminal) 1
883                 }
884                 warning_output
885                 {
886                     set check_ld(source) "file"
887                     set check_ld(file) $progopts
888                 }
889             }
890         }
891
892         # Compile each file in the test.
893         foreach src_file $src_files {
894             set fileroot "[file rootname [file tail $src_file]]"
895             set objfile "tmpdir/$fileroot.o"
896             lappend objfiles $objfile
897
898             if { [ string match "c++" $lang ] } {
899                 set cmd "$CXX -c $CXXFLAGS $cflags"
900             } else {
901                 set cmd "$CC -c $CFLAGS $cflags"
902             }
903             if ![ld_compile $cmd $srcdir/$subdir/$src_file $objfile] {
904                 set failed 1
905                 break
906             }
907         }
908         if { $failed != 0 } {
909             unresolved $testname
910             continue
911         }
912
913         # Clear error and warning counts.
914         reset_vars
915
916         if { [ string match "c++" $lang ] } {
917             set cc_cmd $CXX
918         } else {
919             set cc_cmd $CC
920         }
921
922         if { $binfile eq "tmpdir/" } {
923             # compile only
924         } elseif { [regexp ".*\\.a$" $binfile] } {
925             if { ![ar_simple_create $ar $ldflags $binfile "$objfiles"] } {
926                 set failed 1
927             }
928         } else {
929             if { [string match "" $STATIC_LDFLAGS] \
930                  && [regexp -- ".* \[-\]+static .*" " $board_cflags $ldflags $objfiles "] } {
931                 untested $testname
932                 continue
933             }
934             ld_link $cc_cmd $binfile "$board_cflags -L$srcdir/$subdir $ldflags $objfiles"
935             set ld_output "$exec_output"
936
937             if { $check_ld(source) == "regexp" } then {
938                 # Match output against regexp argument.
939                 verbose -log "returned with: <$ld_output>, expected: <$check_ld(regexp)>"
940                 if { ![regexp $check_ld(regexp) $ld_output] } then {
941                     set failed 1
942                 }
943             } elseif { $check_ld(source) == "file" } then {
944                 # Match output against patterns in a file.
945                 set_file_contents "tmpdir/ld.messages" "$ld_output"
946                 verbose "ld.messages has '[file_contents tmpdir/ld.messages]'"
947                 if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$check_ld(file)"] } then {
948                     verbose "output is $ld_output" 2
949                     set failed 1
950                 }
951             }
952
953             if { $check_ld(source) != "" } then {
954                 if { $ld_output == "" } then {
955                     verbose -log "Linker was expected to give error or warning"
956                     set failed 1
957                 }
958             } else {
959                 if { $ld_output != "" } then {
960                     verbose -log "Unexpected linker warning or error"
961                     set failed 1
962                 }
963             }
964         }
965
966         if { $failed == 0 } {
967             foreach actionlist $actions {
968                 set action [lindex $actionlist 0]
969                 set progopts [lindex $actionlist 1]
970
971                 # There are actions where we run regexp_diff on the
972                 # output, and there are other actions (presumably).
973                 # Handling of the former look the same.
974                 set dump_prog ""
975                 switch -- $action {
976                     objdump
977                         { set dump_prog $objdump }
978                     nm
979                         { set dump_prog $nm }
980                     readelf
981                         { set dump_prog $READELF }
982                     error {}
983                     warning {}
984                     error_output {}
985                     warning_output {}
986                     default
987                         {
988                             perror "Unrecognized action $action"
989                             set is_unresolved 1
990                             break
991                         }
992                     }
993
994                 if { $dump_prog != "" } {
995                     set dumpfile [lindex $actionlist 2]
996                     set binary $dump_prog
997
998                     # Ensure consistent sorting of symbols
999                     if {[info exists env(LC_ALL)]} {
1000                         set old_lc_all $env(LC_ALL)
1001                     }
1002                     set env(LC_ALL) "C"
1003                     set cmd "$binary $progopts $binfile > dump.out"
1004                     send_log "$cmd\n"
1005                     catch "exec $cmd" comp_output
1006                     if {[info exists old_lc_all]} {
1007                         set env(LC_ALL) $old_lc_all
1008                     } else {
1009                         unset env(LC_ALL)
1010                     }
1011                     set comp_output [prune_warnings $comp_output]
1012
1013                     if ![string match "" $comp_output] then {
1014                         send_log "$comp_output\n"
1015                         set failed 1
1016                         break
1017                     }
1018
1019                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1020                         verbose "output is [file_contents "dump.out"]" 2
1021                         set failed 1
1022                         break
1023                     }
1024                 }
1025             }
1026         }
1027
1028         if { $failed } {
1029             fail $testname
1030         } elseif { $is_unresolved } {
1031             unresolved $testname
1032         } else {
1033             pass $testname
1034         }
1035     }
1036 }
1037
1038 # Returns true if --gc-sections is supported on the target.
1039
1040 proc check_gc_sections_available { } {
1041     global gc_sections_available_saved
1042     global ld
1043
1044     if {![info exists gc_sections_available_saved]} {
1045         # Some targets don't support gc-sections despite whatever's
1046         # advertised by ld's options.
1047         if {   [istarget alpha-*-*]
1048             || [istarget d30v-*-*]
1049             || [istarget dlx-*-*]
1050             || [istarget hppa*64-*-*]
1051             || [istarget ia64-*-*]
1052             || [istarget mep-*-*]
1053             || [istarget mn10200-*-*]
1054             || [istarget pj*-*-*]
1055             || [istarget pru*-*-*]
1056             || [istarget s12z-*-*]
1057             || [istarget xgate-*-*] } {
1058             set gc_sections_available_saved 0
1059             return 0
1060         }
1061
1062         # elf2flt uses -q (--emit-relocs), which is incompatible with
1063         # --gc-sections.
1064         if { [board_info target exists ldflags]
1065              && [regexp " -elf2flt\[ =\]" " [board_info target ldflags] "] } {
1066             set gc_sections_available_saved 0
1067             return 0
1068         }
1069
1070         # Check if the ld used by gcc supports --gc-sections.
1071         # FIXME: this test is useless since ld --help always says
1072         # --gc-sections is available
1073         set ld_output [remote_exec host $ld "--help"]
1074         if { [ string first "--gc-sections" $ld_output ] >= 0 } {
1075             set gc_sections_available_saved 1
1076         } else {
1077             set gc_sections_available_saved 0
1078         }
1079     }
1080     return $gc_sections_available_saved
1081 }
1082
1083 # Return true if target uses genelf.em (assuming it is ELF).
1084 proc is_generic_elf { } {
1085     if { [istarget "d30v-*-*"]
1086          || [istarget "dlx-*-*"]
1087          || [istarget "fr30-*-*"]
1088          || ([istarget "frv-*-*"] && ![istarget "frv-*-linux*"])
1089          || [istarget "ft32-*-*"]
1090          || [istarget "iq2000-*-*"]
1091          || [istarget "mn10200-*-*"]
1092          || [istarget "moxie-*-*"]
1093          || [istarget "msp430-*-*"]
1094          || [istarget "mt-*-*"]
1095          || [istarget "pj*-*-*"]
1096          || [istarget "xgate-*-*"] } {
1097         return 1;
1098     }
1099     return 0;
1100 }
1101
1102 proc is_underscore_target { } {
1103     global is_underscore_target_saved
1104     global target_triplet
1105     global srcdir
1106
1107     if { ![info exists is_underscore_target_saved] } {
1108         set cmd "targ=$target_triplet . $srcdir/../../bfd/config.bfd &&"
1109         append cmd { echo "$targ_underscore"}
1110         verbose -log "$cmd"
1111         set status [catch {exec sh -c $cmd} result]
1112         if { $status == 0 && [string match "yes" $result] } {
1113             set is_underscore_target_saved 1
1114         } else {
1115             set is_underscore_target_saved 0
1116         }
1117     }
1118     return $is_underscore_target_saved
1119 }
1120
1121 # Returns true if the target ld supports the plugin API.
1122 proc check_plugin_api_available { } {
1123     global plugin_api_available_saved
1124     global ld
1125     if {![info exists plugin_api_available_saved]} {
1126         # Check if the ld used by gcc supports --plugin.
1127         set ld_output [remote_exec host $ld "--help"]
1128         if { [ string first "-plugin PLUGIN" $ld_output ] >= 0 } {
1129             set plugin_api_available_saved 1
1130         } else {
1131             set plugin_api_available_saved 0
1132         }
1133     }
1134     return $plugin_api_available_saved
1135 }
1136
1137 # Sets ld_sysroot to the current sysroot (empty if not supported) and
1138 # returns true if the target ld supports sysroot.
1139 proc check_sysroot_available { } {
1140     global ld_sysroot_available_saved ld ld_sysroot
1141     if {![info exists ld_sysroot_available_saved]} {
1142         # Check if ld supports --sysroot *other* than empty.
1143         set ld_sysroot [string trimright [lindex [remote_exec host $ld "--print-sysroot"] 1]]
1144         if { $ld_sysroot == "" } {
1145             set ld_sysroot_available_saved 0
1146         } else {
1147             set ld_sysroot_available_saved 1
1148         }
1149     }
1150     return $ld_sysroot_available_saved
1151 }
1152
1153 # Return true if we can build a program with the compiler.
1154 # On some targets, CC might be defined, but libraries and startup
1155 # code might be missing or require special options that the ld test
1156 # harness doesn't know about.
1157
1158 proc check_compiler_available { } {
1159     global compiler_available_saved
1160     global CC
1161
1162     if {![info exists compiler_available_saved]} {
1163         if { [which $CC] == 0 } {
1164             set compiler_available_saved 0
1165             return 0
1166         }
1167
1168         set flags ""
1169         if [board_info [target_info name] exists cflags] {
1170             append flags " [board_info [target_info name] cflags]"
1171         }
1172         if [board_info [target_info name] exists ldflags] {
1173             append flags " [board_info [target_info name] ldflags]"
1174         }
1175
1176         set basename "tmpdir/compiler[pid]"
1177         set src ${basename}.c
1178         set output ${basename}.out
1179         set f [open $src "w"]
1180         puts $f "int main (void)"
1181         puts $f "{"
1182         puts $f "  return 0; "
1183         puts $f "}"
1184         close $f
1185         if [is_remote host] {
1186             set src [remote_download host $src]
1187         }
1188         set compiler_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
1189         remote_file host delete $src
1190         remote_file host delete $output
1191         file delete $src
1192     }
1193     return $compiler_available_saved
1194 }
1195
1196 # Returns 1 if plugin is enabled in gcc.  Returns 0 otherwise.
1197 proc check_gcc_plugin_enabled { } {
1198     global CC
1199
1200     if {![info exists CC]} {
1201         set CC [find_gcc]
1202     }
1203     if { $CC == ""} {
1204         return 0
1205     }
1206     set state [remote_exec host $CC -v]
1207     if { [lindex $state 0] != 0 } {
1208         return 0;
1209     }
1210     for { set i 1 } { $i < [llength $state] } { incr i } {
1211         set v [lindex $state $i]
1212         if { [ string match "*--disable-plugin*" $v ] } {
1213             verbose "plugin is disabled by $v"
1214             return 0;
1215         }
1216     }
1217
1218     return 1;
1219 }
1220
1221 # Returns true if the target compiler supports LTO
1222 proc check_lto_available { } {
1223     global lto_available_saved
1224     global CC
1225
1226     if {![info exists lto_available_saved]} {
1227         if { ![check_gcc_plugin_enabled] } {
1228             set lto_available_saved 0
1229             return 0
1230         }
1231         # This test will hide LTO bugs in ld.  Since GCC 4.9 adds
1232         # -ffat-lto-objects, we always run LTO tests on Linux with
1233         # GCC 4.9 or newer.
1234         if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
1235             set lto_available_saved 1
1236             return 1
1237         }
1238         # Check if gcc supports -flto -fuse-linker-plugin
1239         set flags ""
1240         if [board_info [target_info name] exists cflags] {
1241             append flags " [board_info [target_info name] cflags]"
1242         }
1243         if [board_info [target_info name] exists ldflags] {
1244             append flags " [board_info [target_info name] ldflags]"
1245         }
1246
1247         set basename "tmpdir/lto[pid]"
1248         set src ${basename}.c
1249         set output ${basename}.out
1250         set f [open $src "w"]
1251         puts $f "int main() { return 0; }"
1252         close $f
1253         if [is_remote host] {
1254             set src [remote_download host $src]
1255         }
1256         set lto_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -fuse-linker-plugin $src -o $output"]
1257         remote_file host delete $src
1258         remote_file host delete $output
1259         file delete $src
1260     }
1261     return $lto_available_saved
1262 }
1263
1264 # Returns true if the target compiler supports LTO  -ffat-lto-objects
1265 proc check_lto_fat_available { } {
1266     global lto_fat_available_saved
1267     global CC
1268
1269     if {![info exists lto_fat_available_saved]} {
1270         if { ![check_gcc_plugin_enabled] } {
1271             set lto_fat_available_saved 0
1272             return 0
1273         }
1274         # This test will hide LTO bugs in ld.  Since GCC 4.9 adds
1275         # -ffat-lto-objects, we always run LTO tests on Linux with
1276         # GCC 4.9 or newer.
1277         if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
1278             set lto_fat_available_saved 1
1279             return 1
1280         }
1281         # Check if gcc supports -flto -fuse-linker-plugin
1282         set flags ""
1283         if [board_info [target_info name] exists cflags] {
1284             append flags " [board_info [target_info name] cflags]"
1285         }
1286         if [board_info [target_info name] exists ldflags] {
1287             append flags " [board_info [target_info name] ldflags]"
1288         }
1289
1290         set basename "tmpdir/lto[pid]"
1291         set src ${basename}.c
1292         set output ${basename}.out
1293         set f [open $src "w"]
1294         puts $f "int main() { return 0; }"
1295         close $f
1296         if [is_remote host] {
1297             set src [remote_download host $src]
1298         }
1299         set lto_fat_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -ffat-lto-objects -fuse-linker-plugin $src -o $output"]
1300         remote_file host delete $src
1301         remote_file host delete $output
1302         file delete $src
1303     }
1304     return $lto_fat_available_saved
1305 }
1306
1307 # Returns true if the target compiler supports LTO and -shared
1308 proc check_lto_shared_available { } {
1309     global lto_shared_available_saved
1310     global CC
1311
1312     if {![info exists lto_shared_available_saved]} {
1313         if { ![check_gcc_plugin_enabled] } {
1314             set lto_shared_available_saved 0
1315             return 0
1316         }
1317         # This test will hide LTO bugs in ld.  Since GCC 4.9 adds
1318         # -ffat-lto-objects, we always run LTO tests on Linux with
1319         # GCC 4.9 or newer.
1320         if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
1321             set lto_shared_available_saved 1
1322             return 1
1323         }
1324         # Check if gcc supports -flto -fuse-linker-plugin -shared
1325         set flags ""
1326         if [board_info [target_info name] exists cflags] {
1327             append flags " [board_info [target_info name] cflags]"
1328         }
1329         if [board_info [target_info name] exists ldflags] {
1330             append flags " [board_info [target_info name] ldflags]"
1331         }
1332
1333         set basename "tmpdir/lto_shared[pid]"
1334         set src ${basename}.c
1335         set output ${basename}.so
1336         set f [open $src "w"]
1337         puts $f ""
1338         close $f
1339         if [is_remote host] {
1340             set src [remote_download host $src]
1341         }
1342         set lto_shared_available_saved [run_host_cmd_yesno "$CC" "$flags -shared -fPIC -flto -fuse-linker-plugin $src -o $output"]
1343         remote_file host delete $src
1344         remote_file host delete $output
1345         file delete $src
1346     }
1347     return $lto_shared_available_saved
1348 }
1349
1350 # Check if the assembler supports CFI statements.
1351
1352 proc check_as_cfi { } {
1353     global check_as_cfi_result
1354     global as
1355     if [info exists check_as_cfi_result] {
1356         return $check_as_cfi_result
1357     }
1358     set as_file "tmpdir/check_as_cfi.s"
1359     set as_fh [open $as_file w 0666]
1360     puts $as_fh "# Generated file. DO NOT EDIT"
1361     puts $as_fh "\t.cfi_startproc"
1362     puts $as_fh "\t.cfi_endproc"
1363     close $as_fh
1364     remote_download host $as_file
1365     verbose -log "Checking CFI support:"
1366     rename "perror" "check_as_cfi_perror"
1367     proc perror { args } { }
1368     set success [ld_assemble $as $as_file "/dev/null"]
1369     rename "perror" ""
1370     rename "check_as_cfi_perror" "perror"
1371     #remote_file host delete $as_file
1372     set check_as_cfi_result $success
1373     return $success
1374 }
1375
1376 # Returns true if IFUNC works.
1377
1378 proc check_ifunc_available { } {
1379     global ifunc_available_saved
1380     global CC
1381
1382     if {![info exists ifunc_available_saved]} {
1383         if { ![check_compiler_available] } {
1384             set ifunc_available_saved 0
1385             return 0
1386         }
1387         # Check if gcc supports -flto -fuse-linker-plugin
1388         set flags ""
1389         if [board_info [target_info name] exists cflags] {
1390             append flags " [board_info [target_info name] cflags]"
1391         }
1392         if [board_info [target_info name] exists ldflags] {
1393             append flags " [board_info [target_info name] ldflags]"
1394         }
1395
1396         set basename "tmpdir/ifunc[pid]"
1397         set src ${basename}.c
1398         set output ${basename}.out
1399         set f [open $src "w"]
1400         puts $f "extern int library_func2 (void);"
1401         puts $f "int main (void)"
1402         puts $f "{"
1403         puts $f "  if (library_func2 () != 2) __builtin_abort ();"
1404         puts $f "  return 0; "
1405         puts $f "}"
1406         puts $f "static int library_func1 (void) {return 2; }"
1407         puts $f "void *foo (void) __asm__ (\"library_func2\");"
1408         puts $f "void *foo (void) { return library_func1; }"
1409         puts $f "__asm__(\".type library_func2, %gnu_indirect_function\");"
1410         close $f
1411         if [is_remote host] {
1412             set src [remote_download host $src]
1413         }
1414         set ifunc_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
1415         if { [isnative] && $ifunc_available_saved == 1 } {
1416           set ifunc_available_saved [run_host_cmd_yesno "$output" ""]
1417         }
1418         remote_file host delete $src
1419         remote_file host delete $output
1420         file delete $src
1421     }
1422     return $ifunc_available_saved
1423 }
1424
1425 # Returns true if ifunc attribute works.
1426
1427 proc check_ifunc_attribute_available { } {
1428     global ifunc_attribute_available_saved
1429     global CC
1430
1431     if {![info exists ifunc_attribute_available_saved]} {
1432         if { ![check_compiler_available] } {
1433             set ifunc_attribute_available_saved 0
1434             return 0
1435         }
1436         # Check if gcc supports -flto -fuse-linker-plugin
1437         set flags ""
1438         if [board_info [target_info name] exists cflags] {
1439             append flags " [board_info [target_info name] cflags]"
1440         }
1441         if [board_info [target_info name] exists ldflags] {
1442             append flags " [board_info [target_info name] ldflags]"
1443         }
1444
1445         set basename "tmpdir/ifunc[pid]"
1446         set src ${basename}.c
1447         set output ${basename}.out
1448         set f [open $src "w"]
1449         puts $f "extern int library_func2 (void) __attribute__ ((ifunc (\"foo\")));"
1450         puts $f "int main (void)"
1451         puts $f "{"
1452         puts $f "  if (library_func2 () != 2) __builtin_abort ();"
1453         puts $f "  return 0; "
1454         puts $f "}"
1455         puts $f "static int library_func1 (void) {return 2; }"
1456         puts $f "void *foo (void) { return library_func1; }"
1457         close $f
1458         if [is_remote host] {
1459             set src [remote_download host $src]
1460         }
1461         set ifunc_attribute_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
1462         if { [isnative] && $ifunc_attribute_available_saved == 1 } {
1463           set ifunc_attribute_available_saved [run_host_cmd_yesno "$output" ""]
1464         }
1465         remote_file host delete $src
1466         remote_file host delete $output
1467         file delete $src
1468     }
1469     return $ifunc_attribute_available_saved
1470 }
1471
1472 # Return true if libdl is supported.
1473
1474 proc check_libdl_available { } {
1475     global libdl_available_saved
1476     global CC
1477
1478     if {![info exists libdl_available_saved]} {
1479         if { ![check_compiler_available] } {
1480             set libdl_available_saved 0
1481             return 0
1482         }
1483
1484         set basename "tmpdir/dl_avail_test[pid]"
1485         set src ${basename}.c
1486         set output ${basename}.out
1487         set f [open $src "w"]
1488         # Sample test file.
1489         puts $f "#include <dlfcn.h>"
1490         puts $f "int main (void)"
1491         puts $f "{"
1492         puts $f "  dlopen (\"dummy.so\", RTLD_NOW);"
1493         puts $f "  return 0; "
1494         puts $f "}"
1495         close $f
1496         if [is_remote host] {
1497             set src [remote_download host $src]
1498         }
1499         set libdl_available_saved [run_host_cmd_yesno "$CC" "$src -o $output -ldl"]
1500         remote_file host delete $src
1501         remote_file host delete $output
1502         file delete $src
1503     }
1504     return $libdl_available_saved
1505 }
1506
1507 # Returns true if GNU2 TLS works.
1508
1509 proc check_gnu2_tls_available { } {
1510     global gnu2_tls_available_saved
1511     global CC
1512     global GNU2_CFLAGS
1513
1514     if {![info exists gnu2_tls_available_saved]} {
1515         if { ![check_compiler_available] || "$GNU2_CFLAGS" == "" } {
1516             set gnu2_tls_available_saved 0
1517             return 0
1518         }
1519         # Check if GNU2 TLS works.
1520         set flags "$GNU2_CFLAGS"
1521         if [board_info [target_info name] exists cflags] {
1522             append flags " [board_info [target_info name] cflags]"
1523         }
1524         if [board_info [target_info name] exists ldflags] {
1525             append flags " [board_info [target_info name] ldflags]"
1526         }
1527
1528         set basename "tmpdir/gnu2_tls[pid]"
1529         set src1 ${basename}1.c
1530         set output1 ${basename}.so
1531         set f [open $src1 "w"]
1532         puts $f "extern __thread int zzz;"
1533         puts $f "int foo (void)"
1534         puts $f "{"
1535         puts $f "  return zzz;"
1536         puts $f "}"
1537         close $f
1538         if [is_remote host] {
1539             set src1 [remote_download host $src1]
1540         }
1541         set src2 ${basename}2.c
1542         set output2 ${basename}.exe
1543         set f [open $src2 "w"]
1544         puts $f "__thread int zzz = 20;"
1545         puts $f "extern int foo (void);"
1546         puts $f "int main (void)"
1547         puts $f "{"
1548         puts $f "  if (foo () != 20) __builtin_abort ();"
1549         puts $f "  return 0; "
1550         puts $f "}"
1551         close $f
1552         if [is_remote host] {
1553             set src2 [remote_download host $src2]
1554         }
1555         set gnu2_tls_available_saved [run_host_cmd_yesno "$CC" "-fPIC -shared $flags $src1 -o $output1"]
1556         if { $gnu2_tls_available_saved == 1 } {
1557             set gnu2_tls_available_saved [run_host_cmd_yesno "$CC" "$flags $src2 $output1 -o $output2"]
1558             if { $gnu2_tls_available_saved == 1 } {
1559                 set gnu2_tls_available_saved [run_host_cmd_yesno "$output2" ""]
1560             }
1561         }
1562         remote_file host delete $src1
1563         remote_file host delete $output1
1564         remote_file host delete $src2
1565         remote_file host delete $output2
1566         file delete $src1 $src2
1567     }
1568     return $gnu2_tls_available_saved
1569 }