bfd/
[binutils-gdb.git] / ld / testsuite / lib / ld-lib.exp
1 # Support routines for LD testsuite.
2 # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 # 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4 #
5 # This file is part of the GNU Binutils.
6 #
7 # This file is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 # MA 02110-1301, USA.
21
22 # Extract and print the version number of ld.
23 #
24 proc default_ld_version { ld } {
25 global host_triplet
26
27 if { ![is_remote host] && [which $ld] == 0 } then {
28 perror "$ld does not exist"
29 exit 1
30 }
31
32 remote_exec host "$ld --version" "" "/dev/null" "ld.version"
33 remote_upload host "ld.version"
34 set tmp [prune_warnings [file_contents "ld.version"]]
35 remote_file build delete "ld.version"
36 remote_file host delete "ld.version"
37
38 regexp "\[^\n\]* (cygnus-|)(\[-0-9.a-zA-Z-\]+)\[\r\n\].*" $tmp version cyg number
39 if [info exists number] then {
40 clone_output "$ld $number\n"
41 }
42 }
43
44 proc run_host_cmd { prog command } {
45 global link_output
46
47 if { ![is_remote host] && [which "$prog"] == 0 } then {
48 perror "$prog does not exist"
49 return 0
50 }
51
52 verbose -log "$prog $command"
53 set status [remote_exec host [concat sh -c [list "$prog $command 2>&1"]] "" "/dev/null" "ld.tmp"]
54 remote_upload host "ld.tmp"
55 set link_output [file_contents "ld.tmp"]
56 regsub "\n$" $link_output "" link_output
57 if { [lindex $status 0] != 0 && [string match "" $link_output] } then {
58 append link_output "child process exited abnormally"
59 }
60 remote_file build delete ld.tmp
61 remote_file host delete ld.tmp
62
63 if [string match "" $link_output] then {
64 return ""
65 }
66
67 verbose -log "$link_output"
68 return "$link_output"
69 }
70
71 proc run_host_cmd_yesno { prog command } {
72 global exec_output
73
74 set exec_output [prune_warnings [run_host_cmd "$prog" "$command"]]
75 if [string match "" $exec_output] then {
76 return 1;
77 }
78 return 0;
79 }
80
81 # Link an object using relocation.
82 #
83 proc default_ld_relocate { ld target objects } {
84 global HOSTING_EMU
85
86 remote_file host delete $target
87 return [run_host_cmd_yesno "$ld" "$HOSTING_EMU -o $target -r $objects"]
88 }
89
90 # Check to see if ld is being invoked with a non-endian output format
91 #
92 proc is_endian_output_format { object_flags } {
93
94 if {[string match "*-oformat binary*" $object_flags] || \
95 [string match "*-oformat ieee*" $object_flags] || \
96 [string match "*-oformat ihex*" $object_flags] || \
97 [string match "*-oformat netbsd-core*" $object_flags] || \
98 [string match "*-oformat srec*" $object_flags] || \
99 [string match "*-oformat tekhex*" $object_flags] || \
100 [string match "*-oformat trad-core*" $object_flags] } then {
101 return 0
102 } else {
103 return 1
104 }
105 }
106
107 # Look for big-endian or little-endian switches in the multlib
108 # options and translate these into a -EB or -EL switch. Note
109 # we cannot rely upon proc process_multilib_options to do this
110 # for us because for some targets the compiler does not support
111 # -EB/-EL but it does support -mbig-endian/-mlittle-endian, and
112 # the site.exp file will include the switch "-mbig-endian"
113 # (rather than "big-endian") which is not detected by proc
114 # process_multilib_options.
115 #
116 proc big_or_little_endian {} {
117
118 if [board_info [target_info name] exists multilib_flags] {
119 set tmp_flags " [board_info [target_info name] multilib_flags]"
120
121 foreach x $tmp_flags {
122 case $x in {
123 {*big*endian eb EB -eb -EB -mb -meb} {
124 set flags " -EB"
125 return $flags
126 }
127 {*little*endian el EL -el -EL -ml -mel} {
128 set flags " -EL"
129 return $flags
130 }
131 }
132 }
133 }
134
135 set flags ""
136 return $flags
137 }
138
139 # Link a program using ld.
140 #
141 proc default_ld_link { ld target objects } {
142 global HOSTING_EMU
143 global HOSTING_CRT0
144 global HOSTING_LIBS
145 global LIBS
146 global host_triplet
147 global link_output
148 global exec_output
149
150 set objs "$HOSTING_CRT0 $objects"
151 set libs "$LIBS $HOSTING_LIBS"
152
153 if [is_endian_output_format $objects] then {
154 set flags [big_or_little_endian]
155 } else {
156 set flags ""
157 }
158
159 remote_file host delete $target
160
161 return [run_host_cmd_yesno "$ld" "$HOSTING_EMU $flags -o $target $objs $libs"]
162 }
163
164 # Link a program using ld, without including any libraries.
165 #
166 proc default_ld_simple_link { ld target objects } {
167 global host_triplet
168 global gcc_ld_flag
169 global exec_output
170
171 if [is_endian_output_format $objects] then {
172 set flags [big_or_little_endian]
173 } else {
174 set flags ""
175 }
176
177 # If we are compiling with gcc, we want to add gcc_ld_flag to
178 # flags. Rather than determine this in some complex way, we guess
179 # based on the name of the compiler.
180 set ldexe $ld
181 set ldparm [string first " " $ld]
182 if { $ldparm > 0 } then {
183 set ldexe [string range $ld 0 $ldparm]
184 }
185 set ldexe [string replace $ldexe 0 [string last "/" $ldexe] ""]
186 if {[string match "*gcc*" $ldexe] || [string match "*++*" $ldexe]} then {
187 set flags "$gcc_ld_flag $flags"
188 }
189
190 remote_file host delete $target
191
192 set exec_output [run_host_cmd "$ld" "$flags -o $target $objects"]
193 set exec_output [prune_warnings $exec_output]
194
195 # We don't care if we get a warning about a non-existent start
196 # symbol, since the default linker script might use ENTRY.
197 regsub -all "(^|\n)(\[^\n\]*: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
198
199 if [string match "" $exec_output] then {
200 return 1
201 } else {
202 return 0
203 }
204 }
205
206 # Compile an object using cc.
207 #
208 proc default_ld_compile { cc source object } {
209 global CFLAGS
210 global CXXFLAGS
211 global srcdir
212 global subdir
213 global host_triplet
214 global gcc_gas_flag
215
216 set cc_prog $cc
217 if {[llength $cc_prog] > 1} then {
218 set cc_prog [lindex $cc_prog 0]
219 }
220 if {![is_remote host] && [which $cc_prog] == 0} then {
221 perror "$cc_prog does not exist"
222 return 0
223 }
224
225 remote_file build delete "$object"
226 remote_file host delete "$object"
227
228 set flags "-I$srcdir/$subdir"
229
230 # If we are compiling with gcc, we want to add gcc_gas_flag to
231 # flags. Rather than determine this in some complex way, we guess
232 # based on the name of the compiler.
233 set ccexe $cc
234 set ccparm [string first " " $cc]
235 set ccflags ""
236 if { $ccparm > 0 } then {
237 set ccflags [string range $cc $ccparm end]
238 set ccexe [string range $cc 0 $ccparm]
239 set cc $ccexe
240 }
241 set ccexe [string replace $ccexe 0 [string last "/" $ccexe] ""]
242 if {[string match "*gcc*" $ccexe] || [string match "*++*" $ccexe]} then {
243 set flags "$gcc_gas_flag $flags"
244 }
245
246 if {[string match "*++*" $ccexe]} {
247 set flags "$flags $CXXFLAGS"
248 } else {
249 set flags "$flags $CFLAGS"
250 }
251
252 if [board_info [target_info name] exists multilib_flags] {
253 append flags " [board_info [target_info name] multilib_flags]"
254 }
255
256 verbose -log "$cc $flags $ccflags -c $source -o $object"
257
258 set status [remote_exec host [concat sh -c [list "$cc $flags $ccflags -c $source -o $object 2>&1"]] "" "/dev/null" "ld.tmp"]
259 remote_upload host "ld.tmp"
260 set exec_output [file_contents "ld.tmp"]
261 remote_file build delete "ld.tmp"
262 remote_file host delete "ld.tmp"
263 set exec_output [prune_warnings $exec_output]
264 if [string match "" $exec_output] then {
265 if {![file exists $object]} then {
266 regexp ".*/(\[^/\]*)$" $source all dobj
267 regsub "\\.c" $dobj ".o" realobj
268 verbose "looking for $realobj"
269 if {[remote_file host exists $realobj]} then {
270 verbose -log "mv $realobj $object"
271 remote_upload "$realobj" "$object"
272 } else {
273 perror "$object not found after compilation"
274 return 0
275 }
276 }
277 return 1
278 } else {
279 verbose -log "$exec_output"
280 perror "$source: compilation failed"
281 return 0
282 }
283 }
284
285 # Assemble a file.
286 #
287 proc default_ld_assemble { as source object } {
288 global ASFLAGS
289 global host_triplet
290
291 if ![info exists ASFLAGS] { set ASFLAGS "" }
292
293 set flags [big_or_little_endian]
294 set exec_output [run_host_cmd "$as" "$flags $ASFLAGS -o $object $source"]
295 set exec_output [prune_warnings $exec_output]
296 if [string match "" $exec_output] then {
297 return 1
298 } else {
299 perror "$source: assembly failed"
300 return 0
301 }
302 }
303
304 # Run nm on a file, putting the result in the array nm_output.
305 #
306 proc default_ld_nm { nm nmflags object } {
307 global NMFLAGS
308 global nm_output
309 global host_triplet
310
311 if {[info exists nm_output]} {
312 unset nm_output
313 }
314
315 if ![info exists NMFLAGS] { set NMFLAGS "" }
316
317 # Ensure consistent sorting of symbols
318 if {[info exists env(LC_ALL)]} {
319 set old_lc_all $env(LC_ALL)
320 }
321 set env(LC_ALL) "C"
322
323 verbose -log "$nm $NMFLAGS $nmflags $object >tmpdir/nm.out"
324
325 set status [remote_exec host [concat sh -c [list "$nm $NMFLAGS $nmflags $object 2>ld.stderr"]] "" "/dev/null" "tmpdir/nm.out"]
326 if {[info exists old_lc_all]} {
327 set env(LC_ALL) $old_lc_all
328 } else {
329 unset env(LC_ALL)
330 }
331 remote_upload host "ld.stderr"
332 remote_upload host "tmpdir/nm.out" "tmpdir/nm.out"
333 set exec_output [prune_warnings [file_contents "ld.stderr"]]
334 remote_file host delete "ld.stderr"
335 remote_file build delete "ld.stderr"
336 if [string match "" $exec_output] then {
337 set file [open tmpdir/nm.out r]
338 while { [gets $file line] != -1 } {
339 verbose "$line" 2
340 if [regexp "^(\[0-9a-fA-F\]+) \[a-zA-Z0-9\] \\.*(.+)$" $line whole value name] {
341 set name [string trimleft $name "_"]
342 verbose "Setting nm_output($name) to 0x$value" 2
343 set nm_output($name) 0x$value
344 }
345 }
346 close $file
347 return 1
348 } else {
349 verbose -log "$exec_output"
350 perror "$object: nm failed"
351 return 0
352 }
353 }
354
355 # Define various symbols needed when not linking against all
356 # target libs.
357 proc ld_simple_link_defsyms {} {
358
359 set flags "--defsym __stack_chk_fail=0"
360
361 # ARM targets call __gccmain
362 if {[istarget arm*-*-*] || \
363 [istarget strongarm*-*-*] || \
364 [istarget xscale*-*-*] || \
365 [istarget thumb-*-*] } {
366 append flags " --defsym __gccmain=0"
367 }
368
369 # PowerPC EABI code calls __eabi.
370 if {[istarget powerpc*-*-eabi*] || [istarget powerpc*-*-rtems*]} {
371 append flags " --defsym __eabi=0"
372 }
373
374 # mn10200 code calls __truncsipsi2_d0_d2.
375 if {[istarget mn10200*-*-*]} then {
376 append flags " --defsym __truncsipsi2_d0_d2=0"
377 }
378
379 # m6811/m6812 code has references to soft registers.
380 if {[istarget m6811-*-*] || [istarget m6812-*-*]} {
381 append flags " --defsym _.frame=0 --defsym _.d1=0 --defsym _.d2=0"
382 append flags " --defsym _.d3=0 --defsym _.d4=0"
383 append flags " --defsym _.tmp=0 --defsym _.xy=0 --defsym _.z=0"
384 }
385
386 # Some OpenBSD targets have ProPolice and reference __guard and
387 # __stack_smash_handler.
388 if [istarget *-*-openbsd*] {
389 append flags " --defsym __guard=0"
390 append flags " --defsym __stack_smash_handler=0"
391 }
392
393 return $flags
394 }
395
396 # True if the object format is known to be ELF.
397 #
398 proc is_elf_format {} {
399 if { ![istarget *-*-sysv4*] \
400 && ![istarget *-*-unixware*] \
401 && ![istarget *-*-elf*] \
402 && ![istarget *-*-eabi*] \
403 && ![istarget hppa*64*-*-hpux*] \
404 && ![istarget *-*-linux*] \
405 && ![istarget frv-*-uclinux*] \
406 && ![istarget bfin-*-uclinux] \
407 && ![istarget *-*-irix5*] \
408 && ![istarget *-*-irix6*] \
409 && ![istarget *-*-netbsd*] \
410 && ![istarget *-*-solaris2*] } {
411 return 0
412 }
413
414 if { [istarget *-*-linux*aout*] \
415 || [istarget *-*-linux*oldld*] } {
416 return 0
417 }
418
419 if { ![istarget *-*-netbsdelf*] \
420 && ([istarget *-*-netbsd*aout*] \
421 || [istarget *-*-netbsdpe*] \
422 || [istarget arm*-*-netbsd*] \
423 || [istarget sparc-*-netbsd*] \
424 || [istarget i*86-*-netbsd*] \
425 || [istarget m68*-*-netbsd*] \
426 || [istarget vax-*-netbsd*] \
427 || [istarget ns32k-*-netbsd*]) } {
428 return 0
429 }
430 return 1
431 }
432
433 # True if the object format is known to be 64-bit ELF.
434 #
435 proc is_elf64 { binary_file } {
436 global READELF
437 global READELFFLAGS
438
439 set readelf_size ""
440 catch "exec $READELF $READELFFLAGS -h $binary_file > readelf.out" got
441
442 if ![string match "" $got] then {
443 return 0
444 }
445
446 if { ![regexp "\n\[ \]*Class:\[ \]*ELF(\[0-9\]+)\n" \
447 [file_contents readelf.out] nil readelf_size] } {
448 return 0
449 }
450
451 if { $readelf_size == "64" } {
452 return 1
453 }
454
455 return 0
456 }
457
458 # True if the object format is known to be a.out.
459 #
460 proc is_aout_format {} {
461 if { [istarget *-*-*\[ab\]out*] \
462 || [istarget *-*-linux*oldld*] \
463 || [istarget *-*-msdos*] \
464 || [istarget arm-*-netbsd] \
465 || [istarget i?86-*-netbsd] \
466 || [istarget i?86-*-mach*] \
467 || [istarget i?86-*-vsta] \
468 || [istarget pdp11-*-*] \
469 || [istarget m68*-ericsson-ose] \
470 || [istarget m68k-hp-bsd*] \
471 || [istarget m68*-*-hpux*] \
472 || [istarget m68*-*-netbsd] \
473 || [istarget m68*-*-netbsd*4k*] \
474 || [istarget m68k-sony-*] \
475 || [istarget m68*-sun-sunos\[34\]*] \
476 || [istarget m68*-wrs-vxworks*] \
477 || [istarget ns32k-*-*] \
478 || [istarget sparc*-*-netbsd] \
479 || [istarget sparc-sun-sunos4*] \
480 || [istarget vax-dec-ultrix*] \
481 || [istarget vax-*-netbsd] } {
482 return 1
483 }
484 return 0
485 }
486
487 # True if the object format is known to be PE COFF.
488 #
489 proc is_pecoff_format {} {
490 if { ![istarget *-*-mingw*] \
491 && ![istarget *-*-cygwin*] \
492 && ![istarget *-*-cegcc*] \
493 && ![istarget *-*-pe*] } {
494 return 0
495 }
496
497 return 1
498 }
499
500 # Compares two files line-by-line.
501 # Returns differences if exist.
502 # Returns null if file(s) cannot be opened.
503 #
504 proc simple_diff { file_1 file_2 } {
505 global target
506
507 set eof -1
508 set differences 0
509
510 if [file exists $file_1] then {
511 set file_a [open $file_1 r]
512 } else {
513 warning "$file_1 doesn't exist"
514 return
515 }
516
517 if [file exists $file_2] then {
518 set file_b [open $file_2 r]
519 } else {
520 fail "$file_2 doesn't exist"
521 return
522 }
523
524 verbose "# Diff'ing: $file_1 $file_2\n" 2
525
526 while { [gets $file_a line] != $eof } {
527 if [regexp "^#.*$" $line] then {
528 continue
529 } else {
530 lappend list_a $line
531 }
532 }
533 close $file_a
534
535 while { [gets $file_b line] != $eof } {
536 if [regexp "^#.*$" $line] then {
537 continue
538 } else {
539 lappend list_b $line
540 }
541 }
542 close $file_b
543
544 for { set i 0 } { $i < [llength $list_a] } { incr i } {
545 set line_a [lindex $list_a $i]
546 set line_b [lindex $list_b $i]
547
548 verbose "\t$file_1: $i: $line_a\n" 3
549 verbose "\t$file_2: $i: $line_b\n" 3
550 if [string compare $line_a $line_b] then {
551 verbose -log "\t$file_1: $i: $line_a\n"
552 verbose -log "\t$file_2: $i: $line_b\n"
553
554 fail "Test: $target"
555 return
556 }
557 }
558
559 if { [llength $list_a] != [llength $list_b] } {
560 fail "Test: $target"
561 return
562 }
563
564 if $differences<1 then {
565 pass "Test: $target"
566 }
567 }
568
569 # run_dump_test FILE
570 # Copied from gas testsuite, tweaked and further extended.
571 #
572 # Assemble a .s file, then run some utility on it and check the output.
573 #
574 # There should be an assembly language file named FILE.s in the test
575 # suite directory, and a pattern file called FILE.d. `run_dump_test'
576 # will assemble FILE.s, run some tool like `objdump', `objcopy', or
577 # `nm' on the .o file to produce textual output, and then analyze that
578 # with regexps. The FILE.d file specifies what program to run, and
579 # what to expect in its output.
580 #
581 # The FILE.d file begins with zero or more option lines, which specify
582 # flags to pass to the assembler, the program to run to dump the
583 # assembler's output, and the options it wants. The option lines have
584 # the syntax:
585 #
586 # # OPTION: VALUE
587 #
588 # OPTION is the name of some option, like "name" or "objdump", and
589 # VALUE is OPTION's value. The valid options are described below.
590 # Whitespace is ignored everywhere, except within VALUE. The option
591 # list ends with the first line that doesn't match the above syntax
592 # (hmm, not great for error detection).
593 #
594 # The interesting options are:
595 #
596 # name: TEST-NAME
597 # The name of this test, passed to DejaGNU's `pass' and `fail'
598 # commands. If omitted, this defaults to FILE, the root of the
599 # .s and .d files' names.
600 #
601 # as: FLAGS
602 # When assembling, pass FLAGS to the assembler.
603 # If assembling several files, you can pass different assembler
604 # options in the "source" directives. See below.
605 #
606 # ld: FLAGS
607 # Link assembled files using FLAGS, in the order of the "source"
608 # directives, when using multiple files.
609 #
610 # ld_after_inputfiles: FLAGS
611 # Similar to "ld", but put after all input files.
612 #
613 # objcopy_linked_file: FLAGS
614 # Run objcopy on the linked file with the specified flags.
615 # This lets you transform the linked file using objcopy, before the
616 # result is analyzed by an analyzer program specified below (which
617 # may in turn *also* be objcopy).
618 #
619 # PROG: PROGRAM-NAME
620 # The name of the program to run to analyze the .o file produced
621 # by the assembler or the linker output. This can be omitted;
622 # run_dump_test will guess which program to run by seeing which of
623 # the flags options below is present.
624 #
625 # objdump: FLAGS
626 # nm: FLAGS
627 # objcopy: FLAGS
628 # Use the specified program to analyze the assembler or linker
629 # output file, and pass it FLAGS, in addition to the output name.
630 # Note that they are run with LC_ALL=C in the environment to give
631 # consistent sorting of symbols.
632 #
633 # source: SOURCE [FLAGS]
634 # Assemble the file SOURCE.s using the flags in the "as" directive
635 # and the (optional) FLAGS. If omitted, the source defaults to
636 # FILE.s.
637 # This is useful if several .d files want to share a .s file.
638 # More than one "source" directive can be given, which is useful
639 # when testing linking.
640 #
641 # xfail: TARGET
642 # The test is expected to fail on TARGET. This may occur more than
643 # once.
644 #
645 # target: TARGET
646 # Only run the test for TARGET. This may occur more than once; the
647 # target being tested must match at least one. You may provide target
648 # name "cfi" for any target supporting the CFI statements.
649 #
650 # notarget: TARGET
651 # Do not run the test for TARGET. This may occur more than once;
652 # the target being tested must not match any of them.
653 #
654 # error: REGEX
655 # An error with message matching REGEX must be emitted for the test
656 # to pass. The PROG, objdump, nm and objcopy options have no
657 # meaning and need not supplied if this is present.
658 #
659 # warning: REGEX
660 # Expect a linker warning matching REGEX. It is an error to issue
661 # both "error" and "warning".
662 #
663 # Each option may occur at most once unless otherwise mentioned.
664 #
665 # After the option lines come regexp lines. `run_dump_test' calls
666 # `regexp_diff' to compare the output of the dumping tool against the
667 # regexps in FILE.d. `regexp_diff' is defined later in this file; see
668 # further comments there.
669 #
670 proc run_dump_test { name } {
671 global subdir srcdir
672 global OBJDUMP NM AS OBJCOPY READELF LD
673 global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS LDFLAGS
674 global host_triplet runtests
675 global env verbose
676
677 if [string match "*/*" $name] {
678 set file $name
679 set name [file tail $name]
680 } else {
681 set file "$srcdir/$subdir/$name"
682 }
683
684 if ![runtest_file_p $runtests $name] then {
685 return
686 }
687
688 set opt_array [slurp_options "${file}.d"]
689 if { $opt_array == -1 } {
690 perror "error reading options from $file.d"
691 unresolved $subdir/$name
692 return
693 }
694 set dumpfile tmpdir/dump.out
695 set run_ld 0
696 set run_objcopy 0
697 set opts(as) {}
698 set opts(ld) {}
699 set opts(ld_after_inputfiles) {}
700 set opts(xfail) {}
701 set opts(target) {}
702 set opts(notarget) {}
703 set opts(objdump) {}
704 set opts(nm) {}
705 set opts(objcopy) {}
706 set opts(readelf) {}
707 set opts(name) {}
708 set opts(PROG) {}
709 set opts(source) {}
710 set opts(error) {}
711 set opts(warning) {}
712 set opts(objcopy_linked_file) {}
713 set asflags(${file}.s) {}
714
715 foreach i $opt_array {
716 set opt_name [lindex $i 0]
717 set opt_val [lindex $i 1]
718 if ![info exists opts($opt_name)] {
719 perror "unknown option $opt_name in file $file.d"
720 unresolved $subdir/$name
721 return
722 }
723
724 switch -- $opt_name {
725 xfail {}
726 target {}
727 notarget {}
728 source {
729 # Move any source-specific as-flags to a separate array to
730 # simplify processing.
731 if { [llength $opt_val] > 1 } {
732 set asflags([lindex $opt_val 0]) [lrange $opt_val 1 end]
733 set opt_val [lindex $opt_val 0]
734 } else {
735 set asflags($opt_val) {}
736 }
737 }
738 default {
739 if [string length $opts($opt_name)] {
740 perror "option $opt_name multiply set in $file.d"
741 unresolved $subdir/$name
742 return
743 }
744
745 # A single "# ld:" with no options should do the right thing.
746 if { $opt_name == "ld" } {
747 set run_ld 1
748 }
749 # Likewise objcopy_linked_file.
750 if { $opt_name == "objcopy_linked_file" } {
751 set run_objcopy 1
752 }
753 }
754 }
755 if { $opt_name == "as" || $opt_name == "ld" } {
756 set opt_val [subst $opt_val]
757 }
758 set opts($opt_name) [concat $opts($opt_name) $opt_val]
759 }
760 foreach opt { as ld } {
761 regsub {\[big_or_little_endian\]} $opts($opt) \
762 [big_or_little_endian] opts($opt)
763 }
764
765 # Decide early whether we should run the test for this target.
766 if { [llength $opts(target)] > 0 } {
767 set targmatch 0
768 foreach targ $opts(target) {
769 if [istarget $targ] {
770 set targmatch 1
771 break
772 }
773 }
774 if { $targmatch == 0 } {
775 return
776 }
777 }
778 foreach targ $opts(notarget) {
779 if [istarget $targ] {
780 return
781 }
782 }
783
784 set program ""
785 # It's meaningless to require an output-testing method when we
786 # expect an error.
787 if { $opts(error) == "" } {
788 if {$opts(PROG) != ""} {
789 switch -- $opts(PROG) {
790 objdump { set program objdump }
791 nm { set program nm }
792 objcopy { set program objcopy }
793 readelf { set program readelf }
794 default
795 { perror "unrecognized program option $opts(PROG) in $file.d"
796 unresolved $subdir/$name
797 return }
798 }
799 } else {
800 # Guess which program to run, by seeing which option was specified.
801 foreach p {objdump objcopy nm readelf} {
802 if {$opts($p) != ""} {
803 if {$program != ""} {
804 perror "ambiguous dump program in $file.d"
805 unresolved $subdir/$name
806 return
807 } else {
808 set program $p
809 }
810 }
811 }
812 }
813 if { $program == "" && $opts(warning) == "" } {
814 perror "dump program unspecified in $file.d"
815 unresolved $subdir/$name
816 return
817 }
818 }
819
820 if { $opts(name) == "" } {
821 set testname "$subdir/$name"
822 } else {
823 set testname $opts(name)
824 }
825
826 if { $opts(source) == "" } {
827 set sourcefiles [list ${file}.s]
828 } else {
829 set sourcefiles {}
830 foreach sf $opts(source) {
831 if { [string match "/*" $sf] } {
832 lappend sourcefiles "$sf"
833 } else {
834 lappend sourcefiles "$srcdir/$subdir/$sf"
835 }
836 # Must have asflags indexed on source name.
837 set asflags($srcdir/$subdir/$sf) $asflags($sf)
838 }
839 }
840
841 # Time to setup xfailures.
842 foreach targ $opts(xfail) {
843 setup_xfail $targ
844 }
845
846 # Assemble each file.
847 set objfiles {}
848 for { set i 0 } { $i < [llength $sourcefiles] } { incr i } {
849 set sourcefile [lindex $sourcefiles $i]
850
851 set objfile "tmpdir/dump$i.o"
852 catch "exec rm -f $objfile" exec_output
853 lappend objfiles $objfile
854 set cmd "$AS $ASFLAGS $opts(as) $asflags($sourcefile) -o $objfile $sourcefile"
855
856 send_log "$cmd\n"
857 set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
858 remote_upload host "ld.tmp"
859 set comp_output [prune_warnings [file_contents "ld.tmp"]]
860 remote_file host delete "ld.tmp"
861 remote_file build delete "ld.tmp"
862
863 if { [lindex $cmdret 0] != 0 || ![string match "" $comp_output] } then {
864 send_log "$comp_output\n"
865 verbose "$comp_output" 3
866
867 set exitstat "succeeded"
868 if { $cmdret != 0 } { set exitstat "failed" }
869 verbose -log "$exitstat with: <$comp_output>"
870 fail $testname
871 return
872 }
873 }
874
875 set expmsg $opts(error)
876 if { $opts(warning) != "" } {
877 if { $expmsg != "" } {
878 perror "$testname: mixing error and warning test-directives"
879 return
880 }
881 set expmsg $opts(warning)
882 }
883
884 # Perhaps link the file(s).
885 if { $run_ld } {
886 set objfile "tmpdir/dump"
887 catch "exec rm -f $objfile" exec_output
888
889 # Add -L$srcdir/$subdir so that the linker command can use
890 # linker scripts in the source directory.
891 set cmd "$LD $LDFLAGS -L$srcdir/$subdir \
892 $opts(ld) -o $objfile $objfiles $opts(ld_after_inputfiles)"
893
894 send_log "$cmd\n"
895 set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
896 remote_upload host "ld.tmp"
897 set comp_output [file_contents "ld.tmp"]
898 remote_file host delete "ld.tmp"
899 remote_file build delete "ld.tmp"
900 set cmdret [lindex $cmdret 0]
901
902 if { $cmdret == 0 && $run_objcopy } {
903 set infile $objfile
904 set objfile "tmpdir/dump1"
905 remote_file host delete $objfile
906
907 # Note that we don't use OBJCOPYFLAGS here; any flags must be
908 # explicitly specified.
909 set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile"
910
911 send_log "$cmd\n"
912 set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"]
913 remote_upload host "ld.tmp"
914 append comp_output [file_contents "ld.tmp"]
915 remote_file host delete "ld.tmp"
916 remote_file build delete "ld.tmp"
917 set cmdret [lindex $cmdret 0]
918 }
919
920 regsub "\n$" $comp_output "" comp_output
921 if { $cmdret != 0 || $comp_output != "" || $expmsg != "" } then {
922 set exitstat "succeeded"
923 if { $cmdret != 0 } { set exitstat "failed" }
924 verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>"
925 send_log "$comp_output\n"
926 verbose "$comp_output" 3
927
928 if { [regexp $expmsg $comp_output] \
929 && (($cmdret == 0) == ($opts(warning) != "")) } {
930 # We have the expected output from ld.
931 if { $opts(error) != "" || $program == "" } {
932 pass $testname
933 return
934 }
935 } else {
936 verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>"
937 fail $testname
938 return
939 }
940 }
941 } else {
942 set objfile "tmpdir/dump0.o"
943 }
944
945 # We must not have expected failure if we get here.
946 if { $opts(error) != "" } {
947 fail $testname
948 return
949 }
950
951 set progopts1 $opts($program)
952 eval set progopts \$[string toupper $program]FLAGS
953 eval set binary \$[string toupper $program]
954
955 if { ![is_remote host] && [which $binary] == 0 } {
956 untested $testname
957 return
958 }
959
960 if { $progopts1 == "" } { set $progopts1 "-r" }
961 verbose "running $binary $progopts $progopts1" 3
962
963 # Objcopy, unlike the other two, won't send its output to stdout,
964 # so we have to run it specially.
965 set cmd "$binary $progopts $progopts1 $objfile > $dumpfile"
966 if { $program == "objcopy" } {
967 set cmd "$binary $progopts $progopts1 $objfile $dumpfile"
968 }
969
970 # Ensure consistent sorting of symbols
971 if {[info exists env(LC_ALL)]} {
972 set old_lc_all $env(LC_ALL)
973 }
974 set env(LC_ALL) "C"
975 send_log "$cmd\n"
976 set cmdret [remote_exec host [concat sh -c [list "$cmd 2>ld.tmp"]] "" "/dev/null"]
977 remote_upload host "ld.tmp"
978 set comp_output [prune_warnings [file_contents "ld.tmp"]]
979 remote_file host delete "ld.tmp"
980 remote_file build delete "ld.tmp"
981 if {[info exists old_lc_all]} {
982 set env(LC_ALL) $old_lc_all
983 } else {
984 unset env(LC_ALL)
985 }
986 if ![string match "" $comp_output] then {
987 send_log "$comp_output\n"
988 fail $testname
989 return
990 }
991
992 if { $verbose > 2 } then { verbose "output is [file_contents $dumpfile]" 3 }
993 if { [regexp_diff $dumpfile "${file}.d"] } then {
994 fail $testname
995 if { $verbose == 2 } then { verbose "output is [file_contents $dumpfile]" 2 }
996 return
997 }
998
999 pass $testname
1000 }
1001
1002 proc slurp_options { file } {
1003 if [catch { set f [open $file r] } x] {
1004 #perror "couldn't open `$file': $x"
1005 perror "$x"
1006 return -1
1007 }
1008 set opt_array {}
1009 # whitespace expression
1010 set ws {[ ]*}
1011 set nws {[^ ]*}
1012 # whitespace is ignored anywhere except within the options list;
1013 # option names are alphabetic plus underscore only.
1014 set pat "^#${ws}(\[a-zA-Z_\]*)$ws:${ws}(.*)$ws\$"
1015 while { [gets $f line] != -1 } {
1016 set line [string trim $line]
1017 # Whitespace here is space-tab.
1018 if [regexp $pat $line xxx opt_name opt_val] {
1019 # match!
1020 lappend opt_array [list $opt_name $opt_val]
1021 } else {
1022 break
1023 }
1024 }
1025 close $f
1026 return $opt_array
1027 }
1028
1029 # regexp_diff, copied from gas, based on simple_diff above.
1030 # compares two files line-by-line
1031 # file1 contains strings, file2 contains regexps and #-comments
1032 # blank lines are ignored in either file
1033 # returns non-zero if differences exist
1034 #
1035 proc regexp_diff { file_1 file_2 } {
1036
1037 set eof -1
1038 set end_1 0
1039 set end_2 0
1040 set differences 0
1041 set diff_pass 0
1042
1043 if [file exists $file_1] then {
1044 set file_a [open $file_1 r]
1045 } else {
1046 warning "$file_1 doesn't exist"
1047 return 1
1048 }
1049
1050 if [file exists $file_2] then {
1051 set file_b [open $file_2 r]
1052 } else {
1053 fail "$file_2 doesn't exist"
1054 close $file_a
1055 return 1
1056 }
1057
1058 verbose " Regexp-diff'ing: $file_1 $file_2" 2
1059
1060 while { 1 } {
1061 set line_a ""
1062 set line_b ""
1063 while { [string length $line_a] == 0 } {
1064 if { [gets $file_a line_a] == $eof } {
1065 set end_1 1
1066 break
1067 }
1068 }
1069 while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
1070 if [ string match "#pass" $line_b ] {
1071 set end_2 1
1072 set diff_pass 1
1073 break
1074 } elseif [ string match "#..." $line_b ] {
1075 if { [gets $file_b line_b] == $eof } {
1076 set end_2 1
1077 set diff_pass 1
1078 break
1079 }
1080 verbose "looking for \"^$line_b$\"" 3
1081 while { ![regexp "^$line_b$" "$line_a"] } {
1082 verbose "skipping \"$line_a\"" 3
1083 if { [gets $file_a line_a] == $eof } {
1084 set end_1 1
1085 break
1086 }
1087 }
1088 break
1089 }
1090 if { [gets $file_b line_b] == $eof } {
1091 set end_2 1
1092 break
1093 }
1094 }
1095
1096 if { $diff_pass } {
1097 break
1098 } elseif { $end_1 && $end_2 } {
1099 break
1100 } elseif { $end_1 } {
1101 send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
1102 verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
1103 set differences 1
1104 break
1105 } elseif { $end_2 } {
1106 send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
1107 verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
1108 set differences 1
1109 break
1110 } else {
1111 verbose "regexp \"^$line_b$\"\nline \"$line_a\"" 3
1112 if ![regexp "^$line_b$" "$line_a"] {
1113 send_log "regexp_diff match failure\n"
1114 send_log "regexp \"^$line_b$\"\nline \"$line_a\"\n"
1115 set differences 1
1116 }
1117 }
1118 }
1119
1120 if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
1121 send_log "$file_1 and $file_2 are different lengths\n"
1122 verbose "$file_1 and $file_2 are different lengths" 3
1123 set differences 1
1124 }
1125
1126 close $file_a
1127 close $file_b
1128
1129 return $differences
1130 }
1131
1132 proc file_contents { filename } {
1133 set file [open $filename r]
1134 set contents [read $file]
1135 close $file
1136 return $contents
1137 }
1138
1139 # Create an archive using ar
1140 #
1141 proc ar_simple_create { ar aropts target objects } {
1142 remote_file host delete $target
1143
1144 set exec_output [run_host_cmd "$ar" "$aropts rc $target $objects"]
1145 set exec_output [prune_warnings $exec_output]
1146
1147 if [string match "" $exec_output] then {
1148 send_log "$exec_output\n"
1149 return 1
1150 } else {
1151 return 0
1152 }
1153 }
1154
1155 # List contains test-items with 3 items followed by 2 lists, one item and
1156 # one optional item:
1157 # 0:name 1:ld/ar options 2:assembler options
1158 # 3:filenames of assembler files 4: action and options. 5: name of output file
1159 # 6:compiler flags (optional)
1160 #
1161 # Actions:
1162 # objdump: Apply objdump options on result. Compare with regex (last arg).
1163 # nm: Apply nm options on result. Compare with regex (last arg).
1164 # readelf: Apply readelf options on result. Compare with regex (last arg).
1165 #
1166 proc run_ld_link_tests { ldtests } {
1167 global ld
1168 global as
1169 global nm
1170 global ar
1171 global objdump
1172 global READELF
1173 global srcdir
1174 global subdir
1175 global env
1176 global CC
1177 global CFLAGS
1178 global runtests
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 set ld_options [lindex $testitem 1]
1188 set as_options [lindex $testitem 2]
1189 set src_files [lindex $testitem 3]
1190 set actions [lindex $testitem 4]
1191 set binfile tmpdir/[lindex $testitem 5]
1192 set cflags [lindex $testitem 6]
1193 set objfiles {}
1194 set is_unresolved 0
1195 set failed 0
1196
1197 # verbose -log "Testname is $testname"
1198 # verbose -log "ld_options is $ld_options"
1199 # verbose -log "as_options is $as_options"
1200 # verbose -log "src_files is $src_files"
1201 # verbose -log "actions is $actions"
1202 # verbose -log "binfile is $binfile"
1203
1204 # Assemble each file in the test.
1205 foreach src_file $src_files {
1206 set objfile "tmpdir/[file rootname $src_file].o"
1207 lappend objfiles $objfile
1208
1209 if { [file extension $src_file] == ".c" } {
1210 set as_file "tmpdir/[file rootname $src_file].s"
1211 if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
1212 set is_unresolved 1
1213 break
1214 }
1215 } else {
1216 set as_file "$srcdir/$subdir/$src_file"
1217 }
1218 if ![ld_assemble $as "$as_options $as_file" $objfile] {
1219 set is_unresolved 1
1220 break
1221 }
1222 }
1223
1224 # Catch assembler errors.
1225 if { $is_unresolved != 0 } {
1226 unresolved $testname
1227 continue
1228 }
1229
1230 if { [regexp ".*\\.a$" $binfile] } {
1231 if { ![ar_simple_create $ar $ld_options $binfile "$objfiles"] } {
1232 fail $testname
1233 set failed 1
1234 } else {
1235 set failed 0
1236 }
1237 } elseif { ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] } {
1238 fail $testname
1239 set failed 1
1240 } else {
1241 set failed 0
1242 }
1243
1244 if { $failed == 0 } {
1245 foreach actionlist $actions {
1246 set action [lindex $actionlist 0]
1247 set progopts [lindex $actionlist 1]
1248
1249 # There are actions where we run regexp_diff on the
1250 # output, and there are other actions (presumably).
1251 # Handling of the former look the same.
1252 set dump_prog ""
1253 switch -- $action {
1254 objdump
1255 { set dump_prog $objdump }
1256 nm
1257 { set dump_prog $nm }
1258 readelf
1259 { set dump_prog $READELF }
1260 default
1261 {
1262 perror "Unrecognized action $action"
1263 set is_unresolved 1
1264 break
1265 }
1266 }
1267
1268 if { $dump_prog != "" } {
1269 set dumpfile [lindex $actionlist 2]
1270 set binary $dump_prog
1271
1272 # Ensure consistent sorting of symbols
1273 if {[info exists env(LC_ALL)]} {
1274 set old_lc_all $env(LC_ALL)
1275 }
1276 set env(LC_ALL) "C"
1277 set cmd "$binary $progopts $binfile"
1278 set status [remote_exec host [concat sh -c [list "$cmd >dump.out 2>ld.stderr"]] "" "/dev/null"]
1279 send_log "$cmd\n"
1280 remote_upload host "ld.stderr"
1281 set comp_output [prune_warnings [file_contents "ld.stderr"]]
1282 remote_file host delete "ld.stderr"
1283 remote_file build delete "ld.stderr"
1284
1285 if {[info exists old_lc_all]} {
1286 set env(LC_ALL) $old_lc_all
1287 } else {
1288 unset env(LC_ALL)
1289 }
1290
1291 if ![string match "" $comp_output] then {
1292 send_log "$comp_output\n"
1293 set failed 1
1294 break
1295 }
1296
1297 remote_upload host "dump.out"
1298
1299 if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1300 verbose "output is [file_contents "dump.out"]" 2
1301 set failed 1
1302 remote_file build delete "dump.out"
1303 remote_file host delete "dump.out"
1304 break
1305 }
1306 remote_file build delete "dump.out"
1307 remote_file host delete "dump.out"
1308 }
1309 }
1310
1311 if { $failed != 0 } {
1312 fail $testname
1313 } else { if { $is_unresolved == 0 } {
1314 pass $testname
1315 } }
1316 }
1317
1318 # Catch action errors.
1319 if { $is_unresolved != 0 } {
1320 unresolved $testname
1321 continue
1322 }
1323 }
1324 }
1325
1326 # This definition is taken from an unreleased version of DejaGnu. Once
1327 # that version gets released, and has been out in the world for a few
1328 # months at least, it may be safe to delete this copy.
1329 if ![string length [info proc prune_warnings]] {
1330 #
1331 # prune_warnings -- delete various system verbosities from TEXT
1332 #
1333 # An example is:
1334 # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
1335 #
1336 # Sites with particular verbose os's may wish to override this in site.exp.
1337 #
1338 proc prune_warnings { text } {
1339 # This is from sun4's. Do it for all machines for now.
1340 # The "\\1" is to try to preserve a "\n" but only if necessary.
1341 regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
1342
1343 # It might be tempting to get carried away and delete blank lines, etc.
1344 # Just delete *exactly* what we're ask to, and that's it.
1345 return $text
1346 }
1347 }
1348
1349 # targets_to_xfail is a list of target triplets to be xfailed.
1350 # ldtests contains test-items with 3 items followed by 1 lists, 2 items
1351 # and 3 optional items:
1352 # 0:name
1353 # 1:ld options
1354 # 2:assembler options
1355 # 3:filenames of source files
1356 # 4:name of output file
1357 # 5:expected output
1358 # 6:compiler flags (optional)
1359 # 7:language (optional)
1360 # 8:linker warning (optional)
1361
1362 proc run_ld_link_exec_tests { targets_to_xfail ldtests } {
1363 global ld
1364 global as
1365 global srcdir
1366 global subdir
1367 global env
1368 global CC
1369 global CXX
1370 global CFLAGS
1371 global CXXFLAGS
1372 global errcnt
1373 global exec_output
1374
1375 foreach testitem $ldtests {
1376 foreach target $targets_to_xfail {
1377 setup_xfail $target
1378 }
1379 set testname [lindex $testitem 0]
1380 set ld_options [lindex $testitem 1]
1381 set as_options [lindex $testitem 2]
1382 set src_files [lindex $testitem 3]
1383 set binfile tmpdir/[lindex $testitem 4]
1384 set expfile [lindex $testitem 5]
1385 set cflags [lindex $testitem 6]
1386 set lang [lindex $testitem 7]
1387 set warning [lindex $testitem 8]
1388 set objfiles {}
1389 set failed 0
1390
1391 # verbose -log "Testname is $testname"
1392 # verbose -log "ld_options is $ld_options"
1393 # verbose -log "as_options is $as_options"
1394 # verbose -log "src_files is $src_files"
1395 # verbose -log "actions is $actions"
1396 # verbose -log "binfile is $binfile"
1397
1398 # Assemble each file in the test.
1399 foreach src_file $src_files {
1400 set objfile "tmpdir/[file rootname $src_file].o"
1401 lappend objfiles $objfile
1402
1403 # We ignore warnings since some compilers may generate
1404 # incorrect section attributes and the assembler will warn
1405 # them.
1406 if { [ string match "c++" $lang ] } {
1407 ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1408 } else {
1409 ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1410 }
1411
1412 # We have to use $CC to build PIE and shared library.
1413 if { [ string match "c" $lang ] } {
1414 set link_proc ld_simple_link
1415 set link_cmd $CC
1416 } elseif { [ string match "c++" $lang ] } {
1417 set link_proc ld_simple_link
1418 set link_cmd $CXX
1419 } elseif { [ string match "-shared" $ld_options ] \
1420 || [ string match "-pie" $ld_options ] } {
1421 set link_proc ld_simple_link
1422 set link_cmd $CC
1423 } else {
1424 set link_proc ld_link
1425 set link_cmd $ld
1426 }
1427
1428 if ![$link_proc $link_cmd $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
1429 set failed 1
1430 } else {
1431 set failed 0
1432 }
1433
1434 # Check if exec_output is expected.
1435 if { $warning != "" } then {
1436 verbose -log "returned with: <$exec_output>, expected: <$warning>"
1437 if { [regexp $warning $exec_output] } then {
1438 set failed 0
1439 } else {
1440 set failed 1
1441 }
1442 }
1443
1444 if { $failed == 0 } {
1445 send_log "Running: $binfile > $binfile.out\n"
1446 verbose "Running: $binfile > $binfile.out"
1447 catch "exec $binfile > $binfile.out" exec_output
1448
1449 if ![string match "" $exec_output] then {
1450 send_log "$exec_output\n"
1451 verbose "$exec_output" 1
1452 set failed 1
1453 } else {
1454 send_log "diff $binfile.out $srcdir/$subdir/$expfile\n"
1455 verbose "diff $binfile.out $srcdir/$subdir/$expfile"
1456 catch "exec diff $binfile.out $srcdir/$subdir/$expfile" exec_output
1457 set exec_output [prune_warnings $exec_output]
1458
1459 if ![string match "" $exec_output] then {
1460 send_log "$exec_output\n"
1461 verbose "$exec_output" 1
1462 set failed 1
1463 }
1464 }
1465 }
1466
1467 if { $failed != 0 } {
1468 fail $testname
1469 } else {
1470 set errcnt 0
1471 pass $testname
1472 }
1473 }
1474 }
1475 }
1476
1477 # List contains test-items with 3 items followed by 2 lists, one item and
1478 # one optional item:
1479 # 0:name
1480 # 1:ld or ar options
1481 # 2:compile options
1482 # 3:filenames of source files
1483 # 4:action and options.
1484 # 5:name of output file
1485 # 6:language (optional)
1486 #
1487 # Actions:
1488 # objdump: Apply objdump options on result. Compare with regex (last arg).
1489 # nm: Apply nm options on result. Compare with regex (last arg).
1490 # readelf: Apply readelf options on result. Compare with regex (last arg).
1491 #
1492 proc run_cc_link_tests { ldtests } {
1493 global nm
1494 global objdump
1495 global READELF
1496 global srcdir
1497 global subdir
1498 global env
1499 global CC
1500 global CXX
1501 global CFLAGS
1502 global CXXFLAGS
1503 global ar
1504
1505 foreach testitem $ldtests {
1506 set testname [lindex $testitem 0]
1507 set ldflags [lindex $testitem 1]
1508 set cflags [lindex $testitem 2]
1509 set src_files [lindex $testitem 3]
1510 set actions [lindex $testitem 4]
1511 set binfile tmpdir/[lindex $testitem 5]
1512 set lang [lindex $testitem 6]
1513 set objfiles {}
1514 set is_unresolved 0
1515 set failed 0
1516
1517 # Compile each file in the test.
1518 foreach src_file $src_files {
1519 set objfile "tmpdir/[file rootname $src_file].o"
1520 lappend objfiles $objfile
1521
1522 # We ignore warnings since some compilers may generate
1523 # incorrect section attributes and the assembler will warn
1524 # them.
1525 if { [ string match "c++" $lang ] } {
1526 ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1527 } else {
1528 ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile
1529 }
1530 }
1531
1532 # Clear error and warning counts.
1533 reset_vars
1534
1535 if { [ string match "c++" $lang ] } {
1536 set cc_cmd $CXX
1537 } else {
1538 set cc_cmd $CC
1539 }
1540
1541 if { [regexp ".*\\.a$" $binfile] } {
1542 if { ![ar_simple_create $ar $ldflags $binfile "$objfiles"] } {
1543 fail $testname
1544 set failed 1
1545 } else {
1546 set failed 0
1547 }
1548 } elseif { ![ld_simple_link $cc_cmd $binfile "-L$srcdir/$subdir $ldflags $objfiles"] } {
1549 fail $testname
1550 set failed 1
1551 } else {
1552 set failed 0
1553 }
1554
1555 if { $failed == 0 } {
1556 foreach actionlist $actions {
1557 set action [lindex $actionlist 0]
1558 set progopts [lindex $actionlist 1]
1559
1560 # There are actions where we run regexp_diff on the
1561 # output, and there are other actions (presumably).
1562 # Handling of the former look the same.
1563 set dump_prog ""
1564 switch -- $action {
1565 objdump
1566 { set dump_prog $objdump }
1567 nm
1568 { set dump_prog $nm }
1569 readelf
1570 { set dump_prog $READELF }
1571 default
1572 {
1573 perror "Unrecognized action $action"
1574 set is_unresolved 1
1575 break
1576 }
1577 }
1578
1579 if { $dump_prog != "" } {
1580 set dumpfile [lindex $actionlist 2]
1581 set binary $dump_prog
1582
1583 # Ensure consistent sorting of symbols
1584 if {[info exists env(LC_ALL)]} {
1585 set old_lc_all $env(LC_ALL)
1586 }
1587 set env(LC_ALL) "C"
1588 set cmd "$binary $progopts $binfile > dump.out"
1589 send_log "$cmd\n"
1590 catch "exec $cmd" comp_output
1591 if {[info exists old_lc_all]} {
1592 set env(LC_ALL) $old_lc_all
1593 } else {
1594 unset env(LC_ALL)
1595 }
1596 set comp_output [prune_warnings $comp_output]
1597
1598 if ![string match "" $comp_output] then {
1599 send_log "$comp_output\n"
1600 set failed 1
1601 break
1602 }
1603
1604 if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1605 verbose "output is [file_contents "dump.out"]" 2
1606 set failed 1
1607 break
1608 }
1609 }
1610 }
1611
1612 if { $failed != 0 } {
1613 fail $testname
1614 } else { if { $is_unresolved == 0 } {
1615 pass $testname
1616 } }
1617 }
1618
1619 # Catch action errors.
1620 if { $is_unresolved != 0 } {
1621 unresolved $testname
1622 continue
1623 }
1624 }
1625 }
1626
1627 # Returns true if --gc-sections is supported on the target.
1628
1629 proc check_gc_sections_available { } {
1630 global gc_sections_available_saved
1631 global ld
1632
1633 if {![info exists gc_sections_available_saved]} {
1634 # Some targets don't support gc-sections despite whatever's
1635 # advertised by ld's options.
1636 if { [istarget alpha*-*-*]
1637 || [istarget mep-*-*]
1638 || [istarget ia64-*-*]
1639 || [istarget *-*-cygwin]
1640 || [istarget *-*-mingw*] } {
1641 set gc_sections_available_saved 0
1642 return 0
1643 }
1644
1645 # elf2flt uses -q (--emit-relocs), which is incompatible with
1646 # --gc-sections.
1647 if { [board_info target exists ldflags]
1648 && [regexp " -elf2flt\[ =\]" " [board_info target ldflags] "] } {
1649 set gc_sections_available_saved 0
1650 return 0
1651 }
1652
1653 # Check if the ld used by gcc supports --gc-sections.
1654 set ld_output [remote_exec host $ld "--help"]
1655 if { [ string first "--gc-sections" $ld_output ] >= 0 } {
1656 set gc_sections_available_saved 1
1657 } else {
1658 set gc_sections_available_saved 0
1659 }
1660 }
1661 return $gc_sections_available_saved
1662 }
1663
1664 # Check if the assembler supports CFI statements.
1665
1666 proc check_as_cfi { } {
1667 global check_as_cfi_result
1668 global as
1669 if [info exists check_as_cfi_result] {
1670 return $check_as_cfi_result
1671 }
1672 set as_file "tmpdir/check_as_cfi.s"
1673 set as_fh [open $as_file w 0666]
1674 puts $as_fh "# Generated file. DO NOT EDIT"
1675 puts $as_fh "\t.cfi_startproc"
1676 puts $as_fh "\t.cfi_endproc"
1677 close $as_fh
1678 remote_download host $as_file
1679 verbose -log "Checking CFI support:"
1680 rename "perror" "check_as_cfi_perror"
1681 proc perror { args } { }
1682 set success [ld_assemble $as $as_file "/dev/null"]
1683 rename "perror" ""
1684 rename "check_as_cfi_perror" "perror"
1685 #remote_file host delete $as_file
1686 set check_as_cfi_result $success
1687 return $success
1688 }
1689
1690 # Provide virtual target "cfi" for targets supporting CFI.
1691
1692 rename "istarget" "istarget_ld"
1693 proc istarget { target } {
1694 if {$target == "cfi"} {
1695 return [check_as_cfi]
1696 }
1697 return [istarget_ld $target]
1698 }