s12z genelf.em
[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             if [match_target $target] {
483                 setup_xfail "*-*-*"
484                 break
485             }
486         }
487
488         set ld_options [lindex $testitem 1]
489         set ld_after [lindex $testitem 2]
490         set as_options [lindex $testitem 3]
491         set src_files  [lindex $testitem 4]
492         set actions [lindex $testitem 5]
493         set binfile tmpdir/[lindex $testitem 6]
494         set cflags [lindex $testitem 7]
495         set objfiles {}
496         set is_unresolved 0
497         set failed 0
498         set maybe_failed 0
499         set ld_output ""
500
501 #       verbose -log "Testname is $testname"
502 #       verbose -log "ld_options is $ld_options"
503 #       verbose -log "ld_after is $ld_after"
504 #       verbose -log "as_options is $as_options"
505 #       verbose -log "src_files is $src_files"
506 #       verbose -log "actions is $actions"
507 #       verbose -log "binfile is $binfile"
508
509         # Assemble each file in the test.
510         foreach src_file $src_files {
511             set fileroot "[file rootname [file tail $src_file]]"
512             set objfile "tmpdir/$fileroot.o"
513             lappend objfiles $objfile
514
515             if { [file extension $src_file] == ".c" } {
516                 set as_file "tmpdir/$fileroot.s"
517                 if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
518                     set is_unresolved 1
519                     break
520                 }
521             } else {
522                 set as_file "$srcdir/$subdir/$src_file"
523             }
524             if ![ld_assemble $as "$as_options $as_file" $objfile] {
525                 set is_unresolved 1
526                 break
527             }
528         }
529
530         # Catch assembler errors.
531         if { $is_unresolved } {
532             unresolved $testname
533             continue
534         }
535
536         if { $binfile eq "tmpdir/" } {
537             # compile only
538         } elseif { [regexp ".*\\.a$" $binfile] } {
539             if { ![ar_simple_create $ar $ld_options $binfile "$objfiles $ld_after"] } {
540                 set failed 1
541             }
542         } elseif { ![ld_link $ld $binfile "$ld_extra_opt -L$srcdir/$subdir $ld_options $objfiles $ld_after"] } {
543             set maybe_failed 1
544             set ld_output "$exec_output"
545         }
546
547         if { !$failed } {
548             foreach actionlist $actions {
549                 set action [lindex $actionlist 0]
550                 set progopts [lindex $actionlist 1]
551
552                 # There are actions where we run regexp_diff on the
553                 # output, and there are other actions (presumably).
554                 # Handling of the former look the same.
555                 set dump_prog ""
556                 switch -- $action {
557                     objdump
558                         { set dump_prog $objdump }
559                     nm
560                         { set dump_prog $nm }
561                     readelf
562                         { set dump_prog $READELF }
563                     ld
564                         { set dump_prog "ld" }
565                     default
566                         {
567                             perror "Unrecognized action $action"
568                             set is_unresolved 1
569                             break
570                         }
571                     }
572
573                 if { $action == "ld" } {
574                     set regexpfile $progopts
575                     verbose "regexpfile is $srcdir/$subdir/$regexpfile"
576                     set_file_contents "tmpdir/ld.messages" "$ld_output"
577                     verbose "ld.messages has '[file_contents tmpdir/ld.messages]'"
578                     if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$regexpfile"] } then {
579                         verbose "output is $ld_output" 2
580                         set failed 1
581                         break
582                     }
583                     set maybe_failed 0
584                 } elseif { !$maybe_failed && $dump_prog != "" } {
585                     set dumpfile [lindex $actionlist 2]
586                     set binary $dump_prog
587
588                     # Ensure consistent sorting of symbols
589                     if {[info exists env(LC_ALL)]} {
590                         set old_lc_all $env(LC_ALL)
591                     }
592                     set env(LC_ALL) "C"
593                     set cmd "$binary $progopts $binfile"
594                     set status [remote_exec host [concat sh -c [list "$cmd >dump.out 2>ld.stderr"]] "" "/dev/null"]
595                     send_log "$cmd\n"
596                     remote_upload host "ld.stderr"
597                     set comp_output [prune_warnings [file_contents "ld.stderr"]]
598                     remote_file host delete "ld.stderr"
599                     remote_file build delete "ld.stderr"
600
601                     if {[info exists old_lc_all]} {
602                         set env(LC_ALL) $old_lc_all
603                     } else {
604                         unset env(LC_ALL)
605                     }
606
607                     if ![string match "" $comp_output] then {
608                         send_log "$comp_output\n"
609                         set failed 1
610                         break
611                     }
612
613                     remote_upload host "dump.out"
614
615                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
616                         verbose "output is [file_contents "dump.out"]" 2
617                         set failed 1
618                         remote_file build delete "dump.out"
619                         remote_file host delete "dump.out"
620                         break
621                     }
622                     remote_file build delete "dump.out"
623                     remote_file host delete "dump.out"
624                 }
625             }
626         }
627
628         if { $is_unresolved } {
629             unresolved $testname
630         } elseif { $maybe_failed || $failed } {
631             fail $testname
632         } else {
633             pass $testname
634         }
635     }
636 }
637
638 # ldtests contains test-items with 3 items followed by 1 lists, 2 items
639 # and 3 optional items:
640 #   0:name
641 #   1:ld leading options, placed before object files
642 #   2:assembler options
643 #   3:filenames of source files
644 #   4:name of output file
645 #   5:expected output
646 #   6:compiler flags (optional)
647 #   7:language (optional)
648 #   8:linker warning (optional)
649 #   9:ld trailing options, placed after object files (optional)
650 # args is an optional list of target triplets to be xfailed.
651
652 proc run_ld_link_exec_tests { ldtests args } {
653     global ld
654     global as
655     global srcdir
656     global subdir
657     global env
658     global CC
659     global CXX
660     global CFLAGS
661     global CXXFLAGS
662     global errcnt
663     global exec_output
664     global board_cflags
665     global STATIC_LDFLAGS
666
667     # When using GCC as the linker driver, we need to specify board cflags when
668     # linking because cflags may contain linker options.  For example when
669     # linker options are included in GCC spec files then we need the -specs
670     # option.
671     if [board_info [target_info name] exists cflags] {
672         set board_cflags " [board_info [target_info name] cflags]"
673     } else {
674         set board_cflags ""
675     }
676
677     foreach testitem $ldtests {
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         foreach target $args {
697             if [match_target $target] {
698                 setup_xfail "*-*-*"
699                 break
700             }
701         }
702
703 #       verbose -log "Testname is $testname"
704 #       verbose -log "ld_options is $ld_options"
705 #       verbose -log "as_options is $as_options"
706 #       verbose -log "src_files is $src_files"
707 #       verbose -log "binfile is $binfile"
708
709         # Assemble each file in the test.
710         foreach src_file $src_files {
711             set fileroot "[file rootname [file tail $src_file]]"
712             set objfile "tmpdir/$fileroot.o"
713             lappend objfiles $objfile
714
715             if { [ string match "c++" $lang ] } {
716                 set cmd "$CXX -c $CXXFLAGS $cflags"
717             } else {
718                 set cmd "$CC -c $CFLAGS $cflags"
719             }
720             if ![ld_compile $cmd $srcdir/$subdir/$src_file $objfile] {
721                 set failed 1
722                 break
723             }
724         }
725         if { $failed != 0 } {
726             unresolved $testname
727             continue
728         }
729
730         if { [ string match "asm" $lang ] } {
731             set link_proc ld_link
732             set link_cmd $ld
733         } elseif { [ string match "c++" $lang ] } {
734             set link_proc ld_link
735             set link_cmd $CXX
736         } else {
737             set link_proc ld_link
738             set link_cmd $CC
739         }
740
741         if { $binfile eq "tmpdir/" } {
742             # compile only
743             pass $testname
744             continue;
745         } else {
746             if { [string match "" $STATIC_LDFLAGS] \
747                  && [regexp -- ".* \[-\]+static .*" " $board_cflags $ld_options $objfiles $ld_after "] } {
748                 untested $testname
749                 continue
750             }
751             if ![$link_proc $link_cmd $binfile "$board_cflags -L$srcdir/$subdir $ld_options $objfiles $ld_after"] {
752                 set failed 1
753             }
754         }
755
756         # Check if exec_output is expected.
757         if { $warning != "" } then {
758             verbose -log "returned with: <$exec_output>, expected: <$warning>"
759             if { [regexp $warning $exec_output] } then {
760                 set failed 0
761             } else {
762                 set failed 1
763             }
764         }
765
766         if { $failed == 0 && [isnative] } {
767             send_log "Running: $binfile > $binfile.out\n"
768             verbose "Running: $binfile > $binfile.out"
769             catch "exec $binfile > $binfile.out" exec_output
770
771             if ![string match "" $exec_output] then {
772                 send_log "$exec_output\n"
773                 verbose "$exec_output" 1
774                 set failed 1
775             } else {
776                 send_log "diff $binfile.out $srcdir/$subdir/$expfile\n"
777                 verbose "diff $binfile.out $srcdir/$subdir/$expfile"
778                 catch "exec diff $binfile.out $srcdir/$subdir/$expfile" exec_output
779                 set exec_output [prune_warnings $exec_output]
780
781                 if ![string match "" $exec_output] then {
782                     send_log "$exec_output\n"
783                     verbose "$exec_output" 1
784                     set failed 1
785                 }
786             }
787         }
788
789         if { $failed != 0 } {
790             fail $testname
791         } elseif ![isnative] {
792             unsupported $testname
793         } else {
794             set errcnt 0
795             pass $testname
796         }
797     }
798 }
799
800 # List contains test-items with 3 items followed by 2 lists, one item and
801 # one optional item:
802 #  0:name
803 #  1:ld or ar options
804 #  2:compile options
805 #  3:filenames of source files
806 #  4:action and options.
807 #  5:name of output file
808 #  6:language (optional)
809 #
810 # Actions:
811 # objdump: Apply objdump options on result.  Compare with regex (last arg).
812 # nm: Apply nm options on result.  Compare with regex (last arg).
813 # readelf: Apply readelf options on result.  Compare with regex (last arg).
814 # warning: Check linker output against regex (last arg).
815 # error: Like 'warning' but checking output in error case.
816 # warning_output: Check linker output against regex in a file (last arg).
817 # error_output: Like 'warning_output' but checking output in error case.
818 #
819 proc run_cc_link_tests { ldtests } {
820     global nm
821     global objdump
822     global READELF
823     global srcdir
824     global subdir
825     global env
826     global CC
827     global CXX
828     global CFLAGS
829     global CXXFLAGS
830     global ar
831     global exec_output
832     global board_cflags
833     global STATIC_LDFLAGS
834
835     if [board_info [target_info name] exists cflags] {
836         set board_cflags " [board_info [target_info name] cflags]"
837     } else {
838         set board_cflags ""
839     }
840
841     foreach testitem $ldtests {
842         set testname [lindex $testitem 0]
843         set ldflags [lindex $testitem 1]
844         set cflags [lindex $testitem 2]
845         set src_files  [lindex $testitem 3]
846         set actions [lindex $testitem 4]
847         set binfile tmpdir/[lindex $testitem 5]
848         set lang [lindex $testitem 6]
849         set objfiles {}
850         set is_unresolved 0
851         set failed 0
852         set check_ld(terminal) 0
853         set check_ld(source) ""
854
855         if { ![check_compiler_available] } {
856             unsupported $testname
857             continue
858         }
859
860         #verbose -log "testname  is $testname"
861         #verbose -log "ldflags   is $ldflags"
862         #verbose -log "cflags    is $cflags"
863         #verbose -log "src_files is $src_files"
864         #verbose -log "actions   is $actions"
865         #verbose -log "binfile   is $binfile"
866         #verbose -log "lang      is $lang"
867
868         foreach actionlist $actions {
869             set action [lindex $actionlist 0]
870             set progopts [lindex $actionlist 1]
871
872             # Find actions related to error/warning processing.
873             switch -- $action {
874                 error
875                 {
876                     set check_ld(source) "regexp"
877                     set check_ld(regexp) $progopts
878                     set check_ld(terminal) 1
879                 }
880                 warning
881                 {
882                     set check_ld(source) "regexp"
883                     set check_ld(regexp) $progopts
884                 }
885                 error_output
886                 {
887                     set check_ld(source) "file"
888                     set check_ld(file) $progopts
889                     set check_ld(terminal) 1
890                 }
891                 warning_output
892                 {
893                     set check_ld(source) "file"
894                     set check_ld(file) $progopts
895                 }
896             }
897         }
898
899         # Compile each file in the test.
900         foreach src_file $src_files {
901             set fileroot "[file rootname [file tail $src_file]]"
902             set objfile "tmpdir/$fileroot.o"
903             lappend objfiles $objfile
904
905             if { [ string match "c++" $lang ] } {
906                 set cmd "$CXX -c $CXXFLAGS $cflags"
907             } else {
908                 set cmd "$CC -c $CFLAGS $cflags"
909             }
910             if ![ld_compile $cmd $srcdir/$subdir/$src_file $objfile] {
911                 set failed 1
912                 break
913             }
914         }
915         if { $failed != 0 } {
916             unresolved $testname
917             continue
918         }
919
920         # Clear error and warning counts.
921         reset_vars
922
923         if { [ string match "c++" $lang ] } {
924             set cc_cmd $CXX
925         } else {
926             set cc_cmd $CC
927         }
928
929         if { $binfile eq "tmpdir/" } {
930             # compile only
931         } elseif { [regexp ".*\\.a$" $binfile] } {
932             if { ![ar_simple_create $ar $ldflags $binfile "$objfiles"] } {
933                 set failed 1
934             }
935         } else {
936             if { [string match "" $STATIC_LDFLAGS] \
937                  && [regexp -- ".* \[-\]+static .*" " $board_cflags $ldflags $objfiles "] } {
938                 untested $testname
939                 continue
940             }
941             ld_link $cc_cmd $binfile "$board_cflags -L$srcdir/$subdir $ldflags $objfiles"
942             set ld_output "$exec_output"
943
944             if { $check_ld(source) == "regexp" } then {
945                 # Match output against regexp argument.
946                 verbose -log "returned with: <$ld_output>, expected: <$check_ld(regexp)>"
947                 if { ![regexp $check_ld(regexp) $ld_output] } then {
948                     set failed 1
949                 }
950             } elseif { $check_ld(source) == "file" } then {
951                 # Match output against patterns in a file.
952                 set_file_contents "tmpdir/ld.messages" "$ld_output"
953                 verbose "ld.messages has '[file_contents tmpdir/ld.messages]'"
954                 if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$check_ld(file)"] } then {
955                     verbose "output is $ld_output" 2
956                     set failed 1
957                 }
958             }
959
960             if { $check_ld(source) != "" } then {
961                 if { $ld_output == "" } then {
962                     verbose -log "Linker was expected to give error or warning"
963                     set failed 1
964                 }
965             } else {
966                 if { $ld_output != "" } then {
967                     verbose -log "Unexpected linker warning or error"
968                     set failed 1
969                 }
970             }
971         }
972
973         if { $failed == 0 } {
974             foreach actionlist $actions {
975                 set action [lindex $actionlist 0]
976                 set progopts [lindex $actionlist 1]
977
978                 # There are actions where we run regexp_diff on the
979                 # output, and there are other actions (presumably).
980                 # Handling of the former look the same.
981                 set dump_prog ""
982                 switch -- $action {
983                     objdump
984                         { set dump_prog $objdump }
985                     nm
986                         { set dump_prog $nm }
987                     readelf
988                         { set dump_prog $READELF }
989                     error {}
990                     warning {}
991                     error_output {}
992                     warning_output {}
993                     default
994                         {
995                             perror "Unrecognized action $action"
996                             set is_unresolved 1
997                             break
998                         }
999                     }
1000
1001                 if { $dump_prog != "" } {
1002                     set dumpfile [lindex $actionlist 2]
1003                     set binary $dump_prog
1004
1005                     # Ensure consistent sorting of symbols
1006                     if {[info exists env(LC_ALL)]} {
1007                         set old_lc_all $env(LC_ALL)
1008                     }
1009                     set env(LC_ALL) "C"
1010                     set cmd "$binary $progopts $binfile > dump.out"
1011                     send_log "$cmd\n"
1012                     catch "exec $cmd" comp_output
1013                     if {[info exists old_lc_all]} {
1014                         set env(LC_ALL) $old_lc_all
1015                     } else {
1016                         unset env(LC_ALL)
1017                     }
1018                     set comp_output [prune_warnings $comp_output]
1019
1020                     if ![string match "" $comp_output] then {
1021                         send_log "$comp_output\n"
1022                         set failed 1
1023                         break
1024                     }
1025
1026                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1027                         verbose "output is [file_contents "dump.out"]" 2
1028                         set failed 1
1029                         break
1030                     }
1031                 }
1032             }
1033         }
1034
1035         if { $failed } {
1036             fail $testname
1037         } elseif { $is_unresolved } {
1038             unresolved $testname
1039         } else {
1040             pass $testname
1041         }
1042     }
1043 }
1044
1045 # Returns true if --gc-sections is supported on the target.
1046
1047 proc check_gc_sections_available { } {
1048     global gc_sections_available_saved
1049     global ld
1050
1051     if {![info exists gc_sections_available_saved]} {
1052         # Some targets don't support gc-sections despite whatever's
1053         # advertised by ld's options.
1054         if {   [istarget alpha-*-*]
1055             || [istarget bpf-*-*]
1056             || [istarget d30v-*-*]
1057             || [istarget dlx-*-*]
1058             || [istarget hppa*64-*-*]
1059             || [istarget ia64-*-*]
1060             || [istarget mep-*-*]
1061             || [istarget mn10200-*-*]
1062             || [istarget pj*-*-*]
1063             || [istarget pru*-*-*]
1064             || [istarget s12z-*-*]
1065             || [istarget xgate-*-*] } {
1066             set gc_sections_available_saved 0
1067             return 0
1068         }
1069
1070         # elf2flt uses -q (--emit-relocs), which is incompatible with
1071         # --gc-sections.
1072         if { [board_info target exists ldflags]
1073              && [regexp " -elf2flt\[ =\]" " [board_info target ldflags] "] } {
1074             set gc_sections_available_saved 0
1075             return 0
1076         }
1077
1078         # Check if the ld used by gcc supports --gc-sections.
1079         # FIXME: this test is useless since ld --help always says
1080         # --gc-sections is available
1081         set ld_output [remote_exec host $ld "--help"]
1082         if { [ string first "--gc-sections" $ld_output ] >= 0 } {
1083             set gc_sections_available_saved 1
1084         } else {
1085             set gc_sections_available_saved 0
1086         }
1087     }
1088     return $gc_sections_available_saved
1089 }
1090
1091 # Return true if target uses the generic_link_hash_table linker.
1092 proc is_generic { } {
1093     if { [istarget "d30v-*-*"]
1094          || [istarget "dlx-*-*"]
1095          || [istarget "pj*-*-*"]
1096          || [istarget "s12z-*-*"]
1097          || [istarget "xgate-*-*"] } {
1098         return 1
1099     }
1100     return 0
1101 }
1102
1103 # Return true if target uses genelf.em.
1104 proc uses_genelf { } {
1105     if { [istarget "d30v-*-*"]
1106          || [istarget "dlx-*-*"]
1107          || [istarget "fr30-*-*"]
1108          || ([istarget "frv-*-*"] && ![istarget "frv-*-linux*"])
1109          || [istarget "ft32-*-*"]
1110          || [istarget "iq2000-*-*"]
1111          || [istarget "mn10200-*-*"]
1112          || [istarget "moxie-*-*"]
1113          || [istarget "msp430-*-*"]
1114          || [istarget "mt-*-*"]
1115          || [istarget "pj*-*-*"]
1116          || [istarget "s12z-*-*"]
1117          || [istarget "xgate-*-*"] } {
1118         return 1
1119     }
1120     return 0
1121 }
1122
1123 proc is_underscore_target { } {
1124     global is_underscore_target_saved
1125     global target_triplet
1126     global srcdir
1127
1128     if { ![info exists is_underscore_target_saved] } {
1129         set cmd "targ=$target_triplet . $srcdir/../../bfd/config.bfd &&"
1130         append cmd { echo "$targ_underscore"}
1131         verbose -log "$cmd"
1132         set status [catch {exec sh -c $cmd} result]
1133         if { $status == 0 && [string match "yes" $result] } {
1134             set is_underscore_target_saved 1
1135         } else {
1136             set is_underscore_target_saved 0
1137         }
1138     }
1139     return $is_underscore_target_saved
1140 }
1141
1142 # Returns true if the target ld supports the plugin API.
1143 proc check_plugin_api_available { } {
1144     global plugin_api_available_saved
1145     global ld
1146     if {![info exists plugin_api_available_saved]} {
1147         # Check if the ld used by gcc supports --plugin.
1148         set ld_output [remote_exec host $ld "--help"]
1149         if { [ string first "-plugin PLUGIN" $ld_output ] >= 0 } {
1150             set plugin_api_available_saved 1
1151         } else {
1152             set plugin_api_available_saved 0
1153         }
1154     }
1155     return $plugin_api_available_saved
1156 }
1157
1158 # Sets ld_sysroot to the current sysroot (empty if not supported) and
1159 # returns true if the target ld supports sysroot.
1160 proc check_sysroot_available { } {
1161     global ld_sysroot_available_saved ld ld_sysroot
1162     if {![info exists ld_sysroot_available_saved]} {
1163         # Check if ld supports --sysroot *other* than empty.
1164         set ld_sysroot [string trimright [lindex [remote_exec host $ld "--print-sysroot"] 1]]
1165         if { $ld_sysroot == "" } {
1166             set ld_sysroot_available_saved 0
1167         } else {
1168             set ld_sysroot_available_saved 1
1169         }
1170     }
1171     return $ld_sysroot_available_saved
1172 }
1173
1174 # Return true if we can build a program with the compiler.
1175 # On some targets, CC might be defined, but libraries and startup
1176 # code might be missing or require special options that the ld test
1177 # harness doesn't know about.
1178
1179 proc check_compiler_available { } {
1180     global compiler_available_saved
1181     global CC
1182
1183     if {![info exists compiler_available_saved]} {
1184         if { [which $CC] == 0 } {
1185             set compiler_available_saved 0
1186             return 0
1187         }
1188
1189         set flags ""
1190         if [board_info [target_info name] exists cflags] {
1191             append flags " [board_info [target_info name] cflags]"
1192         }
1193         if [board_info [target_info name] exists ldflags] {
1194             append flags " [board_info [target_info name] ldflags]"
1195         }
1196
1197         set basename "tmpdir/compiler[pid]"
1198         set src ${basename}.c
1199         set output ${basename}.out
1200         set f [open $src "w"]
1201         puts $f "int main (void)"
1202         puts $f "{"
1203         puts $f "  return 0; "
1204         puts $f "}"
1205         close $f
1206         if [is_remote host] {
1207             set src [remote_download host $src]
1208         }
1209         set compiler_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
1210         remote_file host delete $src
1211         remote_file host delete $output
1212         file delete $src
1213     }
1214     return $compiler_available_saved
1215 }
1216
1217 # Returns 1 if plugin is enabled in gcc.  Returns 0 otherwise.
1218 proc check_gcc_plugin_enabled { } {
1219     global CC
1220
1221     if {![info exists CC]} {
1222         set CC [find_gcc]
1223     }
1224     if { $CC == ""} {
1225         return 0
1226     }
1227     set state [remote_exec host $CC -v]
1228     if { [lindex $state 0] != 0 } {
1229         return 0;
1230     }
1231     for { set i 1 } { $i < [llength $state] } { incr i } {
1232         set v [lindex $state $i]
1233         if { [ string match "*--disable-plugin*" $v ] } {
1234             verbose "plugin is disabled by $v"
1235             return 0;
1236         }
1237     }
1238
1239     return 1;
1240 }
1241
1242 # Returns true if the target compiler supports LTO
1243 proc check_lto_available { } {
1244     global lto_available_saved
1245     global CC
1246
1247     if {![info exists lto_available_saved]} {
1248         if { ![check_gcc_plugin_enabled] } {
1249             set lto_available_saved 0
1250             return 0
1251         }
1252         # This test will hide LTO bugs in ld.  Since GCC 4.9 adds
1253         # -ffat-lto-objects, we always run LTO tests on Linux with
1254         # GCC 4.9 or newer.
1255         if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
1256             set lto_available_saved 1
1257             return 1
1258         }
1259         # Check if gcc supports -flto -fuse-linker-plugin
1260         set flags ""
1261         if [board_info [target_info name] exists cflags] {
1262             append flags " [board_info [target_info name] cflags]"
1263         }
1264         if [board_info [target_info name] exists ldflags] {
1265             append flags " [board_info [target_info name] ldflags]"
1266         }
1267
1268         set basename "tmpdir/lto[pid]"
1269         set src ${basename}.c
1270         set output ${basename}.out
1271         set f [open $src "w"]
1272         puts $f "int main() { return 0; }"
1273         close $f
1274         if [is_remote host] {
1275             set src [remote_download host $src]
1276         }
1277         set lto_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -fuse-linker-plugin $src -o $output"]
1278         remote_file host delete $src
1279         remote_file host delete $output
1280         file delete $src
1281     }
1282     return $lto_available_saved
1283 }
1284
1285 # Returns true if the target compiler supports LTO  -ffat-lto-objects
1286 proc check_lto_fat_available { } {
1287     global lto_fat_available_saved
1288     global CC
1289
1290     if {![info exists lto_fat_available_saved]} {
1291         if { ![check_gcc_plugin_enabled] } {
1292             set lto_fat_available_saved 0
1293             return 0
1294         }
1295         # This test will hide LTO bugs in ld.  Since GCC 4.9 adds
1296         # -ffat-lto-objects, we always run LTO tests on Linux with
1297         # GCC 4.9 or newer.
1298         if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
1299             set lto_fat_available_saved 1
1300             return 1
1301         }
1302         # Check if gcc supports -flto -fuse-linker-plugin
1303         set flags ""
1304         if [board_info [target_info name] exists cflags] {
1305             append flags " [board_info [target_info name] cflags]"
1306         }
1307         if [board_info [target_info name] exists ldflags] {
1308             append flags " [board_info [target_info name] ldflags]"
1309         }
1310
1311         set basename "tmpdir/lto[pid]"
1312         set src ${basename}.c
1313         set output ${basename}.out
1314         set f [open $src "w"]
1315         puts $f "int main() { return 0; }"
1316         close $f
1317         if [is_remote host] {
1318             set src [remote_download host $src]
1319         }
1320         set lto_fat_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -ffat-lto-objects -fuse-linker-plugin $src -o $output"]
1321         remote_file host delete $src
1322         remote_file host delete $output
1323         file delete $src
1324     }
1325     return $lto_fat_available_saved
1326 }
1327
1328 # Returns true if the target compiler supports LTO and -shared
1329 proc check_lto_shared_available { } {
1330     global lto_shared_available_saved
1331     global CC
1332
1333     if {![info exists lto_shared_available_saved]} {
1334         if { ![check_gcc_plugin_enabled] } {
1335             set lto_shared_available_saved 0
1336             return 0
1337         }
1338         # This test will hide LTO bugs in ld.  Since GCC 4.9 adds
1339         # -ffat-lto-objects, we always run LTO tests on Linux with
1340         # GCC 4.9 or newer.
1341         if { [istarget "*-*-linux*"] && [at_least_gcc_version 4 9] } {
1342             set lto_shared_available_saved 1
1343             return 1
1344         }
1345         # Check if gcc supports -flto -fuse-linker-plugin -shared
1346         set flags ""
1347         if [board_info [target_info name] exists cflags] {
1348             append flags " [board_info [target_info name] cflags]"
1349         }
1350         if [board_info [target_info name] exists ldflags] {
1351             append flags " [board_info [target_info name] ldflags]"
1352         }
1353
1354         set basename "tmpdir/lto_shared[pid]"
1355         set src ${basename}.c
1356         set output ${basename}.so
1357         set f [open $src "w"]
1358         puts $f ""
1359         close $f
1360         if [is_remote host] {
1361             set src [remote_download host $src]
1362         }
1363         set lto_shared_available_saved [run_host_cmd_yesno "$CC" "$flags -shared -fPIC -flto -fuse-linker-plugin $src -o $output"]
1364         remote_file host delete $src
1365         remote_file host delete $output
1366         file delete $src
1367     }
1368     return $lto_shared_available_saved
1369 }
1370
1371 # Check if the assembler supports CFI statements.
1372
1373 proc check_as_cfi { } {
1374     global check_as_cfi_result
1375     global as
1376     if [info exists check_as_cfi_result] {
1377         return $check_as_cfi_result
1378     }
1379     set as_file "tmpdir/check_as_cfi.s"
1380     set as_fh [open $as_file w 0666]
1381     puts $as_fh "# Generated file. DO NOT EDIT"
1382     puts $as_fh "\t.cfi_startproc"
1383     puts $as_fh "\t.cfi_endproc"
1384     close $as_fh
1385     remote_download host $as_file
1386     verbose -log "Checking CFI support:"
1387     rename "perror" "check_as_cfi_perror"
1388     proc perror { args } { }
1389     set success [ld_assemble $as $as_file "/dev/null"]
1390     rename "perror" ""
1391     rename "check_as_cfi_perror" "perror"
1392     #remote_file host delete $as_file
1393     set check_as_cfi_result $success
1394     return $success
1395 }
1396
1397 # Returns true if IFUNC works.
1398
1399 proc check_ifunc_available { } {
1400     global ifunc_available_saved
1401     global CC
1402
1403     if {![info exists ifunc_available_saved]} {
1404         if { ![check_compiler_available] } {
1405             set ifunc_available_saved 0
1406             return 0
1407         }
1408         # Check if gcc supports -flto -fuse-linker-plugin
1409         set flags ""
1410         if [board_info [target_info name] exists cflags] {
1411             append flags " [board_info [target_info name] cflags]"
1412         }
1413         if [board_info [target_info name] exists ldflags] {
1414             append flags " [board_info [target_info name] ldflags]"
1415         }
1416
1417         set basename "tmpdir/ifunc[pid]"
1418         set src ${basename}.c
1419         set output ${basename}.out
1420         set f [open $src "w"]
1421         puts $f "extern int library_func2 (void);"
1422         puts $f "int main (void)"
1423         puts $f "{"
1424         puts $f "  if (library_func2 () != 2) __builtin_abort ();"
1425         puts $f "  return 0; "
1426         puts $f "}"
1427         puts $f "static int library_func1 (void) {return 2; }"
1428         puts $f "void *foo (void) __asm__ (\"library_func2\");"
1429         puts $f "void *foo (void) { return library_func1; }"
1430         puts $f "__asm__(\".type library_func2, %gnu_indirect_function\");"
1431         close $f
1432         if [is_remote host] {
1433             set src [remote_download host $src]
1434         }
1435         set ifunc_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
1436         if { [isnative] && $ifunc_available_saved == 1 } {
1437           set ifunc_available_saved [run_host_cmd_yesno "$output" ""]
1438         }
1439         remote_file host delete $src
1440         remote_file host delete $output
1441         file delete $src
1442     }
1443     return $ifunc_available_saved
1444 }
1445
1446 # Returns true if ifunc attribute works.
1447
1448 proc check_ifunc_attribute_available { } {
1449     global ifunc_attribute_available_saved
1450     global CC
1451
1452     if {![info exists ifunc_attribute_available_saved]} {
1453         if { ![check_compiler_available] } {
1454             set ifunc_attribute_available_saved 0
1455             return 0
1456         }
1457         # Check if gcc supports -flto -fuse-linker-plugin
1458         set flags ""
1459         if [board_info [target_info name] exists cflags] {
1460             append flags " [board_info [target_info name] cflags]"
1461         }
1462         if [board_info [target_info name] exists ldflags] {
1463             append flags " [board_info [target_info name] ldflags]"
1464         }
1465
1466         set basename "tmpdir/ifunc[pid]"
1467         set src ${basename}.c
1468         set output ${basename}.out
1469         set f [open $src "w"]
1470         puts $f "extern int library_func2 (void) __attribute__ ((ifunc (\"foo\")));"
1471         puts $f "int main (void)"
1472         puts $f "{"
1473         puts $f "  if (library_func2 () != 2) __builtin_abort ();"
1474         puts $f "  return 0; "
1475         puts $f "}"
1476         puts $f "static int library_func1 (void) {return 2; }"
1477         puts $f "void *foo (void) { return library_func1; }"
1478         close $f
1479         if [is_remote host] {
1480             set src [remote_download host $src]
1481         }
1482         set ifunc_attribute_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"]
1483         if { [isnative] && $ifunc_attribute_available_saved == 1 } {
1484           set ifunc_attribute_available_saved [run_host_cmd_yesno "$output" ""]
1485         }
1486         remote_file host delete $src
1487         remote_file host delete $output
1488         file delete $src
1489     }
1490     return $ifunc_attribute_available_saved
1491 }
1492
1493 # Return true if libdl is supported.
1494
1495 proc check_libdl_available { } {
1496     global libdl_available_saved
1497     global CC
1498
1499     if {![info exists libdl_available_saved]} {
1500         if { ![check_compiler_available] } {
1501             set libdl_available_saved 0
1502             return 0
1503         }
1504
1505         set basename "tmpdir/dl_avail_test[pid]"
1506         set src ${basename}.c
1507         set output ${basename}.out
1508         set f [open $src "w"]
1509         # Sample test file.
1510         puts $f "#include <dlfcn.h>"
1511         puts $f "int main (void)"
1512         puts $f "{"
1513         puts $f "  dlopen (\"dummy.so\", RTLD_NOW);"
1514         puts $f "  return 0; "
1515         puts $f "}"
1516         close $f
1517         if [is_remote host] {
1518             set src [remote_download host $src]
1519         }
1520         set libdl_available_saved [run_host_cmd_yesno "$CC" "$src -o $output -ldl"]
1521         remote_file host delete $src
1522         remote_file host delete $output
1523         file delete $src
1524     }
1525     return $libdl_available_saved
1526 }
1527
1528 # Returns true if GNU2 TLS works.
1529
1530 proc check_gnu2_tls_available { } {
1531     global gnu2_tls_available_saved
1532     global CC
1533     global GNU2_CFLAGS
1534
1535     if {![info exists gnu2_tls_available_saved]} {
1536         if { ![check_compiler_available] || "$GNU2_CFLAGS" == "" } {
1537             set gnu2_tls_available_saved 0
1538             return 0
1539         }
1540         # Check if GNU2 TLS works.
1541         set flags "$GNU2_CFLAGS"
1542         if [board_info [target_info name] exists cflags] {
1543             append flags " [board_info [target_info name] cflags]"
1544         }
1545         if [board_info [target_info name] exists ldflags] {
1546             append flags " [board_info [target_info name] ldflags]"
1547         }
1548
1549         set basename "tmpdir/gnu2_tls[pid]"
1550         set src1 ${basename}1.c
1551         set output1 ${basename}.so
1552         set f [open $src1 "w"]
1553         puts $f "extern __thread int zzz;"
1554         puts $f "int foo (void)"
1555         puts $f "{"
1556         puts $f "  return zzz;"
1557         puts $f "}"
1558         close $f
1559         if [is_remote host] {
1560             set src1 [remote_download host $src1]
1561         }
1562         set src2 ${basename}2.c
1563         set output2 ${basename}.exe
1564         set f [open $src2 "w"]
1565         puts $f "__thread int zzz = 20;"
1566         puts $f "extern int foo (void);"
1567         puts $f "int main (void)"
1568         puts $f "{"
1569         puts $f "  if (foo () != 20) __builtin_abort ();"
1570         puts $f "  return 0; "
1571         puts $f "}"
1572         close $f
1573         if [is_remote host] {
1574             set src2 [remote_download host $src2]
1575         }
1576         set gnu2_tls_available_saved [run_host_cmd_yesno "$CC" "-fPIC -shared $flags $src1 -o $output1"]
1577         if { $gnu2_tls_available_saved == 1 } {
1578             set gnu2_tls_available_saved [run_host_cmd_yesno "$CC" "$flags $src2 $output1 -o $output2"]
1579             if { $gnu2_tls_available_saved == 1 } {
1580                 set gnu2_tls_available_saved [run_host_cmd_yesno "$output2" ""]
1581             }
1582         }
1583         remote_file host delete $src1
1584         remote_file host delete $output1
1585         remote_file host delete $src2
1586         remote_file host delete $output2
1587         file delete $src1 $src2
1588     }
1589     return $gnu2_tls_available_saved
1590 }