1# Copyright (C) 1993-2020 Free Software Foundation, Inc.
2#
3# This file is part of the GNU Binutils.
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 3 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., 51 Franklin Street - Fifth Floor, Boston,
18# MA 02110-1301, USA.
19
20# True if the object format is known to be ELF.
21#
22proc is_elf_format {} {
23    # config.sub for these targets curiously transforms a target doublet
24    # ending in -elf to -none.  eg. m68hc12-elf to m68hc12-unknown-none
25    # They are always elf.
26    if { [istarget m68hc1*-*] || [istarget s12z*-*] || [istarget xgate-*] } {
27	return 1;
28    }
29# vxworks (and windiss) excluded due to number of ELF tests that need
30# modifying to pass on those targets.
31#	 && ![istarget *-*-vxworks*]
32#	 && ![istarget *-*-windiss*]
33
34    if {    ![istarget *-*-chorus*]
35	 && ![istarget *-*-cloudabi*]
36	 && ![istarget *-*-eabi*]
37	 && ![istarget *-*-*elf*]
38	 && ![istarget *-*-*freebsd*]
39	 && ![istarget *-*-fuchsia*]
40	 && ![istarget *-*-gnu*]
41	 && ![istarget *-*-irix5*]
42	 && ![istarget *-*-irix6*]
43	 && ![istarget *-*-kaos*]
44	 && ![istarget *-*-*linux*]
45	 && ![istarget *-*-lynxos*]
46	 && ![istarget *-*-nacl*]
47	 && ![istarget *-*-netbsd*]
48	 && ![istarget *-*-nto*]
49	 && ![istarget *-*-openbsd*]
50	 && ![istarget *-*-rtems*]
51	 && ![istarget *-*-solaris2*]
52	 && ![istarget *-*-sysv4*]
53	 && ![istarget *-*-unixware*]
54	 && ![istarget *-*-wasm32*]
55	 && ![istarget avr-*-*]
56	 && ![istarget hppa*64*-*-hpux*]
57	 && ![istarget ia64-*-hpux*] } {
58	return 0
59    }
60
61    if { [istarget *-*-linux*ecoff*]
62	 || [istarget *-*-rtemscoff*] } {
63	return 0
64    }
65
66    if { ![istarget *-*-netbsdelf*]
67	 && (   [istarget vax-*-netbsd*]
68	     || [istarget ns32k-*-netbsd*]) } {
69    	return 0
70    }
71
72    if {    [istarget arm-*-openbsd*]
73	 || [istarget ns32k-*-openbsd*]
74	 || [istarget vax-*-openbsd*] } {
75	return 0
76    }
77
78    return 1
79}
80
81# True if the object format is known to be a.out.
82#
83proc is_aout_format {} {
84    if { [istarget *-*-*aout*]
85	 || [istarget *-*-bsd*]
86	 || [istarget *-*-msdos*]
87	 || [istarget ns32k-*-*]
88	 || [istarget pdp11-*-*]
89	 || [istarget vax-*-netbsd] } {
90	return 1
91    }
92    return 0
93}
94
95# True if the object format is known to be PE COFF.
96#
97proc is_pecoff_format args {
98    if { [llength $args] == 1 } {
99	set m_os [lindex $args 0]
100    } else {
101	set m_os *-*
102    }
103    if { [istarget $m_os-beospe*]
104	 || [istarget $m_os-cegcc*]
105	 || [istarget $m_os-cygwin*]
106	 || [istarget $m_os-interix*]
107	 || [istarget $m_os-mingw*]
108	 || [istarget $m_os-netbsdpe*]
109	 || [istarget $m_os-pe*]
110	 || [istarget $m_os-winnt*] } {
111	return 1
112    }
113    return 0
114}
115
116proc is_som_format {} {
117    if { ![istarget hppa*-*-*] || [istarget hppa*64*-*-*] } {
118	return 0;
119    }
120    if { [istarget *-*-osf*] \
121	     || [istarget {*-*-h[ip]ux*}] \
122	     || [istarget *-*-mpeix*] \
123	     || [istarget *-*-bsd*] } {
124	return 1;
125    }
126    return 0;
127}
128
129proc is_xcoff_format {} {
130    if { [istarget rs6000-*-*]
131	 || [istarget powerpc*-*-aix*]
132	 || [istarget powerpc*-*-beos*]
133	 || [istarget powerpc*-*-macos*] } {
134	return 1;
135    }
136    return 0;
137}
138
139# True if the object format is known to be 64-bit ELF.
140#
141proc is_elf64 { binary_file } {
142    global READELF
143    global READELFFLAGS
144
145    set tmpfile [file dirname $binary_file]/readelf.out
146    set readelf_size ""
147    catch "exec $READELF $READELFFLAGS -h $binary_file > $tmpfile" got
148
149    if ![string match "" $got] then {
150	return 0
151    }
152
153    if { ![regexp "\n\[ \]*Class:\[ \]*ELF(\[0-9\]+)\n" \
154	   [file_contents $tmpfile] nil readelf_size] } {
155	return 0
156    }
157
158    if { $readelf_size == "64" } {
159	return 1
160    }
161
162    return 0
163}
164
165# True if the object format is known to use RELA relocations.
166#
167proc is_rela { binary_file } {
168    global READELF
169    global READELFFLAGS
170
171    set tmpfile [file dirname $binary_file]/readelf.out
172    catch "exec $READELF $READELFFLAGS -S $binary_file > $tmpfile" got
173
174    if ![string match "" $got] then {
175	return 0
176    }
177
178    if { ![regexp "RELA" [file_contents $tmpfile]] } {
179	return 0
180    }
181
182    return 1
183}
184
185# True if the target matches TARGET, specified as a TCL procedure if
186# in square brackets or as machine triplet otherwise.
187#
188proc match_target { target } {
189   if [regexp {^!?\[.*\]$} $target] {
190	return $target
191   } else {
192	return [istarget $target]
193   }
194}
195
196# True if the ELF target supports setting the ELF header OSABI field
197# to ELFOSABI_GNU or ELFOSABI_FREEBSD, a requirement for STT_GNU_IFUNC
198# symbol and SHF_GNU_MBIND section support.
199#
200# This generally depends on the target OS only, however there are a
201# number of exceptions for bare metal targets as follows.  The MSP430
202# and Visium targets set OSABI to ELFOSABI_STANDALONE.  Likewise
203# non-EABI ARM targets set OSABI to ELFOSABI_ARM
204#
205# Note that some TI C6X targets use ELFOSABI_C6000_* but one doesn't,
206# so we don't try to sort out tic6x here.  (The effect is that linker
207# testcases will generally need to exclude tic6x or use a -m option.)
208#
209proc supports_gnu_osabi {} {
210    if { [istarget *-*-gnu*]
211	 || [istarget *-*-linux*]
212	 || [istarget *-*-nacl*]
213	 || ( [istarget *-*-*bsd*] && ![istarget arm*-*-netbsd*] )
214	 || [istarget *-*-symbianelf]
215	 || [istarget *-*-lynxos]
216	 || ( [istarget *-*-nto*] && ![istarget arm*-*-*] )
217	 || [istarget *-*-irix*]
218	 || [istarget *-*-*eabi*]
219	 || [istarget *-*-rtems*] } {
220	return 1
221    }
222    if { [istarget "wasm32*-*-*"] } {
223        return 1
224    }
225    if { ![istarget "*-*-elf*"] } {
226	return 0
227    }
228    if { [istarget "arm*-*-*"]
229	 || [istarget "msp430-*-*"]
230	 || [istarget "visium-*-*"] } {
231	return 0
232    }
233    return 1
234}
235
236# Return true if target uses the generic_link_hash_table linker.
237proc is_generic { } {
238    if { [istarget "d30v-*-*"]
239	 || [istarget "dlx-*-*"]
240	 || [istarget "pj*-*-*"]
241	 || [istarget "s12z-*-*"]
242	 || [istarget "xgate-*-*"] } {
243	return 1
244    }
245    return 0
246}
247
248# True if the ELF target supports STB_GNU_UNIQUE.
249#
250# This require ELFOSABI_GNU, and `bfd_elf_final_link'.
251#
252proc supports_gnu_unique {} {
253    if { [istarget *-*-freebsd*] } {
254	return 0
255    }
256    if { [supports_gnu_osabi] && ![is_generic] } {
257	return 1
258    }
259    return 0
260}
261
262# True for targets that do not sort .symtab as per the ELF standard.
263# ie. any that have mips_elf32_be_vec, mips_elf32_le_vec,
264# mips_elf32_n_be_vec or mips_elf32_n_le_vec as the primary bfd target
265# vector in config.bfd.  When syncing with config.bfd, don't forget that
266# earlier case-matches trump later ones.
267proc is_bad_symtab {} {
268    if { ![istarget "mips*-*-*"] } {
269	return 0;
270    }
271    if { [istarget "*-*-chorus*"]
272	 || [istarget "*-*-irix5*"]
273	 || [istarget "*-*-irix6*"]
274	 || [istarget "*-*-none"]
275	 || [istarget "*-*-rtems*"]
276	 || [istarget "*-*-windiss"] } {
277	return 1;
278    }
279    if { [istarget "*-*-elf*"]
280	 && ![istarget "*-sde-*"]
281	 && ![istarget "*-mti-*"]
282	 && ![istarget "*-img-*"] } {
283	return 1;
284    }
285    if { [istarget "*-*-openbsd*"]
286	 && ![istarget "mips64*-*-*"] } {
287	return 1;
288    }
289    return 0;
290}
291
292# Returns true if -shared is supported on the target
293
294proc check_shared_lib_support { } {
295    global shared_available_saved
296    global ld
297
298    if {![info exists shared_available_saved]} {
299	set ld_output [remote_exec host $ld "-shared"]
300	if { [ string first "not supported" $ld_output ] >= 0 } {
301	    set shared_available_saved 0
302	} else {
303	    set shared_available_saved 1
304	}
305    }
306    return $shared_available_saved
307}
308
309# Returns true if -pie is supported on the target
310
311proc check_pie_support { } {
312    global pie_available_saved
313    global ld
314
315    if {![info exists pie_available_saved]} {
316	set ld_output [remote_exec host $ld "-pie"]
317	if { [ string first "not supported" $ld_output ] >= 0 } {
318	    set pie_available_saved 0
319	} else {
320	    set pie_available_saved 1
321	}
322    }
323    return $pie_available_saved
324}
325
326proc check_relro_support { } {
327    global relro_available_saved
328    global ld
329
330    if {![info exists relro_available_saved]} {
331	remote_file host delete norelro
332	set ld_output [remote_exec host $ld "-z norelro"]
333	if { [string first "not supported" $ld_output] >= 0
334	     || [string first "unrecognized option" $ld_output] >= 0
335	     || [string first "-z norelro ignored" $ld_output] >= 0
336	     || [string first "cannot find norelro" $ld_output] >= 0 } {
337	    set relro_available_saved 0
338	} else {
339	    set relro_available_saved 1
340	}
341    }
342    return $relro_available_saved
343}
344
345# Compare two files line-by-line.  FILE_1 is the actual output and FILE_2
346# is the expected output.  Ignore blank lines in either file.
347#
348# FILE_2 is a series of regexps, comments and # directives.  The directives
349# are:
350#
351#    #pass
352#        Treat the test as a PASS if everything up till this point has
353#        matched.  Ignore any remaining lines in either FILE_1 or FILE_2.
354#
355#    #failif
356#        Reverse the sense of the test: expect differences to exist.
357#
358#    #...
359#    REGEXP
360#        Skip all lines in FILE_1 until the first that matches REGEXP.
361#
362#    #?REGEXP
363#        Optionally match REGEXP against line from FILE_1.  If the REGEXP
364#        does not match then the next line from FILE_2 is tried.
365#
366# Other # lines are comments.  Regexp lines starting with the `!' character
367# specify inverse matching (use `\!' for literal matching against a leading
368# `!').  Skip empty lines in both files.
369#
370# The first optional argument is a list of regexp substitutions of the form:
371#
372#    EXP1 SUBSPEC1 EXP2 SUBSPEC2 ...
373#
374# This tells the function to apply each regexp substitution EXPi->SUBSPECi
375# in order to every line of FILE_2.
376#
377# Return nonzero if differences exist.
378proc regexp_diff { file_1 file_2 args } {
379    set eof -1
380    set end_1 0
381    set end_2 0
382    set differences 0
383    set diff_pass 0
384    set fail_if_match 0
385    set ref_subst ""
386    if { [llength $args] > 0 } {
387	set ref_subst [lindex $args 0]
388    }
389    if { [llength $args] > 1 } {
390	perror "Too many arguments to regexp_diff"
391	return 1
392    }
393
394    if [file exists $file_1] then {
395	set file_a [open $file_1 r]
396    } else {
397	perror "$file_1 doesn't exist"
398	return 1
399    }
400
401    if [file exists $file_2] then {
402	set file_b [open $file_2 r]
403    } else {
404	perror "$file_2 doesn't exist"
405	close $file_a
406	return 1
407    }
408
409    verbose " Regexp-diff'ing: $file_1 $file_2" 2
410
411    while { 1 } {
412	set line_a ""
413	set line_b ""
414	while { [string length $line_a] == 0 } {
415	    # Ignore blank line in FILE_1.
416	    if { [gets $file_a line_a] == $eof } {
417		set end_1 1
418		break
419	    }
420	}
421	while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
422	    if { [string match "#pass" $line_b] } {
423		set end_2 1
424		set diff_pass 1
425		break
426	    } elseif { [string match "#failif" $line_b] } {
427		send_log "fail if no difference\n"
428		verbose "fail if no difference" 3
429		set fail_if_match 1
430	    } elseif { [string match "#..." $line_b] } {
431		if { [gets $file_b line_b] == $eof } {
432		    set end_2 1
433		    set diff_pass 1
434		    break
435		}
436		set negated [expr { [string index $line_b 0] == "!" }]
437		set line_bx [string range $line_b $negated end]
438		set n [expr { $negated ? "! " : "" }]
439		# Substitute on the reference.
440		foreach {name value} $ref_subst {
441		    regsub -- $name $line_bx $value line_bx
442		}
443		verbose "looking for $n\"^$line_bx$\"" 3
444		while { [expr [regexp "^$line_bx$" "$line_a"] == $negated] } {
445		    verbose "skipping    \"$line_a\"" 3
446		    if { [gets $file_a line_a] == $eof } {
447			set end_1 1
448			break
449		    }
450		}
451		break
452	    } elseif { [string match "#\\?*" $line_b] } {
453		if { ! $end_1 } {
454		    set line_b [string replace $line_b 0 1]
455		    set negated [expr { [string index $line_b 0] == "!" }]
456		    set line_bx [string range $line_b $negated end]
457		    set n [expr { $negated ? "! " : "" }]
458		    # Substitute on the reference.
459		    foreach {name value} $ref_subst {
460			regsub -- $name $line_bx $value line_bx
461		    }
462		    verbose "optional match for $n\"^$line_bx$\"" 3
463		    if { [expr [regexp "^$line_bx$" "$line_a"] != $negated] } {
464			break
465		    }
466		}
467	    }
468	    if { [gets $file_b line_b] == $eof } {
469		set end_2 1
470		break
471	    }
472	}
473
474	if { $diff_pass } {
475	    break
476	} elseif { $end_1 && $end_2 } {
477	    break
478	} elseif { $end_1 } {
479	    send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
480	    verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
481	    set differences 1
482	    break
483	} elseif { $end_2 } {
484	    send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
485	    verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
486	    set differences 1
487	    break
488	} else {
489	    set negated [expr { [string index $line_b 0] == "!" }]
490	    set line_bx [string range $line_b $negated end]
491	    set n [expr { $negated ? "! " : "" }]
492	    set s [expr { $negated ? "  " : "" }]
493	    # Substitute on the reference.
494	    foreach {name value} $ref_subst {
495		regsub -- $name $line_bx $value line_bx
496	    }
497	    verbose "regexp $n\"^$line_bx$\"\nline   \"$line_a\"" 3
498	    if { [expr [regexp "^$line_bx$" "$line_a"] == $negated] } {
499		send_log "regexp_diff match failure\n"
500		send_log "regexp $n\"^$line_bx$\"\nline   $s\"$line_a\"\n"
501		verbose "regexp_diff match failure\n" 3
502		set differences 1
503	    }
504	}
505    }
506
507    if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
508	send_log "$file_1 and $file_2 are different lengths\n"
509	verbose "$file_1 and $file_2 are different lengths" 3
510	set differences 1
511    }
512
513    if { $fail_if_match } {
514	if { $differences == 0 } {
515	    set differences 1
516	} else {
517	    set differences 0
518	}
519    }
520
521    close $file_a
522    close $file_b
523
524    return $differences
525}
526
527# prune_warnings_extra -- delete extra warnings from TEXT.
528#
529# An example is:
530# ld: warning: /lib64/ld-linux-x86-64.so.2: unsupported GNU_PROPERTY_TYPE (5) type : 0xc0010001
531proc prune_warnings_extra { text } {
532    global experimental
533    # Warnings are only pruned from non-experimental code (ie code not
534    # on a release branch).  For experimental code we want the warnings
535    # as they indicate that the sources need to be updated to recognise
536    # the new properties.
537    if { "$experimental" == "false" } {
538	# The "\\1" is to try to preserve a "\n" but only if necessary.
539	regsub -all "(^|\n)(\[^\n\]*: warning:\[^\n\]*unsupported GNU_PROPERTY_TYPE\[^\n\]*\n?)+" $text "\\1" text
540    }
541    # PR binutils/23898: It is OK to have gaps in build notes.
542    regsub -all "(^|\n)(\[^\n\]*: Warning: Gap in build notes detected from\[^\n\]*\n?)+" $text "\\1" text
543    return $text
544}
545
546# This definition is taken from an unreleased version of DejaGnu.  Once
547# that version gets released, and has been out in the world for a few
548# months at least, it may be safe to delete this copy.
549if ![string length [info proc prune_warnings]] {
550    #
551    # prune_warnings -- delete various system verbosities from TEXT
552    #
553    # An example is:
554    # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
555    #
556    # Sites with particular verbose os's may wish to override this in site.exp.
557    #
558    proc prune_warnings { text } {
559	# This is from sun4's.  Do it for all machines for now.
560	# The "\\1" is to try to preserve a "\n" but only if necessary.
561	regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text
562	# It might be tempting to get carried away and delete blank lines, etc.
563	# Just delete *exactly* what we're ask to, and that's it.
564	set text [prune_warnings_extra $text]
565	return $text
566    }
567} elseif { [info procs saved-prune_warnings] == [list] } {
568    rename prune_warnings saved-prune_warnings
569    proc prune_warnings { text } {
570	set text [saved-prune_warnings $text]
571	set text [prune_warnings_extra $text]
572	return $text
573    }
574}
575
576# run_dump_test FILE (optional:) EXTRA_OPTIONS
577#
578# Assemble a .s file, then run some utility on it and check the output.
579# Optionally generate the .s file first by running the compiler.
580#
581# There should be an assembly language file named FILE.s in the test
582# suite directory, and a pattern file called FILE.d.  run_dump_test
583# will assemble FILE.s, optionally run objcopy on the object file,
584# optionally run ld, optionally run another objcopy, optionally run
585# another tool under test specified by PROG, then run a dump tool like
586# addr2line, nm, objdump, readelf or size on the object file to produce
587# textual output, and then analyze that with regexps.
588# The FILE.d file specifies what program to run, and what to expect in
589# its output.
590#
591# The FILE.d file begins with zero or more option lines, which specify
592# flags to pass to the assembler, the program to run to dump the
593# assembler's output, and the options it wants.  The option lines have
594# the syntax:
595#
596#         # OPTION: VALUE
597#
598# OPTION is the name of some option, like "name" or "objdump", and
599# VALUE is OPTION's value.  The valid options are described below.
600# Whitespace is ignored everywhere, except within VALUE.  The option
601# list ends with the first line that doesn't match the above syntax.
602# However, a line within the options that begins with a #, but doesn't
603# have a recognizable option name followed by a colon, is considered a
604# comment and entirely ignored.
605#
606# The optional EXTRA_OPTIONS argument to `run_dump_test' is a list of
607# two-element lists.  The first element of each is an option name, and
608# the second additional arguments to be added on to the end of the
609# option list as given in FILE.d.  (If omitted, no additional options
610# are added.)
611#
612# The interesting options are:
613#
614#   name: TEST-NAME
615#	The name of this test, passed to DejaGNU's `pass' and `fail'
616#	commands.  If omitted, this defaults to FILE, the root of the
617#	.s and .d files' names.
618#
619#   as: FLAGS
620#	When assembling, pass FLAGS to the assembler.
621#	If assembling several files, you can pass different assembler
622#	options in the "source" directives.  See below.
623#       Multiple instances of this directive tells run_dump_test to run the test
624#       multiple times -- one time with each set of flags provided.
625#       Each instance will run exactly as a file with a single "as" line, it is
626#       not possible to condition any behaviour on which set of "as" flags is
627#       used.  That means that the "source" specific options are appended to
628#       the "as" flags for their corresponding files, and any extra processing
629#       (e.g. with "ld" and "objcopy") is repeated for each test.
630#
631#   ld: FLAGS
632#	Link assembled files using FLAGS, in the order of the "source"
633#	directives, when using multiple files.
634#
635#   ld_after_inputfiles: FLAGS
636#	Similar to "ld", but put FLAGS after all input files.
637#
638#   cc: FLAGS
639#       Run the compiler with FLAGS (to which -S is added) to generate assembler
640#       source first.  source: must be provided and should consist of .c files.
641#       Source-specific CC flags are not supported.
642#
643#   objcopy_objects: FLAGS
644#	Run objcopy with the specified flags after assembling any source
645#	that has the special marker RUN_OBJCOPY in the source specific
646#	flags.
647#
648#   objcopy_linked_file: FLAGS
649#	Run objcopy on the linked file with the specified flags.
650#	This lets you transform the linked file using objcopy, before the
651#	result is analyzed by an analyzer program specified below.
652#
653#   PROG: PROGRAM-NAME
654#	The name of a program under test, to run to modify or analyze the
655#	.o file produced by the assembler.  Recognised names are: ar,
656#	elfedit, nm, objcopy, ranlib, strings, and strip.
657#
658#   DUMPPROG: PROGRAM-NAME
659#       The name of the program to run to analyze the file produced
660#       by the assembler or the linker.  This can be omitted;
661#       run_dump_test will guess which program to run from which of
662#       the flags options below is present.
663#
664#   addr2line: FLAGS
665#   nm: FLAGS
666#   objdump: FLAGS
667#   readelf: FLAGS
668#   size: FLAGS
669#	Use the specified program to analyze the output file, and pass it
670#	FLAGS, in addition to the output name.  Note that they are run
671#	with LC_ALL=C in the environment to give consistent sorting of
672#	symbols.  If no FLAGS are needed then you can use:
673#	    DUMPPROG: [nm objdump readelf addr2line]
674#	instead, or just pass a flag that happens to be the default.
675#	If objdump is the dump tool and we're not dumping binary, nor
676#	have run ld, then the standard section names (.text, .data and
677#	.bss) are replaced by target ones if any (eg. rx-elf uses "P"
678#	instead of .text).  The substition is done for both the
679#	objdump options (eg: "-j .text" is replaced by "-j P") and the
680#	reference file.
681#
682#   source: SOURCE [FLAGS]
683#	Assemble the file SOURCE.s using the flags in the "as" directive
684#	and the (optional) FLAGS.  If omitted, the source defaults to
685#	FILE.s.
686#	This is useful if several .d files want to share a .s file.
687#	More than one "source" directive can be given, which is useful
688#	when testing linking.
689#
690#   dump: DUMP
691#	Match against DUMP.d.  If omitted, this defaults to FILE.d.  This
692#	is useful if several .d files differ by options only.  Options are
693#	always read from FILE.d.
694#
695#   target: GLOB|PROC ...
696#	Run this test only on a specified list of targets.  More precisely,
697#	in the space-separated list each glob is passed to "istarget" and
698#	each proc is called as a TCL procedure.  List items are interpreted
699#	such that procs are denoted by surrounding square brackets, and any
700#	other items are consired globs.  If the call evaluates true for any
701#	of them, the test will be run, otherwise it will be marked
702#	unsupported.
703#
704#   notarget: GLOB|PROC ...
705#	Do not run this test on a specified list of targets.  Again, each
706#	glob in the space-separated list is passed to "istarget" and each
707#	proc is called as a TCL procedure, and the test is run if it
708#	evaluates *false* for *all* of them.  Otherwise it will be marked
709#	unsupported.
710#
711#   alltargets: GLOB|PROC ...
712#	Run this test on a specified list of targets.  Again, each
713#	glob in the space-separated list is passed to "istarget" and each
714#	proc is called as a TCL procedure, and the test is run if it
715#	evaluates *true* for *all* of them.  Otherwise it will be marked
716#	unsupported.
717#
718#   skip: GLOB|PROC ...
719#   anyskip: GLOB|PROC ...
720#   noskip: GLOB|PROC ...
721#	These are exactly the same as "notarget", "alltargets" and
722#	"target" respectively, except that they do nothing at all if the
723#	check fails.  They should only be used in groups, to construct a
724#	single test which is run on all targets but with variant options
725#	or expected output on some targets.  (For example, see
726#	gas/arm/inst.d and gas/arm/wince_inst.d.)
727#
728#   xfail: GLOB|PROC ...
729#	Run this test and it is is expected to fail on a specified list
730#	of targets.
731#
732#   error: REGEX
733#	An error with message matching REGEX must be emitted for the test
734#	to pass.  The DUMPPROG, addr2line, nm, objdump, readelf and size
735#	options have no meaning and need not supplied if this is present.
736#	Multiple "error" directives append to the expected error message.
737#
738#   error_output: FILE
739#	Means the same as 'error', except the regular expression lines
740#	are contains in FILE.
741#
742#   warning: REGEX
743#	Expect a warning matching REGEX.  It is an error to issue
744#	both "error" and "warning".  Multiple "warning" directives
745#	append to the expected warning message.
746#
747#   warning_output: FILE
748#	Means the same as 'warning', except the regular expression
749#	lines are contains in FILE.
750#
751#   map: FILE
752#	Adding this option will cause the linker to generate a linker
753#	map file, using the -Map=MAPFILE command line option.  If
754#	there is no -Map=MAPFILE in the 'ld: FLAGS' then one will be
755#	added to the linker command line.  The contents of the
756#	generated MAPFILE are then compared against the regexp lines
757#	in FILE using `regexp_diff' (see below for details).
758#
759#   section_subst: no
760#	Means that the section substitution for objdump is disabled.
761#
762# Each option may occur at most once unless otherwise mentioned.
763#
764# After the option lines come regexp lines.  run_dump_test calls
765# regexp_diff to compare the output of the dumping tool against the
766# regexps in FILE.d.
767#
768proc run_dump_test { name {extra_options {}} } {
769    global ADDR2LINE ADDR2LINEFLAGS AS ASFLAGS CC CFLAGS ELFEDIT ELFEDITFLAGS
770    global LD LDFLAGS NM NMFLAGS OBJCOPY OBJCOPYFLAGS OBJDUMP OBJDUMPFLAGS
771    global READELF READELFFLAGS STRIP STRIPFLAGS
772    global copyfile env runtests srcdir subdir verbose
773
774    if [string match "*/*" $name] {
775	set file $name
776	set name [file tail $name]
777    } else {
778	set file "$srcdir/$subdir/$name"
779    }
780
781    if ![runtest_file_p $runtests $name] then {
782	return
783    }
784
785    set opt_array [slurp_options "${file}.d"]
786    if { $opt_array == -1 } {
787	perror "error reading options from $file.d"
788	unresolved $subdir/$name
789	return
790    }
791    set dumpfile tmpdir/dump.out
792    set run_ld 0
793    set run_objcopy 0
794    set objfile_names {}
795    set opts(PROG) {}
796    set opts(DUMPPROG) {}
797    set opts(addr2line) {}
798    set opts(alltargets) {}
799    set opts(anyskip) {}
800    set opts(ar) {}
801    set opts(as) {}
802    set as_final_flags {}
803    set as_additional_flags {}
804    set opts(cc) {}
805    set opts(dump) {}
806    set opts(elfedit) {}
807    set opts(error) {}
808    set opts(error_output) {}
809    set opts(ld) {}
810    set opts(ld_after_inputfiles) {}
811    set opts(map) {}
812    set opts(name) {}
813    set opts(nm) {}
814    set opts(noskip) {}
815    set opts(notarget) {}
816    set opts(objcopy) {}
817    set opts(objcopy_linked_file) {}
818    set opts(objcopy_objects) {}
819    set opts(objdump) {}
820    set opts(ranlib) {}
821    set opts(readelf) {}
822    set opts(section_subst) {}
823    set opts(size) {}
824    set opts(strings) {}
825    set opts(strip) {}
826    set opts(skip) {}
827    set opts(source) {}
828    set opts(strip) {}
829    set opts(target) {}
830    set opts(warning) {}
831    set opts(warning_output) {}
832    set opts(xfail) {}
833
834    set in_extra 0
835    foreach i [concat $opt_array {{} {}} $extra_options] {
836	set opt_name [lindex $i 0]
837	set opt_val [lindex $i 1]
838	if { $opt_name == "" } {
839	    set in_extra 1
840	    continue
841	}
842	if ![info exists opts($opt_name)] {
843	    perror "unknown option $opt_name in file $file.d"
844	    unresolved $subdir/$name
845	    return
846	}
847
848	# Allow more substitutions, including tcl functions, for as, ld,
849	# and cc.  Not done in general because extra quoting is needed for glob
850	# args used for example in binutils-all/remove-relocs-04.d.
851	if { $opt_name == "as" || $opt_name == "ld" || $opt_name == "cc" } {
852	    set opt_val [subst $opt_val]
853	} else {
854	    # Just substitute $srcdir and $subdir
855	    regsub -all {\$srcdir} "$opt_val" "$srcdir" opt_val
856	    regsub -all {\$subdir} "$opt_val" "$subdir" opt_val
857	}
858
859	switch -- $opt_name {
860	    xfail {}
861	    target {}
862	    alltargets {}
863	    notarget {}
864	    skip {}
865	    anyskip {}
866	    noskip {}
867	    warning {}
868	    error {}
869	    source {
870		# Move any source-specific as-flags to a separate list to
871		# simplify processing.
872		if { [llength $opt_val] > 1 } {
873		    lappend asflags [lrange $opt_val 1 end]
874		    set opt_val [lindex $opt_val 0]
875		} else {
876		    lappend asflags {}
877		}
878
879		# Create the object file name based on nothing but the source
880		# file name.
881		set new_objfile \
882		    [concat tmpdir/[file rootname [file tail [lindex $opt_val 0]]].o]
883		# But, sometimes, we have the exact same source filename in
884		# different directories (foo/src.s bar/src.s) which would lead
885		# us to try and create two src.o files.  We detect this
886		# conflict here, and instead create src.o and src1.o.
887		set j 0
888		while { [lsearch $objfile_names $new_objfile] != -1 } {
889		    incr j
890		    set new_objfile \
891			[concat tmpdir/[file rootname [file tail  [lindex $opt_val 0]]]${j}.o]
892		}
893		lappend objfile_names $new_objfile
894	    }
895	    default {
896		if { !$in_extra
897                     && [string length $opts($opt_name)]
898                     && $opt_name != "as" } {
899		    perror "option $opt_name multiply set in $file.d"
900		    unresolved $subdir/$name
901		    return
902		}
903
904		# A single "#ld:" with no options should do the right thing.
905		if { $opt_name == "ld" } {
906		    set run_ld 1
907		}
908		# Likewise objcopy_linked_file.
909		if { $opt_name == "objcopy_linked_file" } {
910		    set run_objcopy 1
911		}
912	    }
913	}
914
915	# Append differently whether it's a message (without space) or
916	# an option or list (with space).
917	switch -- $opt_name {
918	    warning -
919	    error {
920		append opts($opt_name) $opt_val
921	    }
922            as {
923                if { $in_extra } {
924                    set as_additional_flags [concat $as_additional_flags $opt_val]
925                } else {
926                    lappend opts(as) $opt_val
927                }
928            }
929	    default {
930		set opts($opt_name) [concat $opts($opt_name) $opt_val]
931	    }
932	}
933    }
934
935    # Ensure there is something in $opts(as) for the foreach loop below.
936    if { [llength $opts(as)] == 0 } {
937        set opts(as) [list " "]
938    }
939    foreach x $opts(as) {
940        if { [string length $x] && [string length $as_additional_flags] } {
941            append x " "
942        }
943        append x $as_additional_flags
944        regsub {\[big_or_little_endian\]} $x \
945            [big_or_little_endian] x
946        lappend as_final_flags $x
947    }
948
949    regsub {\[big_or_little_endian\]} $opts(ld) \
950        [big_or_little_endian] opts(ld)
951
952    if { $opts(name) == "" } {
953	set testname "$subdir/$name"
954    } else {
955	set testname $opts(name)
956    }
957
958    set err_warn 0
959    foreach opt { warning error warning_output error_output } {
960	if { $opts($opt) != "" } {
961	    if { $err_warn } {
962		perror "$testname: bad mix of warning and error test directives"
963		unresolved $testname
964		return
965	    }
966	    set err_warn 1
967	}
968    }
969
970    # Decide early whether we should run the test for this target.
971    if { [llength $opts(noskip)] > 0 } {
972	set targmatch 0
973	foreach targ $opts(noskip) {
974	    if [match_target $targ] {
975		set targmatch 1
976		break
977	    }
978	}
979	if { $targmatch == 0 } {
980	    return
981	}
982    }
983    foreach targ $opts(anyskip) {
984	if ![match_target $targ] {
985	    return
986	}
987    }
988    foreach targ $opts(skip) {
989	if [match_target $targ] {
990	    return
991	}
992    }
993    if { [llength $opts(target)] > 0 } {
994	set targmatch 0
995	foreach targ $opts(target) {
996	    if [match_target $targ] {
997		set targmatch 1
998		break
999	    }
1000	}
1001	if { $targmatch == 0 } {
1002	    unsupported $testname
1003	    return
1004	}
1005    }
1006    foreach targ $opts(alltargets) {
1007	if ![match_target $targ] {
1008	    unsupported $testname
1009	    return
1010	}
1011    }
1012    foreach targ $opts(notarget) {
1013	if [match_target $targ] {
1014	    unsupported $testname
1015	    return
1016	}
1017    }
1018
1019    set dumpprogram ""
1020    # It's meaningless to require an output-testing method when we
1021    # expect an error.
1022    if { $opts(error) == "" && $opts(error_output) == "" } {
1023	if { $opts(DUMPPROG) != "" } {
1024	    switch -- $opts(DUMPPROG) {
1025		addr2line	{ set dumpprogram addr2line }
1026		nm		{ set dumpprogram nm }
1027		objdump		{ set dumpprogram objdump }
1028		readelf		{ set dumpprogram readelf }
1029		size		{ set dumpprogram size }
1030		default		{
1031		    perror "unrecognized DUMPPROG option $opts(DUMPPROG) in $file.d"
1032		    unresolved $testname
1033		    return
1034		}
1035	    }
1036	} else {
1037	    # Guess which program to run, by seeing which option was specified.
1038	    foreach p {addr2line nm objdump readelf size} {
1039		if {$opts($p) != ""} {
1040		    if {$dumpprogram != ""} {
1041			perror "ambiguous dump program in $file.d"
1042			unresolved $testname
1043			return
1044		    } else {
1045			set dumpprogram $p
1046		    }
1047		}
1048	    }
1049	}
1050	if { $dumpprogram == "" && $opts(map) == "" && !$err_warn } {
1051	    perror "dump program unspecified in $file.d"
1052	    unresolved $testname
1053	    return
1054	}
1055    }
1056
1057    # Possibly compile some of the inputs, and build up a replacement
1058    # for opts(source) with the output .s names substituted in as we go.
1059    # Set the .s names from the objfile_names to take advantage of the
1060    # uniquification that happened earlier.
1061    if { $opts(cc) != ""} {
1062	set cmdret 0
1063	set new_source ""
1064
1065	foreach cfile $opts(source) ofile $objfile_names {
1066	    if { [file extension $cfile] != ".c" } {
1067		lappend new_source "$cfile"
1068		continue
1069	    }
1070
1071	    if { ! [string match "./*" $cfile] } {
1072		set cfile "$srcdir/$subdir/$cfile"
1073	    }
1074	    # ofile is never absolute, so this always works to protect sfile
1075	    # from later absolutization.
1076	    set sfile "./[file rootname $ofile].s"
1077	    set cmd "$CC $CFLAGS -S $opts(cc) -o $sfile $cfile"
1078	    send_log "$cmd\n"
1079	    set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "dump.tmp"]
1080	    remote_upload host "dump.tmp"
1081	    set comp_output [prune_warnings [file_contents "dump.tmp"]]
1082	    remote_file host delete "dump.tmp"
1083	    remote_file build delete "dump.tmp"
1084	    lappend new_source "$sfile"
1085	    set cmdret [lindex $cmdret 0]
1086
1087	    regsub "\n$" $comp_output "" comp_output
1088	    if { $cmdret != 0} {
1089		send_log "compilation of $cfile failed, exit status $cmdret with <$comp_output>"
1090                # Should this be 'unresolved', or is that too silent?
1091		fail $testname
1092		return 0
1093	    }
1094	}
1095	set opts(source) $new_source
1096    }
1097
1098    if { $opts(source) == "" } {
1099	set sourcefiles [list ${file}.s]
1100	set asflags [list ""]
1101	set objfile_names [list tmpdir/[file tail ${file}].o]
1102    } else {
1103	set sourcefiles {}
1104	foreach sf $opts(source) {
1105	    if { [string match "./*" $sf] } {
1106		lappend sourcefiles "$sf"
1107	    } else {
1108		lappend sourcefiles "$srcdir/$subdir/$sf"
1109	    }
1110	}
1111    }
1112
1113    if { $opts(dump) == "" } {
1114	set dfile ${file}.d
1115    } else {
1116	set dfile $srcdir/$subdir/$opts(dump)
1117    }
1118
1119    # Time to setup xfailures.
1120    foreach targ $opts(xfail) {
1121	if [match_target $targ] {
1122	    setup_xfail "*-*-*"
1123	    break
1124	}
1125    }
1126
1127    foreach as_flags $as_final_flags {
1128        # Assemble each file.
1129        set objfiles {}
1130        for { set i 0 } { $i < [llength $sourcefiles] } { incr i } {
1131            set sourcefile [lindex $sourcefiles $i]
1132            set sourceasflags [lindex $asflags $i]
1133            set run_objcopy_objects 0
1134
1135            if { [string match "*RUN_OBJCOPY*" $sourceasflags] } {
1136                set run_objcopy_objects 1
1137            }
1138            regsub "RUN_OBJCOPY" $sourceasflags "" sourceasflags
1139
1140            set objfile [lindex $objfile_names $i]
1141            catch "exec rm -f $objfile" exec_output
1142            lappend objfiles $objfile
1143
1144            if { $as_flags == "binary" } {
1145                while {[file type $sourcefile] eq "link"} {
1146                    set newfile [file readlink $sourcefile]
1147                    if {[string index $newfile 0] ne "/"} {
1148                        set newfile [file dirname $sourcefile]/$newfile
1149                    }
1150                    set sourcefile $newfile
1151                }
1152                set newfile [remote_download host $sourcefile $objfile]
1153                set cmdret 0
1154                if { $newfile == "" } {
1155                    set cmdret 1
1156                }
1157            } else {
1158                if { [istarget "hppa*-*-*"] \
1159                         && ![istarget "*-*-linux*"] \
1160                         && ![istarget "*-*-netbsd*" ] } {
1161                    set cmd "sed -e 's/^\[	 \]*\.comm \\(\[^,\]*\\),\\(.*\\)/\\1 .comm \\2/' < $sourcefile > tmpdir/asm.s"
1162                    send_log "$cmd\n"
1163                    set cmdret [remote_exec host [concat sh -c [list "$cmd"]]]
1164                    set cmdret [lindex $cmdret 0]
1165                    if { $cmdret != 0 } {
1166                        perror "sed failure"
1167                        unresolved $testname
1168                        continue
1169                    }
1170                    set sourcefile tmpdir/asm.s
1171                }
1172                set cmd "$AS $ASFLAGS $as_flags $sourceasflags -o $objfile $sourcefile"
1173
1174                send_log "$cmd\n"
1175                set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "dump.tmp"]
1176                remote_upload host "dump.tmp"
1177                set comp_output [prune_warnings [file_contents "dump.tmp"]]
1178                remote_file host delete "dump.tmp"
1179                remote_file build delete "dump.tmp"
1180                set cmdret [lindex $cmdret 0]
1181            }
1182            if { $cmdret == 0 && $run_objcopy_objects } {
1183                set cmd "$OBJCOPY $opts(objcopy_objects) $objfile"
1184
1185                send_log "$cmd\n"
1186                set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] \
1187                                "" "/dev/null" "dump.tmp"]
1188                remote_upload host "dump.tmp"
1189                append comp_output [prune_warnings [file_contents "dump.tmp"]]
1190                remote_file host delete "dump.tmp"
1191                remote_file build delete "dump.tmp"
1192                set cmdret [lindex $cmdret 0]
1193            }
1194        }
1195
1196        # Perhaps link the file(s).
1197        if { $cmdret == 0 && $run_ld } {
1198            set objfile "tmpdir/dump"
1199            catch "exec rm -f $objfile" exec_output
1200
1201            set ld_extra_opt ""
1202            global ld
1203            set ld "$LD"
1204	    if [check_relro_support] {
1205		set ld_extra_opt "-z norelro"
1206	    }
1207
1208            # Add -L$srcdir/$subdir so that the linker command can use
1209            # linker scripts in the source directory.
1210            set cmd "$LD $ld_extra_opt $LDFLAGS -L$srcdir/$subdir \
1211		   $opts(ld) -o $objfile $objfiles $opts(ld_after_inputfiles)"
1212
1213            # If needed then check for, or add a -Map option.
1214            set mapfile ""
1215            if { $opts(map) != "" } then {
1216                if { [regexp -- "-Map=(\[^ \]+)" $cmd all mapfile] } then {
1217                    # Found existing mapfile option
1218                    verbose -log "Existing mapfile '$mapfile' found"
1219                } else {
1220                    # No mapfile option.
1221                    set mapfile "tmpdir/dump.map"
1222                    verbose -log "Adding mapfile '$mapfile'"
1223                    set cmd "$cmd -Map=$mapfile"
1224                }
1225            }
1226
1227            send_log "$cmd\n"
1228            set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "dump.tmp"]
1229            remote_upload host "dump.tmp"
1230            append comp_output [file_contents "dump.tmp"]
1231            remote_file host delete "dump.tmp"
1232            remote_file build delete "dump.tmp"
1233            set cmdret [lindex $cmdret 0]
1234
1235            if { $cmdret == 0 && $run_objcopy } {
1236                set infile $objfile
1237                set objfile "tmpdir/dump1"
1238                remote_file host delete $objfile
1239
1240                # Note that we don't use OBJCOPYFLAGS here; any flags must be
1241                # explicitly specified.
1242                set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile"
1243
1244                send_log "$cmd\n"
1245                set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "dump.tmp"]
1246                remote_upload host "dump.tmp"
1247                append comp_output [file_contents "dump.tmp"]
1248                remote_file host delete "dump.tmp"
1249                remote_file build delete "dump.tmp"
1250                set cmdret [lindex $cmdret 0]
1251            }
1252        } else {
1253            set objfile [lindex $objfiles 0]
1254        }
1255
1256        if { $cmdret == 0 && $opts(PROG) != "" } {
1257            set destopt ${copyfile}.o
1258            switch -- $opts(PROG) {
1259                ar		{ set program ar }
1260                elfedit	{
1261                    set program elfedit
1262                    set destopt ""
1263                }
1264                nm		{ set program nm }
1265                objcopy	{ set program objcopy }
1266                ranlib	{ set program ranlib }
1267                strings	{ set program strings }
1268                strip	{
1269                    set program strip
1270                    set destopt "-o $destopt"
1271                }
1272                default	{
1273                    perror "unrecognized PROG option $opts(PROG) in $file.d"
1274                    unresolved $testname
1275                    continue
1276                }
1277            }
1278
1279            set progopts1 $opts($program)
1280            eval set progopts \$[string toupper $program]FLAGS
1281            eval set binary \$[string toupper $program]
1282
1283            if { ![is_remote host] && [which $binary] == 0 } {
1284                untested $testname
1285                continue
1286            }
1287
1288            verbose "running $binary $progopts $progopts1" 3
1289            set cmd "$binary $progopts $progopts1 $objfile $destopt"
1290
1291            # Ensure consistent sorting of symbols
1292            if {[info exists env(LC_ALL)]} {
1293                set old_lc_all $env(LC_ALL)
1294            }
1295            set env(LC_ALL) "C"
1296            send_log "$cmd\n"
1297            set cmdret [remote_exec host [concat sh -c [list "$cmd 2>dump.tmp"]] "" "/dev/null"]
1298            set cmdret [lindex $cmdret 0]
1299            remote_upload host "dump.tmp"
1300            append comp_output [prune_warnings [file_contents "dump.tmp"]]
1301            remote_file host delete "dump.tmp"
1302            remote_file build delete "dump.tmp"
1303            if {[info exists old_lc_all]} {
1304                set env(LC_ALL) $old_lc_all
1305            } else {
1306                unset env(LC_ALL)
1307            }
1308            if { $destopt != "" } {
1309                set objfile ${copyfile}.o
1310            }
1311        }
1312
1313        set want_out(source) ""
1314        set want_out(terminal) 0
1315        if { $err_warn } {
1316            if { $opts(error) != "" || $opts(error_output) != "" } {
1317                set want_out(terminal) 1
1318            }
1319
1320            if { $opts(error) != "" || $opts(warning) != "" } {
1321                set want_out(source) "regex"
1322                if { $opts(error) != "" } {
1323                    set want_out(regex) $opts(error)
1324                } else {
1325                    set want_out(regex) $opts(warning)
1326                }
1327            } else {
1328                set want_out(source) "file"
1329                if { $opts(error_output) != "" } {
1330                    set want_out(file) $opts(error_output)
1331                } else {
1332                    set want_out(file) $opts(warning_output)
1333                }
1334            }
1335        }
1336
1337        regsub "\n$" $comp_output "" comp_output
1338        if { $cmdret != 0 || $comp_output != "" || $want_out(source) != "" } {
1339            set exitstat "succeeded"
1340            if { $cmdret != 0 } { set exitstat "failed" }
1341
1342            if { $want_out(source) == "regex" } {
1343                verbose -log "$exitstat with: <$comp_output>, expected: <$want_out(regex)>"
1344            } elseif { $want_out(source) == "file" } {
1345                verbose -log "$exitstat with: <$comp_output>, expected in file $want_out(file)"
1346                set_file_contents "tmpdir/ld.messages" "$comp_output"
1347            } else {
1348                verbose -log "$exitstat with: <$comp_output>, no expected output"
1349            }
1350
1351            if { (($want_out(source) == "") == ($comp_output == "")) \
1352                     && (($cmdret == 0) == ($want_out(terminal) == 0)) \
1353                     && ((($want_out(source) == "regex") \
1354                              && [regexp -- $want_out(regex) $comp_output]) \
1355                             || (($want_out(source) == "file") \
1356                                     && (![regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$want_out(file)"]))) } {
1357                # We have the expected output.
1358                if { $want_out(terminal) || $dumpprogram == "" } {
1359                    pass $testname
1360                    continue
1361                }
1362            } else {
1363                fail $testname
1364                continue
1365            }
1366        }
1367
1368        # We must not have expected failure if we get here.
1369        if { $opts(error) != "" } {
1370            fail $testname
1371            continue
1372        }
1373
1374        if { $opts(map) != "" } then {
1375            # Check the map file matches.
1376            set map_pattern_file $srcdir/$subdir/$opts(map)
1377            verbose -log "Compare '$mapfile' against '$map_pattern_file'"
1378            if { [regexp_diff $mapfile $map_pattern_file] } then {
1379                fail "$testname (map file check)"
1380            } else {
1381                pass "$testname (map file check)"
1382            }
1383
1384            if { $dumpprogram == "" } then {
1385                continue
1386            }
1387        }
1388
1389        set progopts1 $opts($dumpprogram)
1390        eval set progopts \$[string toupper $dumpprogram]FLAGS
1391        eval set binary \$[string toupper $dumpprogram]
1392
1393        if { ![is_remote host] && [which $binary] == 0 } {
1394            untested $testname
1395            continue
1396        }
1397
1398        # For objdump of gas output, automatically translate standard section names
1399        set sect_names ""
1400        if { !$run_ld && $dumpprogram == "objdump" \
1401                 && $opts(section_subst) != "no" \
1402                 && ![string match "*-b binary*" $progopts1] } {
1403            set sect_names [get_standard_section_names]
1404            if { $sect_names != ""} {
1405                regsub -- "\\.text" $progopts1 "[lindex $sect_names 0]" progopts1
1406                regsub -- "\\.data" $progopts1 "[lindex $sect_names 1]" progopts1
1407                regsub -- "\\.bss"  $progopts1 "[lindex $sect_names 2]" progopts1
1408            }
1409        }
1410
1411        if { $progopts1 == "" } { set $progopts1 "-r" }
1412        verbose "running $binary $progopts $progopts1" 3
1413
1414        set cmd "$binary $progopts $progopts1 $objfile > $dumpfile"
1415
1416        # Ensure consistent sorting of symbols
1417        if {[info exists env(LC_ALL)]} {
1418            set old_lc_all $env(LC_ALL)
1419        }
1420        set env(LC_ALL) "C"
1421        send_log "$cmd\n"
1422        set cmdret [remote_exec host [concat sh -c [list "$cmd 2>dump.tmp"]] "" "/dev/null"]
1423        set cmdret [lindex $cmdret 0]
1424        remote_upload host "dump.tmp"
1425        set comp_output [prune_warnings [file_contents "dump.tmp"]]
1426        remote_file host delete "dump.tmp"
1427        remote_file build delete "dump.tmp"
1428        if {[info exists old_lc_all]} {
1429            set env(LC_ALL) $old_lc_all
1430        } else {
1431            unset env(LC_ALL)
1432        }
1433        if { $cmdret != 0 || $comp_output != "" } {
1434            send_log "exited abnormally with $cmdret, output:$comp_output\n"
1435            fail $testname
1436            continue
1437        }
1438
1439        if { $verbose > 2 } then { verbose "output is [file_contents $dumpfile]" 3 }
1440
1441        # Create the substition list for objdump output.
1442        set regexp_subst ""
1443        if { $sect_names != "" } {
1444            set regexp_subst [list "\\\\?\\.text" [lindex $sect_names 0] \
1445                                  "\\\\?\\.data" [lindex $sect_names 1] \
1446                                  "\\\\?\\.bss" [lindex $sect_names 2] ]
1447        }
1448
1449        if { [regexp_diff $dumpfile "${dfile}" $regexp_subst] } then {
1450            fail $testname
1451            if { $verbose == 2 } then { verbose "output is [file_contents $dumpfile]" 2 }
1452            continue
1453        }
1454
1455        pass $testname
1456    }
1457}
1458
1459proc slurp_options { file } {
1460    # If options_regsub(foo) is set to {a b}, then the contents of a
1461    # "#foo:" line will have regsub -all applied to replace a with b.
1462    global options_regsub
1463
1464    if [catch { set f [open $file r] } x] {
1465	#perror "couldn't open `$file': $x"
1466	perror "$x"
1467	return -1
1468    }
1469    set opt_array {}
1470    # whitespace expression
1471    set ws  {[ 	]*}
1472    set nws {[^ 	]*}
1473    # whitespace is ignored anywhere except within the options list;
1474    # option names are alphanumeric plus underscore.
1475    set pat "^#${ws}(\[a-zA-Z0-9_\]*)$ws:${ws}(.*)$ws\$"
1476    while { [gets $f line] != -1 } {
1477	set line [string trim $line]
1478	# Whitespace here is space-tab.
1479	if [regexp $pat $line xxx opt_name opt_val] {
1480	    # match!
1481	    if [info exists options_regsub($opt_name)] {
1482		set subst $options_regsub($opt_name)
1483		regsub -all -- [lindex $subst 0] $opt_val [lindex $subst 1] \
1484		    opt_val
1485	    }
1486	    lappend opt_array [list $opt_name $opt_val]
1487	} elseif {![regexp "^#" $line ]} {
1488	    break
1489	}
1490    }
1491    close $f
1492    return $opt_array
1493}
1494
1495proc file_contents { filename } {
1496    set file [open $filename r]
1497    set contents [read $file]
1498    close $file
1499    return $contents
1500}
1501
1502proc set_file_contents { filename contents } {
1503    set file [open $filename w]
1504    puts $file "$contents"
1505    close $file
1506}
1507
1508# Look for big-endian or little-endian switches in the multlib
1509# options and translate these into a -EB or -EL switch.  Note
1510# we cannot rely upon proc process_multilib_options to do this
1511# for us because for some targets the compiler does not support
1512# -EB/-EL but it does support -mbig-endian/-mlittle-endian, and
1513# the site.exp file will include the switch "-mbig-endian"
1514# (rather than "big-endian") which is not detected by proc
1515# process_multilib_options.
1516#
1517proc big_or_little_endian {} {
1518
1519    if [board_info [target_info name] exists multilib_flags] {
1520	set tmp_flags " [board_info [target_info name] multilib_flags]"
1521
1522	foreach x $tmp_flags {
1523	    switch -glob $x {
1524		*big*endian -
1525		eb -
1526		EB -
1527		-eb -
1528		-EB -
1529		-mb -
1530		-meb {
1531		    set flags " -EB"
1532		    return $flags
1533		}
1534		*little*endian -
1535		el -
1536		EL -
1537		-el -
1538		-EL -
1539		-ml -
1540		-mel {
1541		    set flags " -EL"
1542		    return $flags
1543		}
1544	    }
1545	}
1546    }
1547
1548    set flags ""
1549    return $flags
1550}
1551
1552# Internal procedure: return the names of the standard sections
1553#
1554proc get_standard_section_names {} {
1555    if [istarget "rx-*-elf"] {
1556	return { "P" "D_1" "B_1" }
1557    }
1558    if { [istarget "alpha*-*-*vms*"] || [is_som_format] } {
1559	return { {\$CODE\$} {\$DATA\$} {\$BSS\$} }
1560    }
1561    return
1562}
1563