dc55dc803439d6742e0441458b509eaf5a13512c
[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 #       verbose -log "Testname is $testname"
692 #       verbose -log "ld_options is $ld_options"
693 #       verbose -log "as_options is $as_options"
694 #       verbose -log "src_files is $src_files"
695 #       verbose -log "binfile is $binfile"
696
697         # Assemble each file in the test.
698         foreach src_file $src_files {
699             set fileroot "[file rootname [file tail $src_file]]"
700             set objfile "tmpdir/$fileroot.o"
701             lappend objfiles $objfile
702
703             if { [ string match "c++" $lang ] } {
704                 set cmd "$CXX -c $CXXFLAGS $cflags"
705             } else {
706                 set cmd "$CC -c $CFLAGS $cflags"
707             }
708             if ![ld_compile $cmd $srcdir/$subdir/$src_file $objfile] {
709                 set failed 1
710                 break
711             }
712         }
713         if { $failed != 0 } {
714             unresolved $testname
715             continue
716         }
717
718         if { [ string match "asm" $lang ] } {
719             set link_proc ld_link
720             set link_cmd $ld
721         } elseif { [ string match "c++" $lang ] } {
722             set link_proc ld_link
723             set link_cmd $CXX
724         } else {
725             set link_proc ld_link
726             set link_cmd $CC
727         }
728
729         if { $binfile eq "tmpdir/" } {
730             # compile only
731             pass $testname
732             continue;
733         } else {
734             if { [string match "" $STATIC_LDFLAGS] \
735                  && [regexp -- ".* \[-\]+static .*" " $board_cflags $ld_options $objfiles $ld_after "] } {
736                 untested $testname
737                 continue
738             }
739             if ![$link_proc $link_cmd $binfile "$board_cflags -L$srcdir/$subdir $ld_options $objfiles $ld_after"] {
740                 set failed 1
741             }
742         }
743
744         # Check if exec_output is expected.
745         if { $warning != "" } then {
746             verbose -log "returned with: <$exec_output>, expected: <$warning>"
747             if { [regexp $warning $exec_output] } then {
748                 set failed 0
749             } else {
750                 set failed 1
751             }
752         }
753
754         if { $failed == 0 && [isnative] } {
755             send_log "Running: $binfile > $binfile.out\n"
756             verbose "Running: $binfile > $binfile.out"
757             catch "exec $binfile > $binfile.out" exec_output
758
759             if ![string match "" $exec_output] then {
760                 send_log "$exec_output\n"
761                 verbose "$exec_output" 1
762                 set failed 1
763             } else {
764                 send_log "diff $binfile.out $srcdir/$subdir/$expfile\n"
765                 verbose "diff $binfile.out $srcdir/$subdir/$expfile"
766                 catch "exec diff $binfile.out $srcdir/$subdir/$expfile" exec_output
767                 set exec_output [prune_warnings $exec_output]
768
769                 if ![string match "" $exec_output] then {
770                     send_log "$exec_output\n"
771                     verbose "$exec_output" 1
772                     set failed 1
773                 }
774             }
775         }
776
777         if { $failed != 0 } {
778             fail $testname
779         } elseif ![isnative] {
780             unsupported $testname
781         } else {
782             set errcnt 0
783             pass $testname
784         }
785     }
786 }
787
788 # List contains test-items with 3 items followed by 2 lists, one item and
789 # one optional item:
790 #  0:name
791 #  1:ld or ar options
792 #  2:compile options
793 #  3:filenames of source files
794 #  4:action and options.
795 #  5:name of output file
796 #  6:language (optional)
797 #
798 # Actions:
799 # objdump: Apply objdump options on result.  Compare with regex (last arg).
800 # nm: Apply nm options on result.  Compare with regex (last arg).
801 # readelf: Apply readelf options on result.  Compare with regex (last arg).
802 # warning: Check linker output against regex (last arg).
803 # error: Like 'warning' but checking output in error case.
804 # warning_output: Check linker output against regex in a file (last arg).
805 # error_output: Like 'warning_output' but checking output in error case.
806 #
807 proc run_cc_link_tests { ldtests } {
808     global nm
809     global objdump
810     global READELF
811     global srcdir
812     global subdir
813     global env
814     global CC
815     global CXX
816     global CFLAGS
817     global CXXFLAGS
818     global ar
819     global exec_output
820     global board_cflags
821     global STATIC_LDFLAGS
822
823     if [board_info [target_info name] exists cflags] {
824         set board_cflags " [board_info [target_info name] cflags]"
825     } else {
826         set board_cflags ""
827     }
828
829     foreach testitem $ldtests {
830         set testname [lindex $testitem 0]
831         set ldflags [lindex $testitem 1]
832         set cflags [lindex $testitem 2]
833         set src_files  [lindex $testitem 3]
834         set actions [lindex $testitem 4]
835         set binfile tmpdir/[lindex $testitem 5]
836         set lang [lindex $testitem 6]
837         set objfiles {}
838         set is_unresolved 0
839         set failed 0
840         set check_ld(terminal) 0
841         set check_ld(source) ""
842
843         #verbose -log "testname  is $testname"
844         #verbose -log "ldflags   is $ldflags"
845         #verbose -log "cflags    is $cflags"
846         #verbose -log "src_files is $src_files"
847         #verbose -log "actions   is $actions"
848         #verbose -log "binfile   is $binfile"
849         #verbose -log "lang      is $lang"
850
851         foreach actionlist $actions {
852             set action [lindex $actionlist 0]
853             set progopts [lindex $actionlist 1]
854
855             # Find actions related to error/warning processing.
856             switch -- $action {
857                 error
858                 {
859                     set check_ld(source) "regexp"
860                     set check_ld(regexp) $progopts
861                     set check_ld(terminal) 1
862                 }
863                 warning
864                 {
865                     set check_ld(source) "regexp"
866                     set check_ld(regexp) $progopts
867                 }
868                 error_output
869                 {
870                     set check_ld(source) "file"
871                     set check_ld(file) $progopts
872                     set check_ld(terminal) 1
873                 }
874                 warning_output
875                 {
876                     set check_ld(source) "file"
877                     set check_ld(file) $progopts
878                 }
879             }
880         }
881
882         # Compile each file in the test.
883         foreach src_file $src_files {
884             set fileroot "[file rootname [file tail $src_file]]"
885             set objfile "tmpdir/$fileroot.o"
886             lappend objfiles $objfile
887
888             if { [ string match "c++" $lang ] } {
889                 set cmd "$CXX -c $CXXFLAGS $cflags"
890             } else {
891                 set cmd "$CC -c $CFLAGS $cflags"
892             }
893             if ![ld_compile $cmd $srcdir/$subdir/$src_file $objfile] {
894                 set failed 1
895                 break
896             }
897         }
898         if { $failed != 0 } {
899             unresolved $testname
900             continue
901         }
902
903         # Clear error and warning counts.
904         reset_vars
905
906         if { [ string match "c++" $lang ] } {
907             set cc_cmd $CXX
908         } else {
909             set cc_cmd $CC
910         }
911
912         if { $binfile eq "tmpdir/" } {
913             # compile only
914         } elseif { [regexp ".*\\.a$" $binfile] } {
915             if { ![ar_simple_create $ar $ldflags $binfile "$objfiles"] } {
916                 set failed 1
917             }
918         } else {
919             if { [string match "" $STATIC_LDFLAGS] \
920                  && [regexp -- ".* \[-\]+static .*" " $board_cflags $ldflags $objfiles "] } {
921                 untested $testname
922                 continue
923             }
924             ld_link $cc_cmd $binfile "$board_cflags -L$srcdir/$subdir $ldflags $objfiles"
925             set ld_output "$exec_output"
926
927             if { $check_ld(source) == "regexp" } then {
928                 # Match output against regexp argument.
929                 verbose -log "returned with: <$ld_output>, expected: <$check_ld(regexp)>"
930                 if { ![regexp $check_ld(regexp) $ld_output] } then {
931                     set failed 1
932                 }
933             } elseif { $check_ld(source) == "file" } then {
934                 # Match output against patterns in a file.
935                 set_file_contents "tmpdir/ld.messages" "$ld_output"
936                 verbose "ld.messages has '[file_contents tmpdir/ld.messages]'"
937                 if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$check_ld(file)"] } then {
938                     verbose "output is $ld_output" 2
939                     set failed 1
940                 }
941             }
942
943             if { $check_ld(source) != "" } then {
944                 if { $ld_output == "" } then {
945                     verbose -log "Linker was expected to give error or warning"
946                     set failed 1
947                 }
948             } else {
949                 if { $ld_output != "" } then {
950                     verbose -log "Unexpected linker warning or error"
951                     set failed 1
952                 }
953             }
954         }
955
956         if { $failed == 0 } {
957             foreach actionlist $actions {
958                 set action [lindex $actionlist 0]
959                 set progopts [lindex $actionlist 1]
960
961                 # There are actions where we run regexp_diff on the
962                 # output, and there are other actions (presumably).
963                 # Handling of the former look the same.
964                 set dump_prog ""
965                 switch -- $action {
966                     objdump
967                         { set dump_prog $objdump }
968                     nm
969                         { set dump_prog $nm }
970                     readelf
971                         { set dump_prog $READELF }
972                     error {}
973                     warning {}
974                     error_output {}
975                     warning_output {}
976                     default
977                         {
978                             perror "Unrecognized action $action"
979                             set is_unresolved 1
980                             break
981                         }
982                     }
983
984                 if { $dump_prog != "" } {
985                     set dumpfile [lindex $actionlist 2]
986                     set binary $dump_prog
987
988                     # Ensure consistent sorting of symbols
989                     if {[info exists env(LC_ALL)]} {
990                         set old_lc_all $env(LC_ALL)
991                     }
992                     set env(LC_ALL) "C"
993                     set cmd "$binary $progopts $binfile > dump.out"
994                     send_log "$cmd\n"
995                     catch "exec $cmd" comp_output
996                     if {[info exists old_lc_all]} {
997                         set env(LC_ALL) $old_lc_all
998                     } else {
999                         unset env(LC_ALL)
1000                     }
1001                     set comp_output [prune_warnings $comp_output]
1002
1003                     if ![string match "" $comp_output] then {
1004                         send_log "$comp_output\n"
1005                         set failed 1
1006                         break
1007                     }
1008
1009                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1010                         verbose "output is [file_contents "dump.out"]" 2
1011                         set failed 1
1012                         break
1013                     }
1014                 }
1015             }
1016         }
1017
1018         if { $failed } {
1019             fail $testname
1020         } elseif { $is_unresolved } {
1021             unresolved $testname
1022         } else {
1023             pass $testname
1024         }
1025     }
1026 }
1027
1028 # Returns true if --gc-sections is supported on the target.
1029
1030 proc check_gc_sections_available { } {
1031     global gc_sections_available_saved
1032     global ld
1033
1034     if {![info exists gc_sections_available_saved]} {
1035         # Some targets don't support gc-sections despite whatever's
1036         # advertised by ld's options.
1037         if {   [istarget alpha-*-*]
1038             || [istarget d30v-*-*]
1039             || [istarget dlx-*-*]
1040             || [istarget hppa*64-*-*]
1041             || [istarget ia64-*-*]
1042             || [istarget mep-*-*]
1043             || [istarget mn10200-*-*]
1044             || [istarget pj*-*-*]
1045             || [istarget pru*-*-*]
1046             || [istarget s12z-*-*]
1047             || [istarget xgate-*-*] } {
1048             set gc_sections_available_saved 0
1049             return 0
1050         }
1051
1052         # elf2flt uses -q (--emit-relocs), which is incompatible with
1053         # --gc-sections.
1054         if { [board_info target exists ldflags]
1055              && [regexp " -elf2flt\[ =\]" " [board_info target ldflags] "] } {
1056             set gc_sections_available_saved 0
1057             return 0
1058         }
1059
1060         # Check if the ld used by gcc supports --gc-sections.
1061         # FIXME: this test is useless since ld --help always says
1062         # --gc-sections is available
1063         set ld_output [remote_exec host $ld "--help"]
1064         if { [ string first "--gc-sections" $ld_output ] >= 0 } {
1065             set gc_sections_available_saved 1
1066         } else {
1067             set gc_sections_available_saved 0
1068         }
1069     }
1070     return $gc_sections_available_saved
1071 }
1072
1073 # Return true if target uses genelf.em (assuming it is ELF).
1074 proc is_generic_elf { } {
1075     if { [istarget "d30v-*-*"]
1076          || [istarget "dlx-*-*"]
1077          || [istarget "fr30-*-*"]
1078          || ([istarget "frv-*-*"] && ![istarget "frv-*-linux*"])
1079          || [istarget "ft32-*-*"]
1080          || [istarget "iq2000-*-*"]
1081          || [istarget "mn10200-*-*"]
1082          || [istarget "moxie-*-*"]
1083          || [istarget "msp430-*-*"]
1084          || [istarget "mt-*-*"]
1085          || [istarget "pj*-*-*"]
1086          || [istarget "xgate-*-*"] } {
1087         return 1;
1088     }
1089     return 0;
1090 }
1091
1092 proc is_underscore_target { } {
1093     global is_underscore_target_saved
1094     global target_triplet
1095     global srcdir
1096
1097     if { ![info exists is_underscore_target_saved] } {
1098         set cmd "targ=$target_triplet . $srcdir/../../bfd/config.bfd &&"
1099         append cmd { echo "$targ_underscore"}
1100         verbose -log "$cmd"
1101         set status [catch {exec sh -c $cmd} result]
1102         if { $status == 0 && [string match "yes" $result] } {
1103             set is_underscore_target_saved 1
1104         } else {
1105             set is_underscore_target_saved 0
1106         }
1107     }
1108     return $is_underscore_target_saved
1109 }
1110
1111 # Returns true if the target ld supports the plugin API.
1112 proc check_plugin_api_available { } {
1113     global plugin_api_available_saved
1114     global ld
1115     if {![info exists plugin_api_available_saved]} {
1116         # Check if the ld used by gcc supports --plugin.
1117         set ld_output [remote_exec host $ld "--help"]
1118         if { [ string first "-plugin PLUGIN" $ld_output ] >= 0 } {
1119             set plugin_api_available_saved 1
1120         } else {
1121             set plugin_api_available_saved 0
1122         }
1123     }
1124     return $plugin_api_available_saved
1125 }
1126
1127 # Sets ld_sysroot to the current sysroot (empty if not supported) and
1128 # returns true if the target ld supports sysroot.
1129 proc check_sysroot_available { } {
1130     global ld_sysroot_available_saved ld ld_sysroot
1131     if {![info exists ld_sysroot_available_saved]} {
1132         # Check if ld supports --sysroot *other* than empty.
1133         set ld_sysroot [string trimright [lindex [remote_exec host $ld "--print-sysroot"] 1]]
1134         if { $ld_sysroot == "" } {
1135             set ld_sysroot_available_saved 0
1136         } else {
1137             set ld_sysroot_available_saved 1
1138         }
1139     }
1140     return $ld_sysroot_available_saved
1141 }
1142
1143 # Returns 1 if plugin is enabled in gcc.  Returns 0 otherwise.
1144 proc check_gcc_plugin_enabled { } {
1145     global CC
1146
1147     if {![info exists CC]} {
1148         set CC [find_gcc]
1149     }
1150     if { $CC == ""} {
1151         return 0
1152     }
1153     set state [remote_exec host $CC -v]
1154     if { [lindex $state 0] != 0 } {
1155         return 0;
1156     }
1157     for { set i 1 } { $i < [llength $state] } { incr i } {
1158         set v [lindex $state $i]
1159         if { [ string match "*--disable-plugin*" $v ] } {
1160             verbose "plugin is disabled by $v"
1161             return 0;
1162         }
1163     }
1164
1165     return 1;
1166 }
1167
1168 # Returns true if the target compiler supports LTO
1169 proc check_lto_available { } {
1170     global lto_available_saved
1171     global CC
1172
1173     if {![info exists lto_available_saved]} {
1174         if { ![check_gcc_plugin_enabled] } {
1175             set lto_available_saved 0
1176             return 0
1177         }
1178         # This test will hide LTO bugs in ld.  Since GCC 4.9 adds
1179         # -ffat-lto-objects, we always run LTO tests on Linux with
1180         # GCC 4.9 or newer.
1181         if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
1182             set lto_available_saved 1
1183             return 1
1184         }
1185         # Check if gcc supports -flto -fuse-linker-plugin
1186         set flags ""
1187         if [board_info [target_info name] exists cflags] {
1188             append flags " [board_info [target_info name] cflags]"
1189         }
1190         if [board_info [target_info name] exists ldflags] {
1191             append flags " [board_info [target_info name] ldflags]"
1192         }
1193
1194         set basename "tmpdir/lto[pid]"
1195         set src ${basename}.c
1196         set output ${basename}.out
1197         set f [open $src "w"]
1198         puts $f "int main() { return 0; }"
1199         close $f
1200         if [is_remote host] {
1201             set src [remote_download host $src]
1202         }
1203         set lto_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -fuse-linker-plugin $src -o $output"]
1204         remote_file host delete $src
1205         remote_file host delete $output
1206         file delete $src
1207     }
1208     return $lto_available_saved
1209 }
1210
1211 # Returns true if the target compiler supports LTO  -ffat-lto-objects
1212 proc check_lto_fat_available { } {
1213     global lto_fat_available_saved
1214     global CC
1215
1216     if {![info exists lto_fat_available_saved]} {
1217         if { ![check_gcc_plugin_enabled] } {
1218             set lto_fat_available_saved 0
1219             return 0
1220         }
1221         # This test will hide LTO bugs in ld.  Since GCC 4.9 adds
1222         # -ffat-lto-objects, we always run LTO tests on Linux with
1223         # GCC 4.9 or newer.
1224         if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
1225             set lto_fat_available_saved 1
1226             return 1
1227         }
1228         # Check if gcc supports -flto -fuse-linker-plugin
1229         set flags ""
1230         if [board_info [target_info name] exists cflags] {
1231             append flags " [board_info [target_info name] cflags]"
1232         }
1233         if [board_info [target_info name] exists ldflags] {
1234             append flags " [board_info [target_info name] ldflags]"
1235         }
1236
1237         set basename "tmpdir/lto[pid]"
1238         set src ${basename}.c
1239         set output ${basename}.out
1240         set f [open $src "w"]
1241         puts $f "int main() { return 0; }"
1242         close $f
1243         if [is_remote host] {
1244             set src [remote_download host $src]
1245         }
1246         set lto_fat_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -ffat-lto-objects -fuse-linker-plugin $src -o $output"]
1247         remote_file host delete $src
1248         remote_file host delete $output
1249         file delete $src
1250     }
1251     return $lto_fat_available_saved
1252 }
1253
1254 # Returns true if the target compiler supports LTO and -shared
1255 proc check_lto_shared_available { } {
1256     global lto_shared_available_saved
1257     global CC
1258
1259     if {![info exists lto_shared_available_saved]} {
1260         if { ![check_gcc_plugin_enabled] } {
1261             set lto_shared_available_saved 0
1262             return 0
1263         }
1264         # This test will hide LTO bugs in ld.  Since GCC 4.9 adds
1265         # -ffat-lto-objects, we always run LTO tests on Linux with
1266         # GCC 4.9 or newer.
1267         if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
1268             set lto_shared_available_saved 1
1269             return 1
1270         }
1271         # Check if gcc supports -flto -fuse-linker-plugin -shared
1272         set flags ""
1273         if [board_info [target_info name] exists cflags] {
1274             append flags " [board_info [target_info name] cflags]"
1275         }
1276         if [board_info [target_info name] exists ldflags] {
1277             append flags " [board_info [target_info name] ldflags]"
1278         }
1279
1280         set basename "tmpdir/lto_shared[pid]"
1281         set src ${basename}.c
1282         set output ${basename}.so
1283         set f [open $src "w"]
1284         puts $f ""
1285         close $f
1286         if [is_remote host] {
1287             set src [remote_download host $src]
1288         }
1289         set lto_shared_available_saved [run_host_cmd_yesno "$CC" "$flags -shared -fPIC -flto -fuse-linker-plugin $src -o $output"]
1290         remote_file host delete $src
1291         remote_file host delete $output
1292         file delete $src
1293     }
1294     return $lto_shared_available_saved
1295 }
1296
1297 # Check if the assembler supports CFI statements.
1298
1299 proc check_as_cfi { } {
1300     global check_as_cfi_result
1301     global as
1302     if [info exists check_as_cfi_result] {
1303         return $check_as_cfi_result
1304     }
1305     set as_file "tmpdir/check_as_cfi.s"
1306     set as_fh [open $as_file w 0666]
1307     puts $as_fh "# Generated file. DO NOT EDIT"
1308     puts $as_fh "\t.cfi_startproc"
1309     puts $as_fh "\t.cfi_endproc"
1310     close $as_fh
1311     remote_download host $as_file
1312     verbose -log "Checking CFI support:"
1313     rename "perror" "check_as_cfi_perror"
1314     proc perror { args } { }
1315     set success [ld_assemble $as $as_file "/dev/null"]
1316     rename "perror" ""
1317     rename "check_as_cfi_perror" "perror"
1318     #remote_file host delete $as_file
1319     set check_as_cfi_result $success
1320     return $success
1321 }
1322
1323 # Returns true if IFUNC works.
1324
1325 proc check_ifunc_available { } {
1326     global ifunc_available_saved
1327     global CC
1328
1329     if {![info exists ifunc_available_saved]} {
1330         if { [which $CC] == 0 } {
1331             set ifunc_available_saved 0
1332             return 0
1333         }
1334         # Check if gcc supports -flto -fuse-linker-plugin
1335         set flags ""
1336         if [board_info [target_info name] exists cflags] {
1337             append flags " [board_info [target_info name] cflags]"
1338         }
1339         if [board_info [target_info name] exists ldflags] {
1340             append flags " [board_info [target_info name] ldflags]"
1341         }
1342
1343         set basename "tmpdir/ifunc[pid]"
1344         set src ${basename}.c
1345         set output ${basename}.out
1346         set f [open $src "w"]
1347         puts $f "extern int library_func2 (void);"
1348         puts $f "int main (void)"
1349         puts $f "{"
1350         puts $f "  if (library_func2 () != 2) __builtin_abort ();"
1351         puts $f "  return 0; "
1352         puts $f "}"
1353         puts $f "static int library_func1 (void) {return 2; }"
1354         puts $f "void *foo (void) __asm__ (\"library_func2\");"
1355         puts $f "void *foo (void) { return library_func1; }"
1356         puts $f "__asm__(\".type library_func2, %gnu_indirect_function\");"
1357         close $f
1358         if [is_remote host] {
1359             set src [remote_download host $src]
1360         }
1361         set ifunc_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
1362         if { [isnative] && $ifunc_available_saved == 1 } {
1363           set ifunc_available_saved [run_host_cmd_yesno "$output" ""]
1364         }
1365         remote_file host delete $src
1366         remote_file host delete $output
1367         file delete $src
1368     }
1369     return $ifunc_available_saved
1370 }
1371
1372 # Returns true if ifunc attribute works.
1373
1374 proc check_ifunc_attribute_available { } {
1375     global ifunc_attribute_available_saved
1376     global CC
1377
1378     if {![info exists ifunc_attribute_available_saved]} {
1379         if { [which $CC] == 0 } {
1380             set ifunc_attribute_available_saved 0
1381             return 0
1382         }
1383         # Check if gcc supports -flto -fuse-linker-plugin
1384         set flags ""
1385         if [board_info [target_info name] exists cflags] {
1386             append flags " [board_info [target_info name] cflags]"
1387         }
1388         if [board_info [target_info name] exists ldflags] {
1389             append flags " [board_info [target_info name] ldflags]"
1390         }
1391
1392         set basename "tmpdir/ifunc[pid]"
1393         set src ${basename}.c
1394         set output ${basename}.out
1395         set f [open $src "w"]
1396         puts $f "extern int library_func2 (void) __attribute__ ((ifunc (\"foo\")));"
1397         puts $f "int main (void)"
1398         puts $f "{"
1399         puts $f "  if (library_func2 () != 2) __builtin_abort ();"
1400         puts $f "  return 0; "
1401         puts $f "}"
1402         puts $f "static int library_func1 (void) {return 2; }"
1403         puts $f "void *foo (void) { return library_func1; }"
1404         close $f
1405         if [is_remote host] {
1406             set src [remote_download host $src]
1407         }
1408         set ifunc_attribute_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
1409         if { [isnative] && $ifunc_attribute_available_saved == 1 } {
1410           set ifunc_attribute_available_saved [run_host_cmd_yesno "$output" ""]
1411         }
1412         remote_file host delete $src
1413         remote_file host delete $output
1414         file delete $src
1415     }
1416     return $ifunc_attribute_available_saved
1417 }
1418
1419 # Return true if libdl is supported.
1420
1421 proc check_libdl_available { } {
1422     global libdl_available_saved
1423     global CC
1424
1425     if {![info exists libdl_available_saved]} {
1426         if { [which $CC] == 0 } {
1427             set libdl_available_saved 0
1428             return 0
1429         }
1430
1431         set basename "tmpdir/dl_avail_test[pid]"
1432         set src ${basename}.c
1433         set output ${basename}.out
1434         set f [open $src "w"]
1435         # Sample test file.
1436         puts $f "#include <dlfcn.h>"
1437         puts $f "int main (void)"
1438         puts $f "{"
1439         puts $f "  dlopen (\"dummy.so\", RTLD_NOW);"
1440         puts $f "  return 0; "
1441         puts $f "}"
1442         close $f
1443         if [is_remote host] {
1444             set src [remote_download host $src]
1445         }
1446         set libdl_available_saved [run_host_cmd_yesno "$CC" "$src -o $output -ldl"]
1447         remote_file host delete $src
1448         remote_file host delete $output
1449         file delete $src
1450     }
1451     return $libdl_available_saved
1452 }
1453
1454 # Returns true if GNU2 TLS works.
1455
1456 proc check_gnu2_tls_available { } {
1457     global gnu2_tls_available_saved
1458     global CC
1459     global GNU2_CFLAGS
1460
1461     if {![info exists gnu2_tls_available_saved]} {
1462         if { [which $CC] == 0 || "$GNU2_CFLAGS" == "" } {
1463             set gnu2_tls_available_saved 0
1464             return 0
1465         }
1466         # Check if GNU2 TLS works.
1467         set flags "$GNU2_CFLAGS"
1468         if [board_info [target_info name] exists cflags] {
1469             append flags " [board_info [target_info name] cflags]"
1470         }
1471         if [board_info [target_info name] exists ldflags] {
1472             append flags " [board_info [target_info name] ldflags]"
1473         }
1474
1475         set basename "tmpdir/gnu2_tls[pid]"
1476         set src1 ${basename}1.c
1477         set output1 ${basename}.so
1478         set f [open $src1 "w"]
1479         puts $f "extern __thread int zzz;"
1480         puts $f "int foo (void)"
1481         puts $f "{"
1482         puts $f "  return zzz;"
1483         puts $f "}"
1484         close $f
1485         if [is_remote host] {
1486             set src1 [remote_download host $src1]
1487         }
1488         set src2 ${basename}2.c
1489         set output2 ${basename}.exe
1490         set f [open $src2 "w"]
1491         puts $f "__thread int zzz = 20;"
1492         puts $f "extern int foo (void);"
1493         puts $f "int main (void)"
1494         puts $f "{"
1495         puts $f "  if (foo () != 20) __builtin_abort ();"
1496         puts $f "  return 0; "
1497         puts $f "}"
1498         close $f
1499         if [is_remote host] {
1500             set src2 [remote_download host $src2]
1501         }
1502         set gnu2_tls_available_saved [run_host_cmd_yesno "$CC" "-fPIC -shared $flags $src1 -o $output1"]
1503         if { $gnu2_tls_available_saved == 1 } {
1504             set gnu2_tls_available_saved [run_host_cmd_yesno "$CC" "$flags $src2 $output1 -o $output2"]
1505             if { $gnu2_tls_available_saved == 1 } {
1506                 set gnu2_tls_available_saved [run_host_cmd_yesno "$output2" ""]
1507             }
1508         }
1509         remote_file host delete $src1
1510         remote_file host delete $output1
1511         remote_file host delete $src2
1512         remote_file host delete $output2
1513         file delete $src1 $src2
1514     }
1515     return $gnu2_tls_available_saved
1516 }