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