# Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-# 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+# 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# This file was written by Ken Raeburn (raeburn@cygnus.com).
+proc load_common_lib { name } {
+ global srcdir
+ load_file $srcdir/../../binutils/testsuite/lib/$name
+}
+
+load_common_lib binutils-common.exp
+
proc gas_version {} {
global AS
if [is_remote host] then {
return [list $comp_output ""]
}
+proc gas_run_stdin { prog as_opts redir } {
+ global AS
+ global ASFLAGS
+ global comp_output
+ global srcdir
+ global subdir
+ global host_triplet
+
+ set status [gas_host_run "$AS $ASFLAGS $as_opts < $srcdir/$subdir/$prog" "$redir"]
+ set comp_output [lindex $status 1]
+ if { [lindex $status 0] != 0 && [regexp "2>.*" $redir] } then {
+ append comp_output "child process exited abnormally"
+ }
+ set comp_output [prune_warnings $comp_output]
+ verbose "output was $comp_output"
+ return [list $comp_output ""]
+}
+
proc all_ones { args } {
foreach x $args { if [expr $x!=1] { return 0 } }
return 1
global comp_output
gas_run $file $as_opts ">/dev/null"
- if ![string match "" $comp_output] then {
- send_log "$comp_output\n"
- verbose "$comp_output" 3
- }
- if [string match "" $comp_output] then {
- fail "$testname"
- } else {
+ send_log "$comp_output\n"
+ verbose "$comp_output" 3
+ if { ![string match "" $comp_output]
+ && ![string match "*Assertion failure*" $comp_output]
+ && ![string match "*Internal error*" $comp_output] } then {
pass "$testname"
+ } else {
+ fail "$testname"
}
}
return
}
+# Internal procedure: return the names of the standard sections
#
-# is_elf_format
-# true if the object format is known to be ELF
-#
-proc is_elf_format {} {
- if { ![istarget *-*-sysv4*] \
- && ![istarget *-*-unixware*] \
- && ![istarget *-*-elf*] \
- && ![istarget *-*-eabi*] \
- && ![istarget hppa*64*-*-hpux*] \
- && ![istarget *-*-linux*] \
- && ![istarget frv-*-uclinux*] \
- && ![istarget *-*-irix5*] \
- && ![istarget *-*-irix6*] \
- && ![istarget *-*-netbsd*] \
- && ![istarget *-*-openbsd*] \
- && ![istarget *-*-solaris2*] } {
- return 0
- }
-
- if { [istarget *-*-linux*aout*] \
- || [istarget *-*-linux*oldld*] } {
- return 0
- }
-
- if { ![istarget *-*-netbsdelf*] \
- && ([istarget *-*-netbsd*aout*] \
- || [istarget *-*-netbsdpe*] \
- || [istarget arm*-*-netbsd*] \
- || [istarget sparc-*-netbsd*] \
- || [istarget i*86-*-netbsd*] \
- || [istarget m68*-*-netbsd*] \
- || [istarget vax-*-netbsd*] \
- || [istarget ns32k-*-netbsd*]) } {
- return 0
- }
-
- if { [istarget arm-*-openbsd*] \
- || [istarget i386-*-openbsd\[0-2\].*] \
- || [istarget i386-*-openbsd3.\[0-3\]] \
- || [istarget m68*-*-openbsd*] \
- || [istarget ns32k-*-openbsd*] \
- || [istarget sparc-*-openbsd\[0-2\].*] \
- || [istarget sparc-*-openbsd3.\[0-1\]] \
- || [istarget vax-*-openbsd*] } {
- return 0
- }
-
- return 1
-}
-
-# True if the object format is known to be PE COFF.
-#
-proc is_pecoff_format {} {
- if { ![istarget *-*-mingw*] \
- && ![istarget *-*-cygwin*] \
- && ![istarget *-*-pe*] } {
- return 0
+proc get_standard_section_names {} {
+ if [istarget "rx-*-*"] {
+ return { "P" "D_1" "B_1" }
}
-
- return 1
+ return
}
# run_dump_tests TESTCASES EXTRA_OPTIONS
# as: FLAGS
# When assembling FILE.s, pass FLAGS to the assembler.
#
+# addr2line: FLAGS
# nm: FLAGS
# objcopy: FLAGS
# objdump: FLAGS
# FLAGS, in addition to the .o file name. Note that they are run
# with LC_ALL=C in the environment to give consistent sorting
# of symbols. If no FLAGS are needed then use:
-# PROG: [nm objcopy objdump readelf]
+# PROG: [nm objcopy objdump readelf addr2line]
# instead.
+# Note: for objdump, we automatically replaces the standard section
+# names (.text, .data and .bss) by target ones if any (eg. rx-elf
+# uses "P" instead of .text). The substition is done for both
+# the objdump options (eg: "-j .text" is replaced by "-j P") and the
+# reference file.
#
# source: SOURCE
# Assemble the file SOURCE.s. If omitted, this defaults to FILE.s.
# This is useful if several .d files want to share a .s file.
#
+# dump: DUMP
+# Match against DUMP.d. If omitted, this defaults to FILE.d. This
+# is useful if several .d files differ by options only. Options are
+# always read from FILE.d.
+#
# target: GLOBS...
# Run this test only on a specified list of targets. More precisely,
# each glob in the space-separated list is passed to "istarget"; if
# is expected to exit unsuccessfully (therefore PROG, objdump, nm,
# and objcopy have no meaning and should not be supplied).
#
+# section-subst: no
+# Means that the section substitution for objdump is disabled.
+#
# Each option may occur at most once.
#
# After the option lines come regexp lines. `run_dump_test' calls
# `regexp_diff' to compare the output of the dumping tool against the
-# regexps in FILE.d. `regexp_diff' is defined later in this file; see
-# further comments there.
+# regexps in FILE.d. `regexp_diff' is defined in binutils-common.exp;
+# see further comments there.
proc run_dump_test { name {extra_options {}} } {
global subdir srcdir
global OBJDUMP NM AS OBJCOPY READELF
global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS
+ global ADDR2LINE ADDR2LINEFLAGS
global host_triplet
global env
unresolved $subdir/$name
return
}
+ set opts(addr2line) {}
set opts(as) {}
set opts(objdump) {}
set opts(nm) {}
set opts(name) {}
set opts(PROG) {}
set opts(source) {}
+ set opts(dump) {}
set opts(stderr) {}
set opts(error) {}
set opts(error-output) {}
set opts(not-target) {}
set opts(skip) {}
set opts(not-skip) {}
+ set opts(section-subst) {}
foreach i $opt_array {
set opt_name [lindex $i 0]
if { $opts(error) == "" && $opts(error-output) == "" } {
if {$opts(PROG) != ""} {
switch -- $opts(PROG) {
+ addr2line { set program addr2line }
objdump { set program objdump }
nm { set program nm }
objcopy { set program objcopy }
}
} else {
# Guess which program to run, by seeing which option was specified.
- foreach p {objdump objcopy nm readelf} {
+ foreach p {objdump objcopy nm readelf addr2line} {
if {$opts($p) != ""} {
if {$program != ""} {
perror "ambiguous dump program in $file.d"
set sourcefile $srcdir/$subdir/$opts(source)
}
+ if { $opts(dump) == "" } {
+ set dumpfile ${file}.d
+ } else {
+ set dumpfile $srcdir/$subdir/$opts(dump)
+ }
+
set cmd "$AS $ASFLAGS $opts(as) -o dump.o $sourcefile"
send_log "$cmd\n"
set status [gas_host_run $cmd ""]
return
}
+ # For objdump, automatically translate standard section names to the targets one,
+ # if they are different.
+ set sect_names [get_standard_section_names]
+ if { $sect_names != "" && $program == "objdump" && $opts(section-subst) == ""} {
+ regsub -- "-j \\.text" $progopts1 "-j [lindex $sect_names 0]" progopts1
+ regsub -- "-j \\.data" $progopts1 "-j [lindex $sect_names 1]" progopts1
+ regsub -- "-j \\.bss" $progopts1 "-j [lindex $sect_names 2]" progopts1
+ }
+
if { $progopts1 == "" } { set $progopts1 "-r" }
verbose "running $binary $progopts $progopts1" 3
return
}
+ # Create the substition list only for objdump reference.
+ if { $sect_names != "" && $program == "objdump" } {
+ # Some testcases use ".text" while others use "\.text".
+ set regexp_subst [list "\\\\?\\.text" [lindex $sect_names 0] \
+ "\\\\?\\.data" [lindex $sect_names 1] \
+ "\\\\?\\.bss" [lindex $sect_names 2] ]
+ } else {
+ set regexp_subst ""
+ }
+
verbose_eval {[file_contents "dump.out"]} 3
- if { [regexp_diff "dump.out" "${file}.d"] } then {
+ if { [regexp_diff "dump.out" "${dumpfile}" $regexp_subst] } then {
fail $testname
verbose "output is [file_contents "dump.out"]" 2
return
set nws {[^ ]*}
# whitespace is ignored anywhere except within the options list;
# option names are alphabetic plus dash
- set pat "^#${ws}(\[a-zA-Z-\]*)$ws:${ws}(.*)$ws\$"
+ set pat "^#${ws}(\[a-zA-Z0-9-\]*)$ws:${ws}(.*)$ws\$"
while { [gets $f line] != -1 } {
set line [string trim $line]
# Whitespace here is space-tab.
eof { perror "eof" }
}
-# regexp_diff, based on simple_diff taken from ld test suite
-# compares two files line-by-line
-# file1 contains strings, file2 contains regexps and #-comments
-# blank lines are ignored in either file
-# returns non-zero if differences exist
-#
-proc regexp_diff { file_1 file_2 } {
-
- set eof -1
- set end_1 0
- set end_2 0
- set differences 0
- set diff_pass 0
-
- if [file exists $file_1] then {
- set file_a [open $file_1 r]
- } else {
- perror "$file_1 doesn't exist"
- return 1
- }
-
- if [file exists $file_2] then {
- set file_b [open $file_2 r]
- } else {
- perror "$file_2 doesn't exist"
- close $file_a
- return 1
- }
-
- verbose " Regexp-diff'ing: $file_1 $file_2" 2
-
- while { 1 } {
- set line_a ""
- set line_b ""
- while { [string length $line_a] == 0 } {
- if { [gets $file_a line_a] == $eof } {
- set end_1 1
- break
- }
- }
- while { [string length $line_b] == 0 || [string match "#*" $line_b] } {
- if [ string match "#pass" $line_b ] {
- set end_2 1
- set diff_pass 1
- break
- } elseif [ string match "#..." $line_b ] {
- if { [gets $file_b line_b] == $eof } {
- set end_2 1
- set diff_pass 1
- break
- }
- verbose "looking for \"^$line_b$\"" 3
- while { ![regexp "^$line_b$" "$line_a"] } {
- verbose "skipping \"$line_a\"" 3
- if { [gets $file_a line_a] == $eof } {
- set end_1 1
- break
- }
- }
- break
- }
- if { [gets $file_b line_b] == $eof } {
- set end_2 1
- break
- }
- }
-
- if { $diff_pass } {
- break
- } elseif { $end_1 && $end_2 } {
- break
- } elseif { $end_1 } {
- send_log "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1\n"
- verbose "extra regexps in $file_2 starting with \"^$line_b$\"\nEOF from $file_1" 3
- set differences 1
- break
- } elseif { $end_2 } {
- send_log "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n"
- verbose "extra lines in $file_1 starting with \"^$line_a$\"\nEOF from $file_2\n" 3
- set differences 1
- break
- } else {
- verbose "regexp \"^$line_b$\"\nline \"$line_a\"" 3
- if ![regexp "^$line_b$" "$line_a"] {
- send_log "regexp_diff match failure\n"
- send_log "regexp \"^$line_b$\"\nline \"$line_a\"\n"
- verbose "regexp_diff match failure\n" 3
- set differences 1
- }
- }
- }
-
- if { $differences == 0 && !$diff_pass && [eof $file_a] != [eof $file_b] } {
- send_log "$file_1 and $file_2 are different lengths\n"
- verbose "$file_1 and $file_2 are different lengths" 3
- set differences 1
- }
-
- close $file_a
- close $file_b
-
- return $differences
-}
-
proc file_contents { filename } {
set file [open $filename r]
set contents [read $file]
}
pass $testname
}
+
+# run_list_test_stdin NAME (optional): OPTS TESTNAME
+#
+# Similar to run_list_test, but use stdin as input.
+
+proc run_list_test_stdin { name {opts {}} {testname {}} } {
+ global srcdir subdir
+ if { [string length $testname] == 0 } then {
+ set testname "[file tail $subdir] $name"
+ }
+ set file $srcdir/$subdir/$name
+ gas_run_stdin ${name}.s $opts ">&dump.out"
+ if { [regexp_diff "dump.out" "${file}.l"] } then {
+ fail $testname
+ verbose "output is [file_contents "dump.out"]" 2
+ return
+ }
+ pass $testname
+}