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 # Free Software Foundation, Inc.
4 #
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.
9 #
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.
14 #
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.
18 #
19 #
20 # default_ld_version
21 # extract and print the version number of ld
22 #
23 proc default_ld_version { ld } {
24 global host_triplet
25
26 if { [which $ld] == 0 } then {
27 perror "$ld does not exist"
28 exit 1
29 }
30
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"
36 }
37 }
38
39 #
40 # default_ld_relocate
41 # link an object using relocation
42 #
43 proc default_ld_relocate { ld target objects } {
44 global HOSTING_EMU
45 global host_triplet
46
47 if { [which $ld] == 0 } then {
48 perror "$ld does not exist"
49 return 0
50 }
51
52 verbose -log "$ld $HOSTING_EMU -o $target -r $objects"
53
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
61 }
62 }
63
64 # Check to see if ld is being invoked with a non-endian output format
65
66 proc is_endian_output_format { object_flags } {
67
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
78 }
79 }
80
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.
89
90 proc big_or_little_endian {} {
91
92 if [board_info [target_info name] exists multilib_flags] {
93 set tmp_flags " [board_info [target_info name] multilib_flags]";
94
95 foreach x $tmp_flags {
96 case $x in {
97 {*big*endian eb EB -eb -EB} {
98 set flags " -EB"
99 return $flags
100 }
101 {*little*endian el EL -el -EL} {
102 set flags " -EL"
103 return $flags
104 }
105 }
106 }
107 }
108
109 set flags ""
110 return $flags
111 }
112
113 #
114 # default_ld_link
115 # link a program using ld
116 #
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
124
125 set objs "$HOSTING_CRT0 $objects"
126 set libs "$LIBS $HOSTING_LIBS"
127
128 if { [which $ld] == 0 } then {
129 perror "$ld does not exist"
130 return 0
131 }
132
133 if [is_endian_output_format $objects] then {
134 set flags [big_or_little_endian]
135 } else {
136 set flags ""
137 }
138 verbose -log "$ld $HOSTING_EMU $flags -o $target $objs $libs"
139
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
147 }
148 }
149
150 #
151 # default_ld_simple_link
152 # link a program using ld, without including any libraries
153 #
154 proc default_ld_simple_link { ld target objects } {
155 global host_triplet
156 global link_output
157
158 if { [which $ld] == 0 } then {
159 perror "$ld does not exist"
160 return 0
161 }
162
163 if [is_endian_output_format $objects] then {
164 set flags [big_or_little_endian]
165 } else {
166 set flags ""
167 }
168
169 verbose -log "$ld $flags -o $target $objects"
170
171 catch "exec $ld $flags -o $target $objects" link_output
172 set exec_output [prune_warnings $link_output]
173
174 # We don't care if we get a warning about a non-existent start
175 # symbol, since the default linker script might use ENTRY.
176 regsub -all "(^|\n)(\[^\n\]*: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output
177
178 if [string match "" $exec_output] then {
179 return 1
180 } else {
181 verbose -log "$exec_output"
182 return 0
183 }
184 }
185
186 #
187 # default_ld_compile
188 # compile an object using cc
189 #
190 proc default_ld_compile { cc source object } {
191 global CFLAGS
192 global srcdir
193 global subdir
194 global host_triplet
195 global gcc_gas_flag
196
197 set cc_prog $cc
198 if {[llength $cc_prog] > 1} then {
199 set cc_prog [lindex $cc_prog 0]
200 }
201 if {[which $cc_prog] == 0} then {
202 perror "$cc_prog does not exist"
203 return 0
204 }
205
206 catch "exec rm -f $object" exec_output
207
208 set flags "-I$srcdir/$subdir $CFLAGS"
209
210 # If we are compiling with gcc, we want to add gcc_gas_flag to
211 # flags. Rather than determine this in some complex way, we guess
212 # based on the name of the compiler.
213 if {[string match "*gcc*" $cc] || [string match "*++*" $cc]} then {
214 set flags "$gcc_gas_flag $flags"
215 }
216
217 if [board_info [target_info name] exists multilib_flags] {
218 append flags " [board_info [target_info name] multilib_flags]";
219 }
220
221 verbose -log "$cc $flags -c $source -o $object"
222
223 catch "exec $cc $flags -c $source -o $object" exec_output
224 set exec_output [prune_warnings $exec_output]
225 if [string match "" $exec_output] then {
226 if {![file exists $object]} then {
227 regexp ".*/(\[^/\]*)$" $source all dobj
228 regsub "\\.c" $dobj ".o" realobj
229 verbose "looking for $realobj"
230 if {[file exists $realobj]} then {
231 verbose -log "mv $realobj $object"
232 catch "exec mv $realobj $object" exec_output
233 set exec_output [prune_warnings $exec_output]
234 if {![string match "" $exec_output]} then {
235 verbose -log "$exec_output"
236 perror "could not move $realobj to $object"
237 return 0
238 }
239 } else {
240 perror "$object not found after compilation"
241 return 0
242 }
243 }
244 return 1
245 } else {
246 verbose -log "$exec_output"
247 perror "$source: compilation failed"
248 return 0
249 }
250 }
251
252 #
253 # default_ld_assemble
254 # assemble a file
255 #
256 proc default_ld_assemble { as source object } {
257 global ASFLAGS
258 global host_triplet
259
260 if {[which $as] == 0} then {
261 perror "$as does not exist"
262 return 0
263 }
264
265 if ![info exists ASFLAGS] { set ASFLAGS "" }
266
267 set flags [big_or_little_endian]
268
269 verbose -log "$as $flags $ASFLAGS -o $object $source"
270
271 catch "exec $as $flags $ASFLAGS -o $object $source" exec_output
272 set exec_output [prune_warnings $exec_output]
273 if [string match "" $exec_output] then {
274 return 1
275 } else {
276 verbose -log "$exec_output"
277 perror "$source: assembly failed"
278 return 0
279 }
280 }
281
282 #
283 # default_ld_nm
284 # run nm on a file, putting the result in the array nm_output
285 #
286 proc default_ld_nm { nm nmflags object } {
287 global NMFLAGS
288 global nm_output
289 global host_triplet
290
291 if {[which $nm] == 0} then {
292 perror "$nm does not exist"
293 return 0
294 }
295
296 if {[info exists nm_output]} {
297 unset nm_output
298 }
299
300 if ![info exists NMFLAGS] { set NMFLAGS "" }
301
302 # Ensure consistent sorting of symbols
303 if {[info exists env(LC_ALL)]} {
304 set old_lc_all $env(LC_ALL)
305 }
306 set env(LC_ALL) "C"
307 verbose -log "$nm $NMFLAGS $nmflags $object >tmpdir/nm.out"
308
309 catch "exec $nm $NMFLAGS $nmflags $object >tmpdir/nm.out" exec_output
310 if {[info exists old_lc_all]} {
311 set env(LC_ALL) $old_lc_all
312 } else {
313 unset env(LC_ALL)
314 }
315 set exec_output [prune_warnings $exec_output]
316 if [string match "" $exec_output] then {
317 set file [open tmpdir/nm.out r]
318 while { [gets $file line] != -1 } {
319 verbose "$line" 2
320 if [regexp "^(\[0-9a-fA-F\]+) \[a-zA-Z0-9\] \\.*(.+)$" $line whole value name] {
321 set name [string trimleft $name "_"]
322 verbose "Setting nm_output($name) to 0x$value" 2
323 set nm_output($name) 0x$value
324 }
325 }
326 close $file
327 return 1
328 } else {
329 verbose -log "$exec_output"
330 perror "$object: nm failed"
331 return 0
332 }
333 }
334
335 #
336 # is_elf_format
337 # true if the object format is known to be ELF
338 #
339 proc is_elf_format {} {
340 if { ![istarget *-*-sysv4*] \
341 && ![istarget *-*-unixware*] \
342 && ![istarget *-*-elf*] \
343 && ![istarget *-*-eabi*] \
344 && ![istarget *-*-linux*] \
345 && ![istarget *-*-irix5*] \
346 && ![istarget *-*-irix6*] \
347 && ![istarget *-*-netbsd*] \
348 && ![istarget *-*-solaris2*] } {
349 return 0
350 }
351
352 if { [istarget *-*-linux*aout*] \
353 || [istarget *-*-linux*oldld*] } {
354 return 0
355 }
356
357 if { ![istarget *-*-netbsdelf*] \
358 && ([istarget *-*-netbsd*aout*] \
359 || [istarget *-*-netbsdpe*] \
360 || [istarget arm*-*-netbsd*] \
361 || [istarget sparc-*-netbsd*] \
362 || [istarget i*86-*-netbsd*] \
363 || [istarget m68*-*-netbsd*] \
364 || [istarget vax-*-netbsd*] \
365 || [istarget ns32k-*-netbsd*]) } {
366 return 0
367 }
368 return 1
369 }
370
371 #
372 # simple_diff
373 # compares two files line-by-line
374 # returns differences if exist
375 # returns null if file(s) cannot be opened
376 #
377 proc simple_diff { file_1 file_2 } {
378 global target
379
380 set eof -1
381 set differences 0
382
383 if [file exists $file_1] then {
384 set file_a [open $file_1 r]
385 } else {
386 warning "$file_1 doesn't exist"
387 return
388 }
389
390 if [file exists $file_2] then {
391 set file_b [open $file_2 r]
392 } else {
393 fail "$file_2 doesn't exist"
394 return
395 }
396
397 verbose "# Diff'ing: $file_1 $file_2\n" 2
398
399 while { [gets $file_a line] != $eof } {
400 if [regexp "^#.*$" $line] then {
401 continue
402 } else {
403 lappend list_a $line
404 }
405 }
406 close $file_a
407
408 while { [gets $file_b line] != $eof } {
409 if [regexp "^#.*$" $line] then {
410 continue
411 } else {
412 lappend list_b $line
413 }
414 }
415 close $file_b
416
417 for { set i 0 } { $i < [llength $list_a] } { incr i } {
418 set line_a [lindex $list_a $i]
419 set line_b [lindex $list_b $i]
420
421 verbose "\t$file_1: $i: $line_a\n" 3
422 verbose "\t$file_2: $i: $line_b\n" 3
423 if [string compare $line_a $line_b] then {
424 verbose -log "\t$file_1: $i: $line_a\n"
425 verbose -log "\t$file_2: $i: $line_b\n"
426
427 fail "Test: $target"
428 return
429 }
430 }
431
432 if { [llength $list_a] != [llength $list_b] } {
433 fail "Test: $target"
434 return
435 }
436
437 if $differences<1 then {
438 pass "Test: $target"
439 }
440 }
441
442 # run_dump_test FILE
443 # Copied from gas testsuite, tweaked and further extended.
444 #
445 # Assemble a .s file, then run some utility on it and check the output.
446 #
447 # There should be an assembly language file named FILE.s in the test
448 # suite directory, and a pattern file called FILE.d. `run_dump_test'
449 # will assemble FILE.s, run some tool like `objdump', `objcopy', or
450 # `nm' on the .o file to produce textual output, and then analyze that
451 # with regexps. The FILE.d file specifies what program to run, and
452 # what to expect in its output.
453 #
454 # The FILE.d file begins with zero or more option lines, which specify
455 # flags to pass to the assembler, the program to run to dump the
456 # assembler's output, and the options it wants. The option lines have
457 # the syntax:
458 #
459 # # OPTION: VALUE
460 #
461 # OPTION is the name of some option, like "name" or "objdump", and
462 # VALUE is OPTION's value. The valid options are described below.
463 # Whitespace is ignored everywhere, except within VALUE. The option
464 # list ends with the first line that doesn't match the above syntax
465 # (hmm, not great for error detection).
466 #
467 # The interesting options are:
468 #
469 # name: TEST-NAME
470 # The name of this test, passed to DejaGNU's `pass' and `fail'
471 # commands. If omitted, this defaults to FILE, the root of the
472 # .s and .d files' names.
473 #
474 # as: FLAGS
475 # When assembling, pass FLAGS to the assembler.
476 # If assembling several files, you can pass different assembler
477 # options in the "source" directives. See below.
478 #
479 # ld: FLAGS
480 # Link assembled files using FLAGS, in the order of the "source"
481 # directives, when using multiple files.
482 #
483 # objcopy_linked_file: FLAGS
484 # Run objcopy on the linked file with the specified flags.
485 # This lets you transform the linked file using objcopy, before the
486 # result is analyzed by an analyzer program specified below (which
487 # may in turn *also* be objcopy).
488 #
489 # PROG: PROGRAM-NAME
490 # The name of the program to run to analyze the .o file produced
491 # by the assembler or the linker output. This can be omitted;
492 # run_dump_test will guess which program to run by seeing which of
493 # the flags options below is present.
494 #
495 # objdump: FLAGS
496 # nm: FLAGS
497 # objcopy: FLAGS
498 # Use the specified program to analyze the assembler or linker
499 # output file, and pass it FLAGS, in addition to the output name.
500 # Note that they are run with LC_ALL=C in the environment to give
501 # consistent sorting of symbols.
502 #
503 # source: SOURCE [FLAGS]
504 # Assemble the file SOURCE.s using the flags in the "as" directive
505 # and the (optional) FLAGS. If omitted, the source defaults to
506 # FILE.s.
507 # This is useful if several .d files want to share a .s file.
508 # More than one "source" directive can be given, which is useful
509 # when testing linking.
510 #
511 # xfail: TARGET
512 # The test is expected to fail on TARGET. This may occur more than
513 # once.
514 #
515 # target: TARGET
516 # Only run the test for TARGET. This may occur more than once; the
517 # target being tested must match at least one.
518 #
519 # notarget: TARGET
520 # Do not run the test for TARGET. This may occur more than once;
521 # the target being tested must not match any of them.
522 #
523 # error: REGEX
524 # An error with message matching REGEX must be emitted for the test
525 # to pass. The PROG, objdump, nm and objcopy options have no
526 # meaning and need not supplied if this is present.
527 #
528 # Each option may occur at most once unless otherwise mentioned.
529 #
530 # After the option lines come regexp lines. `run_dump_test' calls
531 # `regexp_diff' to compare the output of the dumping tool against the
532 # regexps in FILE.d. `regexp_diff' is defined later in this file; see
533 # further comments there.
534
535 proc run_dump_test { name } {
536 global subdir srcdir
537 global OBJDUMP NM AS OBJCOPY READELF LD
538 global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS LDFLAGS
539 global host_triplet runtests
540 global env
541
542 if [string match "*/*" $name] {
543 set file $name
544 set name [file tail $name]
545 } else {
546 set file "$srcdir/$subdir/$name"
547 }
548
549 if ![runtest_file_p $runtests $name] then {
550 return
551 }
552
553 set opt_array [slurp_options "${file}.d"]
554 if { $opt_array == -1 } {
555 perror "error reading options from $file.d"
556 unresolved $subdir/$name
557 return
558 }
559 set dumpfile tmpdir/dump.out
560 set run_ld 0
561 set run_objcopy 0
562 set opts(as) {}
563 set opts(ld) {}
564 set opts(xfail) {}
565 set opts(target) {}
566 set opts(notarget) {}
567 set opts(objdump) {}
568 set opts(nm) {}
569 set opts(objcopy) {}
570 set opts(readelf) {}
571 set opts(name) {}
572 set opts(PROG) {}
573 set opts(source) {}
574 set opts(error) {}
575 set opts(objcopy_linked_file) {}
576 set asflags(${file}.s) {}
577
578 foreach i $opt_array {
579 set opt_name [lindex $i 0]
580 set opt_val [lindex $i 1]
581 if ![info exists opts($opt_name)] {
582 perror "unknown option $opt_name in file $file.d"
583 unresolved $subdir/$name
584 return
585 }
586
587 switch -- $opt_name {
588 xfail {}
589 target {}
590 notarget {}
591 source {
592 # Move any source-specific as-flags to a separate array to
593 # simplify processing.
594 if { [llength $opt_val] > 1 } {
595 set asflags([lindex $opt_val 0]) [lrange $opt_val 1 end]
596 set opt_val [lindex $opt_val 0]
597 } else {
598 set asflags($opt_val) {}
599 }
600 }
601 default {
602 if [string length $opts($opt_name)] {
603 perror "option $opt_name multiply set in $file.d"
604 unresolved $subdir/$name
605 return
606 }
607
608 # A single "# ld:" with no options should do the right thing.
609 if { $opt_name == "ld" } {
610 set run_ld 1
611 }
612 # Likewise objcopy_linked_file.
613 if { $opt_name == "objcopy_linked_file" } {
614 set run_objcopy 1
615 }
616 }
617 }
618 set opts($opt_name) [concat $opts($opt_name) $opt_val]
619 }
620
621 # Decide early whether we should run the test for this target.
622 if { [llength $opts(target)] > 0 } {
623 set targmatch 0
624 foreach targ $opts(target) {
625 if [istarget $targ] {
626 set targmatch 1
627 break
628 }
629 }
630 if { $targmatch == 0 } {
631 return
632 }
633 }
634 foreach targ $opts(notarget) {
635 if [istarget $targ] {
636 return
637 }
638 }
639
640 if {$opts(PROG) != ""} {
641 switch -- $opts(PROG) {
642 objdump
643 { set program objdump }
644 nm
645 { set program nm }
646 objcopy
647 { set program objcopy }
648 readelf
649 { set program readelf }
650 default
651 { perror "unrecognized program option $opts(PROG) in $file.d"
652 unresolved $subdir/$name
653 return }
654 }
655 } elseif { $opts(error) != "" } {
656 # It's meaningless to require an output-testing method when we
657 # expect an error. For simplicity, we fake an arbitrary method.
658 set program "nm"
659 } else {
660 # Guess which program to run, by seeing which option was specified.
661 set program ""
662 foreach p {objdump objcopy nm readelf} {
663 if {$opts($p) != ""} {
664 if {$program != ""} {
665 perror "ambiguous dump program in $file.d"
666 unresolved $subdir/$name
667 return
668 } else {
669 set program $p
670 }
671 }
672 }
673 if {$program == ""} {
674 perror "dump program unspecified in $file.d"
675 unresolved $subdir/$name
676 return
677 }
678 }
679
680 set progopts1 $opts($program)
681 eval set progopts \$[string toupper $program]FLAGS
682 eval set binary \$[string toupper $program]
683 if { $opts(name) == "" } {
684 set testname "$subdir/$name"
685 } else {
686 set testname $opts(name)
687 }
688
689 if { $opts(source) == "" } {
690 set sourcefiles [list ${file}.s]
691 } else {
692 set sourcefiles {}
693 foreach sf $opts(source) {
694 if { [string match "/*" $sf] } {
695 lappend sourcefiles "$sf"
696 } {
697 lappend sourcefiles "$srcdir/$subdir/$sf"
698 }
699 # Must have asflags indexed on source name.
700 set asflags($srcdir/$subdir/$sf) $asflags($sf)
701 }
702 }
703
704 # Time to setup xfailures.
705 foreach targ $opts(xfail) {
706 setup_xfail $targ
707 }
708
709 # Assemble each file.
710 set objfiles {}
711 for { set i 0 } { $i < [llength $sourcefiles] } { incr i } {
712 set sourcefile [lindex $sourcefiles $i]
713
714 set objfile "tmpdir/dump$i.o"
715 lappend objfiles $objfile
716 set cmd "$AS $ASFLAGS $opts(as) $asflags($sourcefile) -o $objfile $sourcefile"
717
718 send_log "$cmd\n"
719 set cmdret [catch "exec $cmd" comp_output]
720 set comp_output [prune_warnings $comp_output]
721
722 # We accept errors at assembly stage too, unless we're supposed to
723 # link something.
724 if { $cmdret != 0 || ![string match "" $comp_output] } then {
725 send_log "$comp_output\n"
726 verbose "$comp_output" 3
727 if { $opts(error) != "" && $run_ld == 0 } {
728 if [regexp $opts(error) $comp_output] {
729 pass $testname
730 return
731 }
732 }
733 fail $testname
734 return
735 }
736 }
737
738 # Perhaps link the file(s).
739 if { $run_ld } {
740 set objfile "tmpdir/dump"
741
742 # Add -L$srcdir/$subdir so that the linker command can use
743 # linker scripts in the source directory.
744 set cmd "$LD $LDFLAGS -L$srcdir/$subdir \
745 $opts(ld) -o $objfile $objfiles"
746
747 send_log "$cmd\n"
748 set cmdret [catch "exec $cmd" comp_output]
749 set comp_output [prune_warnings $comp_output]
750
751 if { $cmdret != 0 || ![string match "" $comp_output] } then {
752 verbose -log "failed with: <$comp_output>, expected: <$opts(error)>"
753 send_log "$comp_output\n"
754 verbose "$comp_output" 3
755 if { $opts(error) != "" && $run_objcopy == 0 } {
756 if [regexp $opts(error) $comp_output] {
757 pass $testname
758 return
759 }
760 }
761 fail $testname
762 return
763 }
764
765 if { $run_objcopy } {
766 set infile $objfile
767 set objfile "tmpdir/dump1"
768
769 # Note that we don't use OBJCOPYFLAGS here; any flags must be
770 # explicitly specified.
771 set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile"
772
773 send_log "$cmd\n"
774 set cmdret [catch "exec $cmd" comp_output]
775 set comp_output [prune_warnings $comp_output]
776
777 if { $cmdret != 0 || ![string match "" $comp_output] } then {
778 verbose -log "failed with: <$comp_output>, expected: <$opts(error)>"
779 send_log "$comp_output\n"
780 verbose "$comp_output" 3
781 if { $opts(error) != "" } {
782 if [regexp $opts(error) $comp_output] {
783 pass $testname
784 return
785 }
786 }
787 fail $testname
788 return
789 }
790 }
791 } else {
792 set objfile "tmpdir/dump0.o"
793 }
794
795 # We must not have expected failure if we get here.
796 if { $opts(error) != "" } {
797 fail $testname
798 return
799 }
800
801 if { [which $binary] == 0 } {
802 untested $testname
803 return
804 }
805
806 if { $progopts1 == "" } { set $progopts1 "-r" }
807 verbose "running $binary $progopts $progopts1" 3
808
809 # Objcopy, unlike the other two, won't send its output to stdout,
810 # so we have to run it specially.
811 set cmd "$binary $progopts $progopts1 $objfile > $dumpfile"
812 if { $program == "objcopy" } {
813 set cmd "$binary $progopts $progopts1 $objfile $dumpfile"
814 }
815
816 # Ensure consistent sorting of symbols
817 if {[info exists env(LC_ALL)]} {
818 set old_lc_all $env(LC_ALL)
819 }
820 set env(LC_ALL) "C"
821 send_log "$cmd\n"
822 catch "exec $cmd" comp_output
823 if {[info exists old_lc_all]} {
824 set env(LC_ALL) $old_lc_all
825 } else {
826 unset env(LC_ALL)
827 }
828 set comp_output [prune_warnings $comp_output]
829 if ![string match "" $comp_output] then {
830 send_log "$comp_output\n"
831 fail $testname
832 return
833 }
834
835 verbose_eval {[file_contents $dumpfile]} 3
836 if { [regexp_diff $dumpfile "${file}.d"] } then {
837 fail $testname
838 verbose "output is [file_contents $dumpfile]" 2
839 return
840 }
841
842 pass $testname
843 }
844
845 proc slurp_options { file } {
846 if [catch { set f [open $file r] } x] {
847 #perror "couldn't open `$file': $x"
848 perror "$x"
849 return -1
850 }
851 set opt_array {}
852 # whitespace expression
853 set ws {[ ]*}
854 set nws {[^ ]*}
855 # whitespace is ignored anywhere except within the options list;
856 # option names are alphabetic plus underscore only.
857 set pat "^#${ws}(\[a-zA-Z_\]*)$ws:${ws}(.*)$ws\$"
858 while { [gets $f line] != -1 } {
859 set line [string trim $line]
860 # Whitespace here is space-tab.
861 if [regexp $pat $line xxx opt_name opt_val] {
862 # match!
863 lappend opt_array [list $opt_name $opt_val]
864 } else {
865 break
866 }
867 }
868 close $f
869 return $opt_array
870 }
871
872 # regexp_diff, copied from gas, based on simple_diff above.
873 # compares two files line-by-line
874 # file1 contains strings, file2 contains regexps and #-comments
875 # blank lines are ignored in either file
876 # returns non-zero if differences exist
877 #
878 proc regexp_diff { file_1 file_2 } {
879
880 set eof -1
881 set end_1 0
882 set end_2 0
883 set differences 0
884 set diff_pass 0
885
886 if [file exists $file_1] then {
887 set file_a [open $file_1 r]
888 } else {
889 warning "$file_1 doesn't exist"
890 return 1
891 }
892
893 if [file exists $file_2] then {
894 set file_b [open $file_2 r]
895 } else {
896 fail "$file_2 doesn't exist"
897 close $file_a
898 return 1
899 }
900
901 verbose " Regexp-diff'ing: $file_1 $file_2" 2
902
903 while { 1 } {
904 set line_a ""
905 set line_b ""
906 while { [string length $line_a] == 0 } {
907 if { [gets $file_a line_a] == $eof } {
908 set end_1 1
909 break
910 }
911 }
912 while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
913 if [ string match "#pass" $line_b ] {
914 set end_2 1
915 set diff_pass 1
916 break
917 } elseif [ string match "#..." $line_b ] {
918 if { [gets $file_b line_b] == $eof } {
919 set end_2 1
920 break
921 }
922 verbose "looking for \"^$line_b$\"" 3
923 while { ![regexp "^$line_b$" "$line_a"] } {
924 verbose "skipping \"$line_a\"" 3
925 if { [gets $file_a line_a] == $eof } {
926 set end_1 1
927 break
928 }
929 }
930 break
931 }
932 if { [gets $file_b line_b] == $eof } {
933 set end_2 1
934 break
935 }
936 }
937
938 if { $diff_pass } {
939 break
940 } elseif { $end_1 && $end_2 } {
941 break
942 } elseif { $end_1 } {
943 send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
944 verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
945 set differences 1
946 break
947 } elseif { $end_2 } {
948 send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
949 verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
950 set differences 1
951 break
952 } else {
953 verbose "regexp \"^$line_b$\"\nline \"$line_a\"" 3
954 if ![regexp "^$line_b$" "$line_a"] {
955 send_log "regexp_diff match failure\n"
956 send_log "regexp \"^$line_b$\"\nline \"$line_a\"\n"
957 set differences 1
958 }
959 }
960 }
961
962 if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
963 send_log "$file_1 and $file_2 are different lengths\n"
964 verbose "$file_1 and $file_2 are different lengths" 3
965 set differences 1
966 }
967
968 close $file_a
969 close $file_b
970
971 return $differences
972 }
973
974 proc file_contents { filename } {
975 set file [open $filename r]
976 set contents [read $file]
977 close $file
978 return $contents
979 }
980
981 # List contains test-items with 3 items followed by 2 lists, one item and
982 # one optional item:
983 # 0:name 1:ld options 2:assembler options
984 # 3:filenames of assembler files 4: action and options. 5: name of output file
985 # 6:compiler flags (optional)
986
987 # Actions:
988 # objdump: Apply objdump options on result. Compare with regex (last arg).
989 # nm: Apply nm options on result. Compare with regex (last arg).
990 # readelf: Apply readelf options on result. Compare with regex (last arg).
991
992 proc run_ld_link_tests { ldtests } {
993 global ld
994 global as
995 global nm
996 global objdump
997 global READELF
998 global srcdir
999 global subdir
1000 global env
1001 global CC
1002 global CFLAGS
1003
1004 foreach testitem $ldtests {
1005 set testname [lindex $testitem 0]
1006 set ld_options [lindex $testitem 1]
1007 set as_options [lindex $testitem 2]
1008 set src_files [lindex $testitem 3]
1009 set actions [lindex $testitem 4]
1010 set binfile tmpdir/[lindex $testitem 5]
1011 set cflags [lindex $testitem 6]
1012 set objfiles {}
1013 set is_unresolved 0
1014 set failed 0
1015
1016 # verbose -log "Testname is $testname"
1017 # verbose -log "ld_options is $ld_options"
1018 # verbose -log "as_options is $as_options"
1019 # verbose -log "src_files is $src_files"
1020 # verbose -log "actions is $actions"
1021 # verbose -log "binfile is $binfile"
1022
1023 # Assemble each file in the test.
1024 foreach src_file $src_files {
1025 set objfile "tmpdir/[file rootname $src_file].o"
1026 lappend objfiles $objfile
1027
1028 if { [file extension $src_file] == ".c" } {
1029 set as_file "tmpdir/[file rootname $src_file].s"
1030 if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
1031 set is_unresolved 1
1032 break
1033 }
1034 } else {
1035 set as_file "$srcdir/$subdir/$src_file"
1036 }
1037 if ![ld_assemble $as "$as_options $as_file" $objfile] {
1038 set is_unresolved 1
1039 break
1040 }
1041 }
1042
1043 # Catch assembler errors.
1044 if { $is_unresolved != 0 } {
1045 unresolved $testname
1046 continue
1047 }
1048
1049 if ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
1050 fail $testname
1051 } else {
1052 set failed 0
1053 foreach actionlist $actions {
1054 set action [lindex $actionlist 0]
1055 set progopts [lindex $actionlist 1]
1056
1057 # There are actions where we run regexp_diff on the
1058 # output, and there are other actions (presumably).
1059 # Handling of the former look the same.
1060 set dump_prog ""
1061 switch -- $action {
1062 objdump
1063 { set dump_prog $objdump }
1064 nm
1065 { set dump_prog $nm }
1066 readelf
1067 { set dump_prog $READELF }
1068 default
1069 {
1070 perror "Unrecognized action $action"
1071 set is_unresolved 1
1072 break
1073 }
1074 }
1075
1076 if { $dump_prog != "" } {
1077 set dumpfile [lindex $actionlist 2]
1078 set binary $dump_prog
1079
1080 # Ensure consistent sorting of symbols
1081 if {[info exists env(LC_ALL)]} {
1082 set old_lc_all $env(LC_ALL)
1083 }
1084 set env(LC_ALL) "C"
1085 set cmd "$binary $progopts $binfile > dump.out"
1086 send_log "$cmd\n"
1087 catch "exec $cmd" comp_output
1088 if {[info exists old_lc_all]} {
1089 set env(LC_ALL) $old_lc_all
1090 } else {
1091 unset env(LC_ALL)
1092 }
1093 set comp_output [prune_warnings $comp_output]
1094
1095 if ![string match "" $comp_output] then {
1096 send_log "$comp_output\n"
1097 set failed 1
1098 break
1099 }
1100
1101 if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1102 verbose "output is [file_contents "dump.out"]" 2
1103 set failed 1
1104 break
1105 }
1106 }
1107 }
1108
1109 if { $failed != 0 } {
1110 fail $testname
1111 } else { if { $is_unresolved == 0 } {
1112 pass $testname
1113 } }
1114 }
1115
1116 # Catch action errors.
1117 if { $is_unresolved != 0 } {
1118 unresolved $testname
1119 continue
1120 }
1121 }
1122 }
1123
1124
1125 proc verbose_eval { expr { level 1 } } {
1126 global verbose
1127 if $verbose>$level then { eval verbose "$expr" $level }
1128 }
1129
1130 # This definition is taken from an unreleased version of DejaGnu. Once
1131 # that version gets released, and has been out in the world for a few
1132 # months at least, it may be safe to delete this copy.
1133 if ![string length [info proc prune_warnings]] {
1134 #
1135 # prune_warnings -- delete various system verbosities from TEXT
1136 #
1137 # An example is:
1138 # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
1139 #
1140 # Sites with particular verbose os's may wish to override this in site.exp.
1141 #
1142 proc prune_warnings { text } {
1143 # This is from sun4's. Do it for all machines for now.
1144 # The "\\1" is to try to preserve a "\n" but only if necessary.
1145 regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
1146
1147 # It might be tempting to get carried away and delete blank lines, etc.
1148 # Just delete *exactly* what we're ask to, and that's it.
1149 return $text
1150 }
1151 }