# Copyright 1993, 1994, 1995, 1996, 1997, 2000, 2001, 2003, 2004, 2006, 2007, # 2009, 2010 Free Software Foundation, Inc. # # This file is part of the GNU Binutils. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, # MA 02110-1301, USA. # True if the object format is known to be ELF. # proc is_elf_format {} { if { ![istarget *-*-sysv4*] && ![istarget *-*-unixware*] && ![istarget *-*-elf*] && ![istarget *-*-eabi*] && ![istarget *-*-rtems*] && ![istarget hppa*64*-*-hpux*] && ![istarget ia64-*-hpux*] && ![istarget *-*-linux*] && ![istarget *-*-gnu*] && ![istarget frv-*-uclinux*] && ![istarget bfin-*-uclinux] && ![istarget sh*-*-uclinux*] && ![istarget *-*-irix5*] && ![istarget *-*-irix6*] && ![istarget *-*-netbsd*] && ![istarget *-*-openbsd*] && ![istarget *-*-solaris2*] } { return 0 } if { [istarget *-*-linux*aout*] || [istarget *-*-linux*oldld*] || [istarget h8500-*-rtems*] || [istarget i960-*-rtems*] || [istarget *-*-rtemscoff*] } { 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-2\]] || [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 a.out. # proc is_aout_format {} { if { [istarget *-*-netbsdelf] || [istarget sparc64-*-netbsd*] || [istarget sparc64-*-openbsd*] } { return 0 } if { [istarget *-*-*\[ab\]out*] || [istarget *-*-linux*oldld*] || [istarget *-*-bsd*] || [istarget *-*-msdos*] || [istarget arm-*-netbsd*] || [istarget arm-*-openbsd*] || [istarget arm-*-riscix*] || [istarget i?86-*-freebsd\[12\]*] || [istarget i?86-*-netbsd*] || [istarget i?86-*-openbsd\[0-2\]*] || [istarget i?86-*-openbsd3.\[0-2\]*] || [istarget i?86-*-vsta] || [istarget i?86-*-mach*] || [istarget m68*-*-netbsd*] || [istarget m68*-*-openbsd*] || [istarget ns32k-*-*] || [istarget pdp11-*-*] || [istarget sparc*-*-sunos4*] || [istarget sparc*-*-netbsd*] || [istarget sparc*-*-openbsd\[0-2\]*] || [istarget sparc*-*-openbsd3.\[0-1\]*] || [istarget sparc*-fujitsu-none] || [istarget vax-dec-ultrix*] || [istarget vax-*-netbsd] } { return 1 } return 0 } # True if the object format is known to be PE COFF. # proc is_pecoff_format {} { if { ![istarget *-*-mingw*] && ![istarget *-*-cygwin*] && ![istarget *-*-cegcc*] && ![istarget *-*-pe*] } { return 0 } return 1 } # True if the object format is known to be 64-bit ELF. # proc is_elf64 { binary_file } { global READELF global READELFFLAGS set readelf_size "" catch "exec $READELF $READELFFLAGS -h $binary_file > readelf.out" got if ![string match "" $got] then { return 0 } if { ![regexp "\n\[ \]*Class:\[ \]*ELF(\[0-9\]+)\n" \ [file_contents readelf.out] nil readelf_size] } { return 0 } if { $readelf_size == "64" } { return 1 } return 0 } # Compare two files line-by-line. FILE_1 is the actual output and FILE_2 # is the expected output. Ignore blank lines in either file. # # FILE_2 is a series of regexps, comments and # directives. The directives # are: # # #pass # Treat the test as a PASS if everything up till this point has # matched. Ignore any remaining lines in either FILE_1 or FILE_2. # # #failif # Reverse the sense of the test: expect differences to exist. # # #... # REGEXP # Skip all lines in FILE_1 until the first that matches REGEXP. # # Other # lines are comments. Regexp lines starting with the `!' character # specify inverse matching (use `\!' for literal matching against a leading # `!'). Skip empty lines in both files. # # The first optional argument is a list of regexp substitutions of the form: # # EXP1 SUBSPEC1 EXP2 SUBSPEC2 ... # # This tells the function to apply each regexp substitution EXPi->SUBSPECi # in order to every line of FILE_2. # # Return nonzero if differences exist. proc regexp_diff { file_1 file_2 args } { set eof -1 set end_1 0 set end_2 0 set differences 0 set diff_pass 0 set fail_if_match 0 set ref_subst "" if { [llength $args] > 0 } { set ref_subst [lindex $args 0] } if { [llength $args] > 1 } { perror "Too many arguments to regexp_diff" return 1 } 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 } { # Ignore blank line in FILE_1. 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 "#failif" $line_b] } { send_log "fail if no difference\n" verbose "fail if no difference" 3 set fail_if_match 1 } elseif { [string match "#..." $line_b] } { if { [gets $file_b line_b] == $eof } { set end_2 1 set diff_pass 1 break } set negated [expr { [string index $line_b 0] == "!" }] set line_bx [string range $line_b $negated end] set n [expr { $negated ? "! " : "" }] # Substitute on the reference. foreach {name value} $ref_subst { regsub -- $name $line_bx $value line_bx } verbose "looking for $n\"^$line_bx$\"" 3 while { [expr [regexp "^$line_bx$" "$line_a"] == $negated] } { 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 { set negated [expr { [string index $line_b 0] == "!" }] set line_bx [string range $line_b $negated end] set n [expr { $negated ? "! " : "" }] set s [expr { $negated ? " " : "" }] # Substitute on the reference. foreach {name value} $ref_subst { regsub -- $name $line_bx $value line_bx } verbose "regexp $n\"^$line_bx$\"\nline \"$line_a\"" 3 if { [expr [regexp "^$line_bx$" "$line_a"] == $negated] } { send_log "regexp_diff match failure\n" send_log "regexp $n\"^$line_bx$\"\nline $s\"$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 } if { $fail_if_match } { if { $differences == 0 } { set differences 1 } else { set differences 0 } } close $file_a close $file_b return $differences }