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