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