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