* ld-elf/warn1.d: Specify -Ttext.
[platform/upstream/binutils.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 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 -mb} {
98                     set flags " -EB"
99                     return $flags
100                 }
101                 {*little*endian el EL -el -EL -ml} {
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     global gcc_ld_flag
158
159     if { [which $ld] == 0 } then {
160         perror "$ld does not exist"
161         return 0
162     }
163
164     if [is_endian_output_format $objects] then {
165         set flags [big_or_little_endian]
166     } else {
167         set flags ""
168     }
169
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]
177     }
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"
181     }
182
183     verbose -log "$ld $flags -o $target $objects"
184
185     catch "exec $ld $flags -o $target $objects" link_output
186     set exec_output [prune_warnings $link_output]
187
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
191
192     if [string match "" $exec_output] then {
193         return 1
194     } else {
195         verbose -log "$exec_output"
196         return 0
197     }
198 }
199
200 #
201 # default_ld_compile
202 #       compile an object using cc
203 #
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
210
211     set cc_prog $cc
212     if {[llength $cc_prog] > 1} then {
213         set cc_prog [lindex $cc_prog 0]
214     }
215     if {[which $cc_prog] == 0} then {
216         perror "$cc_prog does not exist"
217         return 0
218     }
219
220     catch "exec rm -f $object" exec_output
221
222     set flags "-I$srcdir/$subdir $CFLAGS"
223
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]
231     }
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"
235     }
236
237     if [board_info [target_info name] exists multilib_flags] {
238         append flags " [board_info [target_info name] multilib_flags]"
239     }
240
241     verbose -log "$cc $flags -c $source -o $object"
242
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
258                 }
259             } else {
260                 perror "$object not found after compilation"
261                 return 0
262             }
263         }
264         return 1
265     } else {
266         verbose -log "$exec_output"
267         perror "$source: compilation failed"
268         return 0
269     }
270 }
271
272 #
273 # default_ld_assemble
274 #       assemble a file
275 #
276 proc default_ld_assemble { as source object } {
277     global ASFLAGS
278     global host_triplet
279
280     if {[which $as] == 0} then {
281         perror "$as does not exist"
282         return 0
283     }
284
285     if ![info exists ASFLAGS] { set ASFLAGS "" }
286
287     set flags [big_or_little_endian]
288
289     verbose -log "$as $flags $ASFLAGS -o $object $source"
290
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
299     }
300 }
301
302 #
303 # default_ld_nm
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 {[which $nm] == 0} then {
312         perror "$nm does not exist"
313         return 0
314     }
315
316     if {[info exists nm_output]} {
317       unset nm_output
318     }
319
320     if ![info exists NMFLAGS] { set NMFLAGS "" }
321
322     # Ensure consistent sorting of symbols
323     if {[info exists env(LC_ALL)]} {
324         set old_lc_all $env(LC_ALL)
325     }
326     set env(LC_ALL) "C"
327     verbose -log "$nm $NMFLAGS $nmflags $object >tmpdir/nm.out"
328
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)
334     }
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
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 #
356 # is_elf_format
357 #       true if the object format is known to be ELF
358 #
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
372     }
373
374     if { [istarget *-*-linux*aout*] \
375          || [istarget *-*-linux*oldld*] } {
376         return 0
377     }
378
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
389     }
390     return 1
391 }
392
393 #
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
399
400     set readelf_size ""
401     catch "exec $READELF $READELFFLAGS -h $binary_file > readelf.out" got
402
403     if ![string match "" $got] then {
404         return 0
405     }
406
407     if { ![regexp "\n\[ \]*Class:\[ \]*ELF(\[0-9\]+)\n" \
408            [file_contents readelf.out] nil readelf_size] } {
409         return 0
410     }
411
412     if { $readelf_size == "64" } {
413         return 1
414     }
415
416     return 0
417 }
418
419 #
420 # is_aout_format
421 #       true if the object format is known to be aout
422 proc is_aout_format {} {
423     if { [istarget *-*-*\[ab\]out*] \
424              || [istarget *-*-linux*oldld*] \
425              || [istarget *-*-msdos*] \
426              || [istarget arm-*-netbsd] \
427              || [istarget i?86-*-netbsd] \
428              || [istarget i?86-*-mach*] \
429              || [istarget i?86-*-vsta] \
430              || [istarget pdp11-*-*] \
431              || [istarget m68*-ericsson-ose] \
432              || [istarget m68k-hp-bsd*] \
433              || [istarget m68*-*-hpux*] \
434              || [istarget m68*-*-netbsd] \
435              || [istarget m68*-*-netbsd*4k*] \
436              || [istarget m68k-sony-*] \
437              || [istarget m68*-sun-sunos\[34\]*] \
438              || [istarget m68*-wrs-vxworks*] \
439              || [istarget ns32k-*-*] \
440              || [istarget sparc*-*-netbsd] \
441              || [istarget sparc-sun-sunos4*] \
442              || [istarget vax-dec-ultrix*] \
443              || [istarget vax-*-netbsd] } {
444         return 1
445     }
446     return 0
447 }
448
449 #
450 # is_pecoff_format
451 #       true if the object format is known to be PECOFF
452 #
453 proc is_pecoff_format {} {
454     if { ![istarget *-*-mingw32*] \
455          && ![istarget *-*-cygwin*] \
456          && ![istarget *-*-pe*] } {
457         return 0
458     }
459
460     return 1
461 }
462
463 #
464 # simple_diff
465 #       compares two files line-by-line
466 #       returns differences if exist
467 #       returns null if file(s) cannot be opened
468 #
469 proc simple_diff { file_1 file_2 } {
470     global target
471
472     set eof -1
473     set differences 0
474
475     if [file exists $file_1] then {
476         set file_a [open $file_1 r]
477     } else {
478         warning "$file_1 doesn't exist"
479         return
480     }
481
482     if [file exists $file_2] then {
483         set file_b [open $file_2 r]
484     } else {
485         fail "$file_2 doesn't exist"
486         return
487     }
488
489     verbose "# Diff'ing: $file_1 $file_2\n" 2
490
491     while { [gets $file_a line] != $eof } {
492         if [regexp "^#.*$" $line] then {
493             continue
494         } else {
495             lappend list_a $line
496         }
497     }
498     close $file_a
499
500     while { [gets $file_b line] != $eof } {
501         if [regexp "^#.*$" $line] then {
502             continue
503         } else {
504             lappend list_b $line
505         }
506     }
507     close $file_b
508
509     for { set i 0 } { $i < [llength $list_a] } { incr i } {
510         set line_a [lindex $list_a $i]
511         set line_b [lindex $list_b $i]
512
513         verbose "\t$file_1: $i: $line_a\n" 3
514         verbose "\t$file_2: $i: $line_b\n" 3
515         if [string compare $line_a $line_b] then {
516             verbose -log "\t$file_1: $i: $line_a\n"
517             verbose -log "\t$file_2: $i: $line_b\n"
518
519             fail "Test: $target"
520             return
521         }
522     }
523
524     if { [llength $list_a] != [llength $list_b] } {
525         fail "Test: $target"
526         return
527     }
528
529     if $differences<1 then {
530         pass "Test: $target"
531     }
532 }
533
534 # run_dump_test FILE
535 # Copied from gas testsuite, tweaked and further extended.
536 #
537 # Assemble a .s file, then run some utility on it and check the output.
538 #
539 # There should be an assembly language file named FILE.s in the test
540 # suite directory, and a pattern file called FILE.d.  `run_dump_test'
541 # will assemble FILE.s, run some tool like `objdump', `objcopy', or
542 # `nm' on the .o file to produce textual output, and then analyze that
543 # with regexps.  The FILE.d file specifies what program to run, and
544 # what to expect in its output.
545 #
546 # The FILE.d file begins with zero or more option lines, which specify
547 # flags to pass to the assembler, the program to run to dump the
548 # assembler's output, and the options it wants.  The option lines have
549 # the syntax:
550 #
551 #         # OPTION: VALUE
552 #
553 # OPTION is the name of some option, like "name" or "objdump", and
554 # VALUE is OPTION's value.  The valid options are described below.
555 # Whitespace is ignored everywhere, except within VALUE.  The option
556 # list ends with the first line that doesn't match the above syntax
557 # (hmm, not great for error detection).
558 #
559 # The interesting options are:
560 #
561 #   name: TEST-NAME
562 #       The name of this test, passed to DejaGNU's `pass' and `fail'
563 #       commands.  If omitted, this defaults to FILE, the root of the
564 #       .s and .d files' names.
565 #
566 #   as: FLAGS
567 #       When assembling, pass FLAGS to the assembler.
568 #       If assembling several files, you can pass different assembler
569 #       options in the "source" directives.  See below.
570 #
571 #   ld: FLAGS
572 #       Link assembled files using FLAGS, in the order of the "source"
573 #       directives, when using multiple files.
574 #
575 #   objcopy_linked_file: FLAGS
576 #       Run objcopy on the linked file with the specified flags.
577 #       This lets you transform the linked file using objcopy, before the
578 #       result is analyzed by an analyzer program specified below (which
579 #       may in turn *also* be objcopy).
580 #
581 #   PROG: PROGRAM-NAME
582 #       The name of the program to run to analyze the .o file produced
583 #       by the assembler or the linker output.  This can be omitted;
584 #       run_dump_test will guess which program to run by seeing which of
585 #       the flags options below is present.
586 #
587 #   objdump: FLAGS
588 #   nm: FLAGS
589 #   objcopy: FLAGS
590 #       Use the specified program to analyze the assembler or linker
591 #       output file, and pass it FLAGS, in addition to the output name.
592 #       Note that they are run with LC_ALL=C in the environment to give
593 #       consistent sorting of symbols.
594 #
595 #   source: SOURCE [FLAGS]
596 #       Assemble the file SOURCE.s using the flags in the "as" directive
597 #       and the (optional) FLAGS.  If omitted, the source defaults to
598 #       FILE.s.
599 #       This is useful if several .d files want to share a .s file.
600 #       More than one "source" directive can be given, which is useful
601 #       when testing linking.
602 #
603 #   xfail: TARGET
604 #       The test is expected to fail on TARGET.  This may occur more than
605 #       once.
606 #
607 #   target: TARGET
608 #       Only run the test for TARGET.  This may occur more than once; the
609 #       target being tested must match at least one.
610 #
611 #   notarget: TARGET
612 #       Do not run the test for TARGET.  This may occur more than once;
613 #       the target being tested must not match any of them.
614 #
615 #   error: REGEX
616 #       An error with message matching REGEX must be emitted for the test
617 #       to pass.  The PROG, objdump, nm and objcopy options have no
618 #       meaning and need not supplied if this is present.
619 #
620 #   warning: REGEX
621 #       Expect a linker warning matching REGEX.  It is an error to issue
622 #       both "error" and "warning".
623 #
624 # Each option may occur at most once unless otherwise mentioned.
625 #
626 # After the option lines come regexp lines.  `run_dump_test' calls
627 # `regexp_diff' to compare the output of the dumping tool against the
628 # regexps in FILE.d.  `regexp_diff' is defined later in this file; see
629 # further comments there.
630
631 proc run_dump_test { name } {
632     global subdir srcdir
633     global OBJDUMP NM AS OBJCOPY READELF LD
634     global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS LDFLAGS
635     global host_triplet runtests
636     global env
637
638     if [string match "*/*" $name] {
639         set file $name
640         set name [file tail $name]
641     } else {
642         set file "$srcdir/$subdir/$name"
643     }
644
645     if ![runtest_file_p $runtests $name] then {
646         return
647     }
648
649     set opt_array [slurp_options "${file}.d"]
650     if { $opt_array == -1 } {
651         perror "error reading options from $file.d"
652         unresolved $subdir/$name
653         return
654     }
655     set dumpfile tmpdir/dump.out
656     set run_ld 0
657     set run_objcopy 0
658     set opts(as) {}
659     set opts(ld) {}
660     set opts(xfail) {}
661     set opts(target) {}
662     set opts(notarget) {}
663     set opts(objdump) {}
664     set opts(nm) {}
665     set opts(objcopy) {}
666     set opts(readelf) {}
667     set opts(name) {}
668     set opts(PROG) {}
669     set opts(source) {}
670     set opts(error) {}
671     set opts(warning) {}
672     set opts(objcopy_linked_file) {}
673     set asflags(${file}.s) {}
674
675     foreach i $opt_array {
676         set opt_name [lindex $i 0]
677         set opt_val [lindex $i 1]
678         if ![info exists opts($opt_name)] {
679             perror "unknown option $opt_name in file $file.d"
680             unresolved $subdir/$name
681             return
682         }
683
684         switch -- $opt_name {
685             xfail {}
686             target {}
687             notarget {}
688             source {
689                 # Move any source-specific as-flags to a separate array to
690                 # simplify processing.
691                 if { [llength $opt_val] > 1 } {
692                     set asflags([lindex $opt_val 0]) [lrange $opt_val 1 end]
693                     set opt_val [lindex $opt_val 0]
694                 } else {
695                     set asflags($opt_val) {}
696                 }
697             }
698             default {
699                 if [string length $opts($opt_name)] {
700                     perror "option $opt_name multiply set in $file.d"
701                     unresolved $subdir/$name
702                     return
703                 }
704
705                 # A single "# ld:" with no options should do the right thing.
706                 if { $opt_name == "ld" } {
707                     set run_ld 1
708                 }
709                 # Likewise objcopy_linked_file.
710                 if { $opt_name == "objcopy_linked_file" } {
711                     set run_objcopy 1
712                 }
713             }
714         }
715         set opts($opt_name) [concat $opts($opt_name) $opt_val]
716     }
717
718     # Decide early whether we should run the test for this target.
719     if { [llength $opts(target)] > 0 } {
720         set targmatch 0
721         foreach targ $opts(target) {
722             if [istarget $targ] {
723                 set targmatch 1
724                 break
725             }
726         }
727         if { $targmatch == 0 } {
728             return
729         }
730     }
731     foreach targ $opts(notarget) {
732         if [istarget $targ] {
733             return
734         }
735     }
736
737     if {$opts(PROG) != ""} {
738         switch -- $opts(PROG) {
739             objdump
740                 { set program objdump }
741             nm
742                 { set program nm }
743             objcopy
744                 { set program objcopy }
745             readelf
746                 { set program readelf }
747             default
748                 { perror "unrecognized program option $opts(PROG) in $file.d"
749                   unresolved $subdir/$name
750                   return }
751         }
752     } elseif { $opts(error) != "" } {
753         # It's meaningless to require an output-testing method when we
754         # expect an error.  For simplicity, we fake an arbitrary method.
755         set program "nm"
756     } else {
757         # Guess which program to run, by seeing which option was specified.
758         set program ""
759         foreach p {objdump objcopy nm readelf} {
760             if {$opts($p) != ""} {
761                 if {$program != ""} {
762                     perror "ambiguous dump program in $file.d"
763                     unresolved $subdir/$name
764                     return
765                 } else {
766                     set program $p
767                 }
768             }
769         }
770         if {$program == ""} {
771             perror "dump program unspecified in $file.d"
772             unresolved $subdir/$name
773             return
774         }
775     }
776
777     set progopts1 $opts($program)
778     eval set progopts \$[string toupper $program]FLAGS
779     eval set binary \$[string toupper $program]
780     if { $opts(name) == "" } {
781         set testname "$subdir/$name"
782     } else {
783         set testname $opts(name)
784     }
785
786     if { $opts(source) == "" } {
787         set sourcefiles [list ${file}.s]
788     } else {
789         set sourcefiles {}
790         foreach sf $opts(source) {
791             if { [string match "/*" $sf] } {
792                 lappend sourcefiles "$sf"
793             } {
794                 lappend sourcefiles "$srcdir/$subdir/$sf"
795             }
796             # Must have asflags indexed on source name.
797             set asflags($srcdir/$subdir/$sf) $asflags($sf)
798         }
799     }
800
801     # Time to setup xfailures.
802     foreach targ $opts(xfail) {
803         setup_xfail $targ
804     }
805
806     # Assemble each file.
807     set objfiles {}
808     for { set i 0 } { $i < [llength $sourcefiles] } { incr i } {
809         set sourcefile [lindex $sourcefiles $i]
810
811         set objfile "tmpdir/dump$i.o"
812         lappend objfiles $objfile
813         set cmd "$AS $ASFLAGS $opts(as) $asflags($sourcefile) -o $objfile $sourcefile"
814
815         send_log "$cmd\n"
816         set cmdret [catch "exec $cmd" comp_output]
817         set comp_output [prune_warnings $comp_output]
818
819         # We accept errors at assembly stage too, unless we're supposed to
820         # link something.
821         if { $cmdret != 0 || ![string match "" $comp_output] } then {
822             send_log "$comp_output\n"
823             verbose "$comp_output" 3
824             if { $opts(error) != "" && $run_ld == 0 } {
825                 if [regexp $opts(error) $comp_output] {
826                     pass $testname
827                     return
828                 }
829             }
830             fail $testname
831             return
832         }
833     }
834
835     # Perhaps link the file(s).
836     if { $run_ld } {
837         set objfile "tmpdir/dump"
838         set expmsg $opts(error)
839
840         if { $opts(warning) != "" } {
841             if { $expmsg != "" } {
842                 perror "$testname: mixing error and warning test-directives"
843                 return
844             }
845             set expmsg $opts(warning)
846         }
847
848         # Add -L$srcdir/$subdir so that the linker command can use
849         # linker scripts in the source directory.
850         set cmd "$LD $LDFLAGS -L$srcdir/$subdir \
851                    $opts(ld) -o $objfile $objfiles"
852
853         send_log "$cmd\n"
854         set cmdret [catch "exec $cmd" comp_output]
855         set comp_output [prune_warnings $comp_output]
856
857         if { $cmdret != 0 || $comp_output != "" || $expmsg != "" } then {
858             # If the executed program writes to stderr and stderr is not
859             # redirected, exec *always* returns failure, regardless of the
860             # program exit code.  Thankfully, we can retrieve the true
861             # return status from a special variable.  Redirection would
862             # cause a tcl-specific message to be appended, and we'd rather
863             # not deal with that if we can help it.
864             global errorCode
865             if { $cmdret != 0 && [lindex $errorCode 0] == "NONE" } {
866                 set cmdret 0
867             }
868
869             set exitstat "succeeded"
870             if { $cmdret != 0 } { set exitstat "failed" }
871             verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>"
872             send_log "$comp_output\n"
873             verbose "$comp_output" 3
874             if { $expmsg != "" && $run_objcopy == 0 \
875                     && [regexp $expmsg $comp_output] \
876                     && (($cmdret == 0) == ($opts(warning) != "")) } {
877                 # Only "pass" and return here if we expected (and got)
878                 # an error.
879                 if { $opts(error) != "" } {
880                     pass $testname
881                     return
882                 }
883             } {
884                 fail $testname
885                 return
886             }
887         }
888
889         if { $run_objcopy } {
890             set infile $objfile
891             set objfile "tmpdir/dump1"
892
893             # Note that we don't use OBJCOPYFLAGS here; any flags must be
894             # explicitly specified.
895             set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile"
896
897             send_log "$cmd\n"
898             set cmdret [catch "exec $cmd" comp_output]
899             set comp_output [prune_warnings $comp_output]
900
901             if { $cmdret != 0 || ![string match "" $comp_output] } then {
902                 verbose -log "failed with: <$comp_output>, expected: <$opts(error)>"
903                 send_log "$comp_output\n"
904                 verbose "$comp_output" 3
905                 if { $opts(error) != "" } {
906                     if [regexp $opts(error) $comp_output] {
907                         pass $testname
908                         return
909                     }
910                 }
911                 fail $testname
912                 return
913             }
914         }
915     } else {
916         set objfile "tmpdir/dump0.o"
917     }
918
919     # We must not have expected failure if we get here.
920     if { $opts(error) != "" } {
921         fail $testname
922         return
923     }
924
925     if { [which $binary] == 0 } {
926         untested $testname
927         return
928     }
929
930     if { $progopts1 == "" } { set $progopts1 "-r" }
931     verbose "running $binary $progopts $progopts1" 3
932
933     # Objcopy, unlike the other two, won't send its output to stdout,
934     # so we have to run it specially.
935     set cmd "$binary $progopts $progopts1 $objfile > $dumpfile"
936     if { $program == "objcopy" } {
937         set cmd "$binary $progopts $progopts1 $objfile $dumpfile"
938     }
939
940     # Ensure consistent sorting of symbols
941     if {[info exists env(LC_ALL)]} {
942         set old_lc_all $env(LC_ALL)
943     }
944     set env(LC_ALL) "C"
945     send_log "$cmd\n"
946     catch "exec $cmd" comp_output
947     if {[info exists old_lc_all]} {
948         set env(LC_ALL) $old_lc_all
949     } else {
950         unset env(LC_ALL)
951     }
952     set comp_output [prune_warnings $comp_output]
953     if ![string match "" $comp_output] then {
954         send_log "$comp_output\n"
955         fail $testname
956         return
957     }
958
959     verbose_eval {[file_contents $dumpfile]} 3
960     if { [regexp_diff $dumpfile "${file}.d"] } then {
961         fail $testname
962         verbose "output is [file_contents $dumpfile]" 2
963         return
964     }
965
966     pass $testname
967 }
968
969 proc slurp_options { file } {
970     if [catch { set f [open $file r] } x] {
971         #perror "couldn't open `$file': $x"
972         perror "$x"
973         return -1
974     }
975     set opt_array {}
976     # whitespace expression
977     set ws  {[  ]*}
978     set nws {[^         ]*}
979     # whitespace is ignored anywhere except within the options list;
980     # option names are alphabetic plus underscore only.
981     set pat "^#${ws}(\[a-zA-Z_\]*)$ws:${ws}(.*)$ws\$"
982     while { [gets $f line] != -1 } {
983         set line [string trim $line]
984         # Whitespace here is space-tab.
985         if [regexp $pat $line xxx opt_name opt_val] {
986             # match!
987             lappend opt_array [list $opt_name $opt_val]
988         } else {
989             break
990         }
991     }
992     close $f
993     return $opt_array
994 }
995
996 # regexp_diff, copied from gas, based on simple_diff above.
997 #       compares two files line-by-line
998 #       file1 contains strings, file2 contains regexps and #-comments
999 #       blank lines are ignored in either file
1000 #       returns non-zero if differences exist
1001 #
1002 proc regexp_diff { file_1 file_2 } {
1003
1004     set eof -1
1005     set end_1 0
1006     set end_2 0
1007     set differences 0
1008     set diff_pass 0
1009
1010     if [file exists $file_1] then {
1011         set file_a [open $file_1 r]
1012     } else {
1013         warning "$file_1 doesn't exist"
1014         return 1
1015     }
1016
1017     if [file exists $file_2] then {
1018         set file_b [open $file_2 r]
1019     } else {
1020         fail "$file_2 doesn't exist"
1021         close $file_a
1022         return 1
1023     }
1024
1025     verbose " Regexp-diff'ing: $file_1 $file_2" 2
1026
1027     while { 1 } {
1028         set line_a ""
1029         set line_b ""
1030         while { [string length $line_a] == 0 } {
1031             if { [gets $file_a line_a] == $eof } {
1032                 set end_1 1
1033                 break
1034             }
1035         }
1036         while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
1037             if [ string match "#pass" $line_b ] {
1038                 set end_2 1
1039                 set diff_pass 1
1040                 break
1041             } elseif [ string match "#..." $line_b ] {
1042                 if { [gets $file_b line_b] == $eof } {
1043                     set end_2 1
1044                     break
1045                 }
1046                 verbose "looking for \"^$line_b$\"" 3
1047                 while { ![regexp "^$line_b$" "$line_a"] } {
1048                     verbose "skipping    \"$line_a\"" 3
1049                     if { [gets $file_a line_a] == $eof } {
1050                         set end_1 1
1051                         break
1052                     }
1053                 }
1054                 break
1055             }
1056             if { [gets $file_b line_b] == $eof } {
1057                 set end_2 1
1058                 break
1059             }
1060         }
1061
1062         if { $diff_pass } {
1063             break
1064         } elseif { $end_1 && $end_2 } {
1065             break
1066         } elseif { $end_1 } {
1067             send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
1068             verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
1069             set differences 1
1070             break
1071         } elseif { $end_2 } {
1072             send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
1073             verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
1074             set differences 1
1075             break
1076         } else {
1077             verbose "regexp \"^$line_b$\"\nline   \"$line_a\"" 3
1078             if ![regexp "^$line_b$" "$line_a"] {
1079                 send_log "regexp_diff match failure\n"
1080                 send_log "regexp \"^$line_b$\"\nline   \"$line_a\"\n"
1081                 set differences 1
1082             }
1083         }
1084     }
1085
1086     if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
1087         send_log "$file_1 and $file_2 are different lengths\n"
1088         verbose "$file_1 and $file_2 are different lengths" 3
1089         set differences 1
1090     }
1091
1092     close $file_a
1093     close $file_b
1094
1095     return $differences
1096 }
1097
1098 proc file_contents { filename } {
1099     set file [open $filename r]
1100     set contents [read $file]
1101     close $file
1102     return $contents
1103 }
1104
1105 # List contains test-items with 3 items followed by 2 lists, one item and
1106 # one optional item:
1107 # 0:name 1:ld options 2:assembler options
1108 # 3:filenames of assembler files 4: action and options. 5: name of output file
1109 # 6:compiler flags (optional)
1110
1111 # Actions:
1112 # objdump: Apply objdump options on result.  Compare with regex (last arg).
1113 # nm: Apply nm options on result.  Compare with regex (last arg).
1114 # readelf: Apply readelf options on result.  Compare with regex (last arg).
1115
1116 proc run_ld_link_tests { ldtests } {
1117     global ld
1118     global as
1119     global nm
1120     global objdump
1121     global READELF
1122     global srcdir
1123     global subdir
1124     global env
1125     global CC
1126     global CFLAGS
1127
1128     foreach testitem $ldtests {
1129         set testname [lindex $testitem 0]
1130         set ld_options [lindex $testitem 1]
1131         set as_options [lindex $testitem 2]
1132         set src_files  [lindex $testitem 3]
1133         set actions [lindex $testitem 4]
1134         set binfile tmpdir/[lindex $testitem 5]
1135         set cflags [lindex $testitem 6]
1136         set objfiles {}
1137         set is_unresolved 0
1138         set failed 0
1139
1140 #       verbose -log "Testname is $testname"
1141 #       verbose -log "ld_options is $ld_options"
1142 #       verbose -log "as_options is $as_options"
1143 #       verbose -log "src_files is $src_files"
1144 #       verbose -log "actions is $actions"
1145 #       verbose -log "binfile is $binfile"
1146
1147         # Assemble each file in the test.
1148         foreach src_file $src_files {
1149             set objfile "tmpdir/[file rootname $src_file].o"
1150             lappend objfiles $objfile
1151
1152             if { [file extension $src_file] == ".c" } {
1153                 set as_file "tmpdir/[file rootname $src_file].s"
1154                 if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] {
1155                     set is_unresolved 1
1156                     break
1157                 }
1158             } else {
1159                 set as_file "$srcdir/$subdir/$src_file"
1160             }
1161             if ![ld_assemble $as "$as_options $as_file" $objfile] {
1162                 set is_unresolved 1
1163                 break
1164             }
1165         }
1166
1167         # Catch assembler errors.
1168         if { $is_unresolved != 0 } {
1169             unresolved $testname
1170             continue
1171         }
1172
1173         if ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles"] {
1174             fail $testname
1175         } else {
1176             set failed 0
1177             foreach actionlist $actions {
1178                 set action [lindex $actionlist 0]
1179                 set progopts [lindex $actionlist 1]
1180
1181                 # There are actions where we run regexp_diff on the
1182                 # output, and there are other actions (presumably).
1183                 # Handling of the former look the same.
1184                 set dump_prog ""
1185                 switch -- $action {
1186                     objdump
1187                         { set dump_prog $objdump }
1188                     nm
1189                         { set dump_prog $nm }
1190                     readelf
1191                         { set dump_prog $READELF }
1192                     default
1193                         {
1194                             perror "Unrecognized action $action"
1195                             set is_unresolved 1
1196                             break
1197                         }
1198                     }
1199
1200                 if { $dump_prog != "" } {
1201                     set dumpfile [lindex $actionlist 2]
1202                     set binary $dump_prog
1203
1204                     # Ensure consistent sorting of symbols
1205                     if {[info exists env(LC_ALL)]} {
1206                         set old_lc_all $env(LC_ALL)
1207                     }
1208                     set env(LC_ALL) "C"
1209                     set cmd "$binary $progopts $binfile > dump.out"
1210                     send_log "$cmd\n"
1211                     catch "exec $cmd" comp_output
1212                     if {[info exists old_lc_all]} {
1213                         set env(LC_ALL) $old_lc_all
1214                     } else {
1215                         unset env(LC_ALL)
1216                     }
1217                     set comp_output [prune_warnings $comp_output]
1218
1219                     if ![string match "" $comp_output] then {
1220                         send_log "$comp_output\n"
1221                         set failed 1
1222                         break
1223                     }
1224
1225                     if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then {
1226                         verbose "output is [file_contents "dump.out"]" 2
1227                         set failed 1
1228                         break
1229                     }
1230                 }
1231             }
1232
1233             if { $failed != 0 } {
1234                 fail $testname
1235             } else { if { $is_unresolved == 0 } {
1236                 pass $testname
1237             } }
1238         }
1239
1240         # Catch action errors.
1241         if { $is_unresolved != 0 } {
1242             unresolved $testname
1243             continue
1244         }
1245     }
1246 }
1247
1248
1249 proc verbose_eval { expr { level 1 } } {
1250     global verbose
1251     if $verbose>$level then { eval verbose "$expr" $level }
1252 }
1253
1254 # This definition is taken from an unreleased version of DejaGnu.  Once
1255 # that version gets released, and has been out in the world for a few
1256 # months at least, it may be safe to delete this copy.
1257 if ![string length [info proc prune_warnings]] {
1258     #
1259     # prune_warnings -- delete various system verbosities from TEXT
1260     #
1261     # An example is:
1262     # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
1263     #
1264     # Sites with particular verbose os's may wish to override this in site.exp.
1265     #
1266     proc prune_warnings { text } {
1267         # This is from sun4's.  Do it for all machines for now.
1268         # The "\\1" is to try to preserve a "\n" but only if necessary.
1269         regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
1270
1271         # It might be tempting to get carried away and delete blank lines, etc.
1272         # Just delete *exactly* what we're ask to, and that's it.
1273         return $text
1274     }
1275 }