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