fixed bash/dash/sh issue (Ubuntu)
[zpugcc/jano.git] / toolchain / binutils / ld / testsuite / lib / ld-lib.exp
blobacb7a5d175defc44761bbf195fbda6ab43f73579
1 # Support routines for LD testsuite.
2 # Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3 # Free Software Foundation, Inc.
5 # This file is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 # default_ld_version
21 # extract and print the version number of ld
23 proc default_ld_version { ld } {
24 global host_triplet
26 if { [which $ld] == 0 } then {
27 perror "$ld does not exist"
28 exit 1
31 catch "exec $ld --version" tmp
32 set tmp [prune_warnings $tmp]
33 regexp "\[^\n\]* (cygnus-|)(\[-0-9.a-zA-Z-\]+)\[\r\n\].*" $tmp version cyg number
34 if [info exists number] then {
35 clone_output "$ld $number\n"
40 # default_ld_relocate
41 # link an object using relocation
43 proc default_ld_relocate { ld target objects } {
44 global HOSTING_EMU
45 global host_triplet
47 if { [which $ld] == 0 } then {
48 perror "$ld does not exist"
49 return 0
52 verbose -log "$ld $HOSTING_EMU -o $target -r $objects"
54 catch "exec $ld $HOSTING_EMU -o $target -r $objects" exec_output
55 set exec_output [prune_warnings $exec_output]
56 if [string match "" $exec_output] then {
57 return 1
58 } else {
59 verbose -log "$exec_output"
60 return 0
64 # Check to see if ld is being invoked with a non-endian output format
66 proc is_endian_output_format { object_flags } {
68 if {[string match "*-oformat binary*" $object_flags] || \
69 [string match "*-oformat ieee*" $object_flags] || \
70 [string match "*-oformat ihex*" $object_flags] || \
71 [string match "*-oformat netbsd-core*" $object_flags] || \
72 [string match "*-oformat srec*" $object_flags] || \
73 [string match "*-oformat tekhex*" $object_flags] || \
74 [string match "*-oformat trad-core*" $object_flags] } then {
75 return 0
76 } else {
77 return 1
81 # Look for big-endian or little-endian switches in the multlib
82 # options and translate these into a -EB or -EL switch. Note
83 # we cannot rely upon proc process_multilib_options to do this
84 # for us because for some targets the compiler does not support
85 # -EB/-EL but it does support -mbig-endian/-mlittle-endian, and
86 # the site.exp file will include the switch "-mbig-endian"
87 # (rather than "big-endian") which is not detected by proc
88 # process_multilib_options.
90 proc big_or_little_endian {} {
92 if [board_info [target_info name] exists multilib_flags] {
93 set tmp_flags " [board_info [target_info name] multilib_flags]";
95 foreach x $tmp_flags {
96 case $x in {
97 {*big*endian eb EB -eb -EB -mb} {
98 set flags " -EB"
99 return $flags
101 {*little*endian el EL -el -EL -ml} {
102 set flags " -EL"
103 return $flags
109 set flags ""
110 return $flags
114 # default_ld_link
115 # link a program using ld
117 proc default_ld_link { ld target objects } {
118 global HOSTING_EMU
119 global HOSTING_CRT0
120 global HOSTING_LIBS
121 global LIBS
122 global host_triplet
123 global link_output
125 set objs "$HOSTING_CRT0 $objects"
126 set libs "$LIBS $HOSTING_LIBS"
128 if { [which $ld] == 0 } then {
129 perror "$ld does not exist"
130 return 0
133 if [is_endian_output_format $objects] then {
134 set flags [big_or_little_endian]
135 } else {
136 set flags ""
138 verbose -log "$ld $HOSTING_EMU $flags -o $target $objs $libs"
140 catch "exec $ld $HOSTING_EMU $flags -o $target $objs $libs" link_output
141 set exec_output [prune_warnings $link_output]
142 if [string match "" $link_output] then {
143 return 1
144 } else {
145 verbose -log "$link_output"
146 return 0
151 # default_ld_simple_link
152 # link a program using ld, without including any libraries
154 proc default_ld_simple_link { ld target objects } {
155 global host_triplet
156 global link_output
157 global gcc_ld_flag
159 if { [which $ld] == 0 } then {
160 perror "$ld does not exist"
161 return 0
164 if [is_endian_output_format $objects] then {
165 set flags [big_or_little_endian]
166 } else {
167 set flags ""
170 # If we are compiling with gcc, we want to add gcc_ld_flag to
171 # flags. Rather than determine this in some complex way, we guess
172 # based on the name of the compiler.
173 set ldexe $ld
174 set ldparm [string first " " $ld]
175 if { $ldparm > 0 } then {
176 set ldexe [string range $ld 0 $ldparm]
178 set ldexe [string replace $ldexe 0 [string last "/" $ldexe] ""]
179 if {[string match "*gcc*" $ldexe] || [string match "*++*" $ldexe]} then {
180 set flags "$gcc_ld_flag $flags"
183 verbose -log "$ld $flags -o $target $objects"
185 catch "exec $ld $flags -o $target $objects" link_output
186 set exec_output [prune_warnings $link_output]
188 # We don't care if we get a warning about a non-existent start
189 # symbol, since the default linker script might use ENTRY.
190 regsub -all "(^|\n)(\[^\n\]*: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
192 if [string match "" $exec_output] then {
193 return 1
194 } else {
195 verbose -log "$exec_output"
196 return 0
201 # default_ld_compile
202 # compile an object using cc
204 proc default_ld_compile { cc source object } {
205 global CFLAGS
206 global srcdir
207 global subdir
208 global host_triplet
209 global gcc_gas_flag
211 set cc_prog $cc
212 if {[llength $cc_prog] > 1} then {
213 set cc_prog [lindex $cc_prog 0]
215 if {[which $cc_prog] == 0} then {
216 perror "$cc_prog does not exist"
217 return 0
220 catch "exec rm -f $object" exec_output
222 set flags "-I$srcdir/$subdir $CFLAGS"
224 # If we are compiling with gcc, we want to add gcc_gas_flag to
225 # flags. Rather than determine this in some complex way, we guess
226 # based on the name of the compiler.
227 set ccexe $cc
228 set ccparm [string first " " $cc]
229 if { $ccparm > 0 } then {
230 set ccexe [string range $cc 0 $ccparm]
232 set ccexe [string replace $ccexe 0 [string last "/" $ccexe] ""]
233 if {[string match "*gcc*" $ccexe] || [string match "*++*" $ccexe]} then {
234 set flags "$gcc_gas_flag $flags"
237 if [board_info [target_info name] exists multilib_flags] {
238 append flags " [board_info [target_info name] multilib_flags]";
241 verbose -log "$cc $flags -c $source -o $object"
243 catch "exec $cc $flags -c $source -o $object" exec_output
244 set exec_output [prune_warnings $exec_output]
245 if [string match "" $exec_output] then {
246 if {![file exists $object]} then {
247 regexp ".*/(\[^/\]*)$" $source all dobj
248 regsub "\\.c" $dobj ".o" realobj
249 verbose "looking for $realobj"
250 if {[file exists $realobj]} then {
251 verbose -log "mv $realobj $object"
252 catch "exec mv $realobj $object" exec_output
253 set exec_output [prune_warnings $exec_output]
254 if {![string match "" $exec_output]} then {
255 verbose -log "$exec_output"
256 perror "could not move $realobj to $object"
257 return 0
259 } else {
260 perror "$object not found after compilation"
261 return 0
264 return 1
265 } else {
266 verbose -log "$exec_output"
267 perror "$source: compilation failed"
268 return 0
273 # default_ld_assemble
274 # assemble a file
276 proc default_ld_assemble { as source object } {
277 global ASFLAGS
278 global host_triplet
280 if {[which $as] == 0} then {
281 perror "$as does not exist"
282 return 0
285 if ![info exists ASFLAGS] { set ASFLAGS "" }
287 set flags [big_or_little_endian]
289 verbose -log "$as $flags $ASFLAGS -o $object $source"
291 catch "exec $as $flags $ASFLAGS -o $object $source" exec_output
292 set exec_output [prune_warnings $exec_output]
293 if [string match "" $exec_output] then {
294 return 1
295 } else {
296 verbose -log "$exec_output"
297 perror "$source: assembly failed"
298 return 0
303 # default_ld_nm
304 # run nm on a file, putting the result in the array nm_output
306 proc default_ld_nm { nm nmflags object } {
307 global NMFLAGS
308 global nm_output
309 global host_triplet
311 if {[which $nm] == 0} then {
312 perror "$nm does not exist"
313 return 0
316 if {[info exists nm_output]} {
317 unset nm_output
320 if ![info exists NMFLAGS] { set NMFLAGS "" }
322 # Ensure consistent sorting of symbols
323 if {[info exists env(LC_ALL)]} {
324 set old_lc_all $env(LC_ALL)
326 set env(LC_ALL) "C"
327 verbose -log "$nm $NMFLAGS $nmflags $object >tmpdir/nm.out"
329 catch "exec $nm $NMFLAGS $nmflags $object >tmpdir/nm.out" exec_output
330 if {[info exists old_lc_all]} {
331 set env(LC_ALL) $old_lc_all
332 } else {
333 unset env(LC_ALL)
335 set exec_output [prune_warnings $exec_output]
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
346 close $file
347 return 1
348 } else {
349 verbose -log "$exec_output"
350 perror "$object: nm failed"
351 return 0
356 # is_elf_format
357 # true if the object format is known to be ELF
359 proc is_elf_format {} {
360 if { ![istarget *-*-sysv4*] \
361 && ![istarget *-*-unixware*] \
362 && ![istarget *-*-elf*] \
363 && ![istarget *-*-eabi*] \
364 && ![istarget hppa*64*-*-hpux*] \
365 && ![istarget *-*-linux*] \
366 && ![istarget frv-*-uclinux*] \
367 && ![istarget *-*-irix5*] \
368 && ![istarget *-*-irix6*] \
369 && ![istarget *-*-netbsd*] \
370 && ![istarget *-*-solaris2*] } {
371 return 0
374 if { [istarget *-*-linux*aout*] \
375 || [istarget *-*-linux*oldld*] } {
376 return 0
379 if { ![istarget *-*-netbsdelf*] \
380 && ([istarget *-*-netbsd*aout*] \
381 || [istarget *-*-netbsdpe*] \
382 || [istarget arm*-*-netbsd*] \
383 || [istarget sparc-*-netbsd*] \
384 || [istarget i*86-*-netbsd*] \
385 || [istarget m68*-*-netbsd*] \
386 || [istarget vax-*-netbsd*] \
387 || [istarget ns32k-*-netbsd*]) } {
388 return 0
390 return 1
394 # is_elf64
395 # true if the object format is known to be 64bit ELF
396 proc is_elf64 { binary_file } {
397 global READELF
398 global READELFFLAGS
400 set readelf_size ""
401 catch "exec $READELF $READELFFLAGS -h $binary_file > readelf.out" got
403 if ![string match "" $got] then {
404 return 0
407 if { ![regexp "\n\[ \]*Class:\[ \]*ELF(\[0-9\]+)\n" \
408 [file_contents readelf.out] nil readelf_size] } {
409 return 0
412 if { $readelf_size == "64" } {
413 return 1
416 return 0
420 # simple_diff
421 # compares two files line-by-line
422 # returns differences if exist
423 # returns null if file(s) cannot be opened
425 proc simple_diff { file_1 file_2 } {
426 global target
428 set eof -1
429 set differences 0
431 if [file exists $file_1] then {
432 set file_a [open $file_1 r]
433 } else {
434 warning "$file_1 doesn't exist"
435 return
438 if [file exists $file_2] then {
439 set file_b [open $file_2 r]
440 } else {
441 fail "$file_2 doesn't exist"
442 return
445 verbose "# Diff'ing: $file_1 $file_2\n" 2
447 while { [gets $file_a line] != $eof } {
448 if [regexp "^#.*$" $line] then {
449 continue
450 } else {
451 lappend list_a $line
454 close $file_a
456 while { [gets $file_b line] != $eof } {
457 if [regexp "^#.*$" $line] then {
458 continue
459 } else {
460 lappend list_b $line
463 close $file_b
465 for { set i 0 } { $i < [llength $list_a] } { incr i } {
466 set line_a [lindex $list_a $i]
467 set line_b [lindex $list_b $i]
469 verbose "\t$file_1: $i: $line_a\n" 3
470 verbose "\t$file_2: $i: $line_b\n" 3
471 if [string compare $line_a $line_b] then {
472 verbose -log "\t$file_1: $i: $line_a\n"
473 verbose -log "\t$file_2: $i: $line_b\n"
475 fail "Test: $target"
476 return
480 if { [llength $list_a] != [llength $list_b] } {
481 fail "Test: $target"
482 return
485 if $differences<1 then {
486 pass "Test: $target"
490 # run_dump_test FILE
491 # Copied from gas testsuite, tweaked and further extended.
493 # Assemble a .s file, then run some utility on it and check the output.
495 # There should be an assembly language file named FILE.s in the test
496 # suite directory, and a pattern file called FILE.d. `run_dump_test'
497 # will assemble FILE.s, run some tool like `objdump', `objcopy', or
498 # `nm' on the .o file to produce textual output, and then analyze that
499 # with regexps. The FILE.d file specifies what program to run, and
500 # what to expect in its output.
502 # The FILE.d file begins with zero or more option lines, which specify
503 # flags to pass to the assembler, the program to run to dump the
504 # assembler's output, and the options it wants. The option lines have
505 # the syntax:
507 # # OPTION: VALUE
509 # OPTION is the name of some option, like "name" or "objdump", and
510 # VALUE is OPTION's value. The valid options are described below.
511 # Whitespace is ignored everywhere, except within VALUE. The option
512 # list ends with the first line that doesn't match the above syntax
513 # (hmm, not great for error detection).
515 # The interesting options are:
517 # name: TEST-NAME
518 # The name of this test, passed to DejaGNU's `pass' and `fail'
519 # commands. If omitted, this defaults to FILE, the root of the
520 # .s and .d files' names.
522 # as: FLAGS
523 # When assembling, pass FLAGS to the assembler.
524 # If assembling several files, you can pass different assembler
525 # options in the "source" directives. See below.
527 # ld: FLAGS
528 # Link assembled files using FLAGS, in the order of the "source"
529 # directives, when using multiple files.
531 # objcopy_linked_file: FLAGS
532 # Run objcopy on the linked file with the specified flags.
533 # This lets you transform the linked file using objcopy, before the
534 # result is analyzed by an analyzer program specified below (which
535 # may in turn *also* be objcopy).
537 # PROG: PROGRAM-NAME
538 # The name of the program to run to analyze the .o file produced
539 # by the assembler or the linker output. This can be omitted;
540 # run_dump_test will guess which program to run by seeing which of
541 # the flags options below is present.
543 # objdump: FLAGS
544 # nm: FLAGS
545 # objcopy: FLAGS
546 # Use the specified program to analyze the assembler or linker
547 # output file, and pass it FLAGS, in addition to the output name.
548 # Note that they are run with LC_ALL=C in the environment to give
549 # consistent sorting of symbols.
551 # source: SOURCE [FLAGS]
552 # Assemble the file SOURCE.s using the flags in the "as" directive
553 # and the (optional) FLAGS. If omitted, the source defaults to
554 # FILE.s.
555 # This is useful if several .d files want to share a .s file.
556 # More than one "source" directive can be given, which is useful
557 # when testing linking.
559 # xfail: TARGET
560 # The test is expected to fail on TARGET. This may occur more than
561 # once.
563 # target: TARGET
564 # Only run the test for TARGET. This may occur more than once; the
565 # target being tested must match at least one.
567 # notarget: TARGET
568 # Do not run the test for TARGET. This may occur more than once;
569 # the target being tested must not match any of them.
571 # error: REGEX
572 # An error with message matching REGEX must be emitted for the test
573 # to pass. The PROG, objdump, nm and objcopy options have no
574 # meaning and need not supplied if this is present.
576 # Each option may occur at most once unless otherwise mentioned.
578 # After the option lines come regexp lines. `run_dump_test' calls
579 # `regexp_diff' to compare the output of the dumping tool against the
580 # regexps in FILE.d. `regexp_diff' is defined later in this file; see
581 # further comments there.
583 proc run_dump_test { name } {
584 global subdir srcdir
585 global OBJDUMP NM AS OBJCOPY READELF LD
586 global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS LDFLAGS
587 global host_triplet runtests
588 global env
590 if [string match "*/*" $name] {
591 set file $name
592 set name [file tail $name]
593 } else {
594 set file "$srcdir/$subdir/$name"
597 if ![runtest_file_p $runtests $name] then {
598 return
601 set opt_array [slurp_options "${file}.d"]
602 if { $opt_array == -1 } {
603 perror "error reading options from $file.d"
604 unresolved $subdir/$name
605 return
607 set dumpfile tmpdir/dump.out
608 set run_ld 0
609 set run_objcopy 0
610 set opts(as) {}
611 set opts(ld) {}
612 set opts(xfail) {}
613 set opts(target) {}
614 set opts(notarget) {}
615 set opts(objdump) {}
616 set opts(nm) {}
617 set opts(objcopy) {}
618 set opts(readelf) {}
619 set opts(name) {}
620 set opts(PROG) {}
621 set opts(source) {}
622 set opts(error) {}
623 set opts(objcopy_linked_file) {}
624 set asflags(${file}.s) {}
626 foreach i $opt_array {
627 set opt_name [lindex $i 0]
628 set opt_val [lindex $i 1]
629 if ![info exists opts($opt_name)] {
630 perror "unknown option $opt_name in file $file.d"
631 unresolved $subdir/$name
632 return
635 switch -- $opt_name {
636 xfail {}
637 target {}
638 notarget {}
639 source {
640 # Move any source-specific as-flags to a separate array to
641 # simplify processing.
642 if { [llength $opt_val] > 1 } {
643 set asflags([lindex $opt_val 0]) [lrange $opt_val 1 end]
644 set opt_val [lindex $opt_val 0]
645 } else {
646 set asflags($opt_val) {}
649 default {
650 if [string length $opts($opt_name)] {
651 perror "option $opt_name multiply set in $file.d"
652 unresolved $subdir/$name
653 return
656 # A single "# ld:" with no options should do the right thing.
657 if { $opt_name == "ld" } {
658 set run_ld 1
660 # Likewise objcopy_linked_file.
661 if { $opt_name == "objcopy_linked_file" } {
662 set run_objcopy 1
666 set opts($opt_name) [concat $opts($opt_name) $opt_val]
669 # Decide early whether we should run the test for this target.
670 if { [llength $opts(target)] > 0 } {
671 set targmatch 0
672 foreach targ $opts(target) {
673 if [istarget $targ] {
674 set targmatch 1
675 break
678 if { $targmatch == 0 } {
679 return
682 foreach targ $opts(notarget) {
683 if [istarget $targ] {
684 return
688 if {$opts(PROG) != ""} {
689 switch -- $opts(PROG) {
690 objdump
691 { set program objdump }
693 { set program nm }
694 objcopy
695 { set program objcopy }
696 readelf
697 { set program readelf }
698 default
699 { perror "unrecognized program option $opts(PROG) in $file.d"
700 unresolved $subdir/$name
701 return }
703 } elseif { $opts(error) != "" } {
704 # It's meaningless to require an output-testing method when we
705 # expect an error. For simplicity, we fake an arbitrary method.
706 set program "nm"
707 } else {
708 # Guess which program to run, by seeing which option was specified.
709 set program ""
710 foreach p {objdump objcopy nm readelf} {
711 if {$opts($p) != ""} {
712 if {$program != ""} {
713 perror "ambiguous dump program in $file.d"
714 unresolved $subdir/$name
715 return
716 } else {
717 set program $p
721 if {$program == ""} {
722 perror "dump program unspecified in $file.d"
723 unresolved $subdir/$name
724 return
728 set progopts1 $opts($program)
729 eval set progopts \$[string toupper $program]FLAGS
730 eval set binary \$[string toupper $program]
731 if { $opts(name) == "" } {
732 set testname "$subdir/$name"
733 } else {
734 set testname $opts(name)
737 if { $opts(source) == "" } {
738 set sourcefiles [list ${file}.s]
739 } else {
740 set sourcefiles {}
741 foreach sf $opts(source) {
742 if { [string match "/*" $sf] } {
743 lappend sourcefiles "$sf"
745 lappend sourcefiles "$srcdir/$subdir/$sf"
747 # Must have asflags indexed on source name.
748 set asflags($srcdir/$subdir/$sf) $asflags($sf)
752 # Time to setup xfailures.
753 foreach targ $opts(xfail) {
754 setup_xfail $targ
757 # Assemble each file.
758 set objfiles {}
759 for { set i 0 } { $i < [llength $sourcefiles] } { incr i } {
760 set sourcefile [lindex $sourcefiles $i]
762 set objfile "tmpdir/dump$i.o"
763 lappend objfiles $objfile
764 set cmd "$AS $ASFLAGS $opts(as) $asflags($sourcefile) -o $objfile $sourcefile"
766 send_log "$cmd\n"
767 set cmdret [catch "exec $cmd" comp_output]
768 set comp_output [prune_warnings $comp_output]
770 # We accept errors at assembly stage too, unless we're supposed to
771 # link something.
772 if { $cmdret != 0 || ![string match "" $comp_output] } then {
773 send_log "$comp_output\n"
774 verbose "$comp_output" 3
775 if { $opts(error) != "" && $run_ld == 0 } {
776 if [regexp $opts(error) $comp_output] {
777 pass $testname
778 return
781 fail $testname
782 return
786 # Perhaps link the file(s).
787 if { $run_ld } {
788 set objfile "tmpdir/dump"
790 # Add -L$srcdir/$subdir so that the linker command can use
791 # linker scripts in the source directory.
792 set cmd "$LD $LDFLAGS -L$srcdir/$subdir \
793 $opts(ld) -o $objfile $objfiles"
795 send_log "$cmd\n"
796 set cmdret [catch "exec $cmd" comp_output]
797 set comp_output [prune_warnings $comp_output]
799 if { $cmdret != 0 || ![string match "" $comp_output] } then {
800 verbose -log "failed with: <$comp_output>, expected: <$opts(error)>"
801 send_log "$comp_output\n"
802 verbose "$comp_output" 3
803 if { $opts(error) != "" && $run_objcopy == 0 } {
804 if [regexp $opts(error) $comp_output] {
805 pass $testname
806 return
809 fail $testname
810 return
813 if { $run_objcopy } {
814 set infile $objfile
815 set objfile "tmpdir/dump1"
817 # Note that we don't use OBJCOPYFLAGS here; any flags must be
818 # explicitly specified.
819 set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile"
821 send_log "$cmd\n"
822 set cmdret [catch "exec $cmd" comp_output]
823 set comp_output [prune_warnings $comp_output]
825 if { $cmdret != 0 || ![string match "" $comp_output] } then {
826 verbose -log "failed with: <$comp_output>, expected: <$opts(error)>"
827 send_log "$comp_output\n"
828 verbose "$comp_output" 3
829 if { $opts(error) != "" } {
830 if [regexp $opts(error) $comp_output] {
831 pass $testname
832 return
835 fail $testname
836 return
839 } else {
840 set objfile "tmpdir/dump0.o"
843 # We must not have expected failure if we get here.
844 if { $opts(error) != "" } {
845 fail $testname
846 return
849 if { [which $binary] == 0 } {
850 untested $testname
851 return
854 if { $progopts1 == "" } { set $progopts1 "-r" }
855 verbose "running $binary $progopts $progopts1" 3
857 # Objcopy, unlike the other two, won't send its output to stdout,
858 # so we have to run it specially.
859 set cmd "$binary $progopts $progopts1 $objfile > $dumpfile"
860 if { $program == "objcopy" } {
861 set cmd "$binary $progopts $progopts1 $objfile $dumpfile"
864 # Ensure consistent sorting of symbols
865 if {[info exists env(LC_ALL)]} {
866 set old_lc_all $env(LC_ALL)
868 set env(LC_ALL) "C"
869 send_log "$cmd\n"
870 catch "exec $cmd" comp_output
871 if {[info exists old_lc_all]} {
872 set env(LC_ALL) $old_lc_all
873 } else {
874 unset env(LC_ALL)
876 set comp_output [prune_warnings $comp_output]
877 if ![string match "" $comp_output] then {
878 send_log "$comp_output\n"
879 fail $testname
880 return
883 verbose_eval {[file_contents $dumpfile]} 3
884 if { [regexp_diff $dumpfile "${file}.d"] } then {
885 fail $testname
886 verbose "output is [file_contents $dumpfile]" 2
887 return
890 pass $testname
893 proc slurp_options { file } {
894 if [catch { set f [open $file r] } x] {
895 #perror "couldn't open `$file': $x"
896 perror "$x"
897 return -1
899 set opt_array {}
900 # whitespace expression
901 set ws {[ ]*}
902 set nws {[^ ]*}
903 # whitespace is ignored anywhere except within the options list;
904 # option names are alphabetic plus underscore only.
905 set pat "^#${ws}(\[a-zA-Z_\]*)$ws:${ws}(.*)$ws\$"
906 while { [gets $f line] != -1 } {
907 set line [string trim $line]
908 # Whitespace here is space-tab.
909 if [regexp $pat $line xxx opt_name opt_val] {
910 # match!
911 lappend opt_array [list $opt_name $opt_val]
912 } else {
913 break
916 close $f
917 return $opt_array
920 # regexp_diff, copied from gas, based on simple_diff above.
921 # compares two files line-by-line
922 # file1 contains strings, file2 contains regexps and #-comments
923 # blank lines are ignored in either file
924 # returns non-zero if differences exist
926 proc regexp_diff { file_1 file_2 } {
928 set eof -1
929 set end_1 0
930 set end_2 0
931 set differences 0
932 set diff_pass 0
934 if [file exists $file_1] then {
935 set file_a [open $file_1 r]
936 } else {
937 warning "$file_1 doesn't exist"
938 return 1
941 if [file exists $file_2] then {
942 set file_b [open $file_2 r]
943 } else {
944 fail "$file_2 doesn't exist"
945 close $file_a
946 return 1
949 verbose " Regexp-diff'ing: $file_1 $file_2" 2
951 while { 1 } {
952 set line_a ""
953 set line_b ""
954 while { [string length $line_a] == 0 } {
955 if { [gets $file_a line_a] == $eof } {
956 set end_1 1
957 break
960 while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
961 if [ string match "#pass" $line_b ] {
962 set end_2 1
963 set diff_pass 1
964 break
965 } elseif [ string match "#..." $line_b ] {
966 if { [gets $file_b line_b] == $eof } {
967 set end_2 1
968 break
970 verbose "looking for \"^$line_b$\"" 3
971 while { ![regexp "^$line_b$" "$line_a"] } {
972 verbose "skipping \"$line_a\"" 3
973 if { [gets $file_a line_a] == $eof } {
974 set end_1 1
975 break
978 break
980 if { [gets $file_b line_b] == $eof } {
981 set end_2 1
982 break
986 if { $diff_pass } {
987 break
988 } elseif { $end_1 && $end_2 } {
989 break
990 } elseif { $end_1 } {
991 send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
992 verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
993 set differences 1
994 break
995 } elseif { $end_2 } {
996 send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
997 verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
998 set differences 1
999 break
1000 } else {
1001 verbose "regexp \"^$line_b$\"\nline \"$line_a\"" 3
1002 if ![regexp "^$line_b$" "$line_a"] {
1003 send_log "regexp_diff match failure\n"
1004 send_log "regexp \"^$line_b$\"\nline \"$line_a\"\n"
1005 set differences 1
1010 if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
1011 send_log "$file_1 and $file_2 are different lengths\n"
1012 verbose "$file_1 and $file_2 are different lengths" 3
1013 set differences 1
1016 close $file_a
1017 close $file_b
1019 return $differences
1022 proc file_contents { filename } {
1023 set file [open $filename r]
1024 set contents [read $file]
1025 close $file
1026 return $contents
1029 # List contains test-items with 3 items followed by 2 lists, one item and
1030 # one optional item:
1031 # 0:name 1:ld options 2:assembler options
1032 # 3:filenames of assembler files 4: action and options. 5: name of output file
1033 # 6:compiler flags (optional)
1035 # Actions:
1036 # objdump: Apply objdump options on result. Compare with regex (last arg).
1037 # nm: Apply nm options on result. Compare with regex (last arg).
1038 # readelf: Apply readelf options on result. Compare with regex (last arg).
1040 proc run_ld_link_tests { ldtests } {
1041 global ld
1042 global as
1043 global nm
1044 global objdump
1045 global READELF
1046 global srcdir
1047 global subdir
1048 global env
1049 global CC
1050 global CFLAGS
1052 foreach testitem $ldtests {
1053 set testname [lindex $testitem 0]
1054 set ld_options [lindex $testitem 1]
1055 set as_options [lindex $testitem 2]
1056 set src_files [lindex $testitem 3]
1057 set actions [lindex $testitem 4]
1058 set binfile tmpdir/[lindex $testitem 5]
1059 set cflags [lindex $testitem 6]
1060 set objfiles {}
1061 set is_unresolved 0
1062 set failed 0
1064 # verbose -log "Testname is $testname"
1065 # verbose -log "ld_options is $ld_options"
1066 # verbose -log "as_options is $as_options"
1067 # verbose -log "src_files is $src_files"
1068 # verbose -log "actions is $actions"
1069 # verbose -log "binfile is $binfile"
1071 # Assemble each file in the test.
1072 foreach src_file $src_files {
1073 set objfile "tmpdir/[file rootname $src_file].o"
1074 lappend objfiles $objfile
1076 if { [file extension $src_file] == ".c" } {
1077 set as_file "tmpdir/[file rootname $src_file].s"
1078 if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
1079 set is_unresolved 1
1080 break
1082 } else {
1083 set as_file "$srcdir/$subdir/$src_file"
1085 if ![ld_assemble $as "$as_options $as_file" $objfile] {
1086 set is_unresolved 1
1087 break
1091 # Catch assembler errors.
1092 if { $is_unresolved != 0 } {
1093 unresolved $testname
1094 continue
1097 if ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
1098 fail $testname
1099 } else {
1100 set failed 0
1101 foreach actionlist $actions {
1102 set action [lindex $actionlist 0]
1103 set progopts [lindex $actionlist 1]
1105 # There are actions where we run regexp_diff on the
1106 # output, and there are other actions (presumably).
1107 # Handling of the former look the same.
1108 set dump_prog ""
1109 switch -- $action {
1110 objdump
1111 { set dump_prog $objdump }
1113 { set dump_prog $nm }
1114 readelf
1115 { set dump_prog $READELF }
1116 default
1118 perror "Unrecognized action $action"
1119 set is_unresolved 1
1120 break
1124 if { $dump_prog != "" } {
1125 set dumpfile [lindex $actionlist 2]
1126 set binary $dump_prog
1128 # Ensure consistent sorting of symbols
1129 if {[info exists env(LC_ALL)]} {
1130 set old_lc_all $env(LC_ALL)
1132 set env(LC_ALL) "C"
1133 set cmd "$binary $progopts $binfile > dump.out"
1134 send_log "$cmd\n"
1135 catch "exec $cmd" comp_output
1136 if {[info exists old_lc_all]} {
1137 set env(LC_ALL) $old_lc_all
1138 } else {
1139 unset env(LC_ALL)
1141 set comp_output [prune_warnings $comp_output]
1143 if ![string match "" $comp_output] then {
1144 send_log "$comp_output\n"
1145 set failed 1
1146 break
1149 if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1150 verbose "output is [file_contents "dump.out"]" 2
1151 set failed 1
1152 break
1157 if { $failed != 0 } {
1158 fail $testname
1159 } else { if { $is_unresolved == 0 } {
1160 pass $testname
1164 # Catch action errors.
1165 if { $is_unresolved != 0 } {
1166 unresolved $testname
1167 continue
1173 proc verbose_eval { expr { level 1 } } {
1174 global verbose
1175 if $verbose>$level then { eval verbose "$expr" $level }
1178 # This definition is taken from an unreleased version of DejaGnu. Once
1179 # that version gets released, and has been out in the world for a few
1180 # months at least, it may be safe to delete this copy.
1181 if ![string length [info proc prune_warnings]] {
1183 # prune_warnings -- delete various system verbosities from TEXT
1185 # An example is:
1186 # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
1188 # Sites with particular verbose os's may wish to override this in site.exp.
1190 proc prune_warnings { text } {
1191 # This is from sun4's. Do it for all machines for now.
1192 # The "\\1" is to try to preserve a "\n" but only if necessary.
1193 regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
1195 # It might be tempting to get carried away and delete blank lines, etc.
1196 # Just delete *exactly* what we're ask to, and that's it.
1197 return $text