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