| # Copyright 1999, 2000, 2001, 2003, 2004, 2007 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 |
| # 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. |
| |
| # Please email any bugs, comments, and/or additions to this file to: |
| # bug-dejagnu@prep.ai.mit.edu |
| |
| # Written by Nick Clifton <nickc@cygnus.com> |
| # Based on scripts written by Ian Lance Taylor <ian@cygnus.com> |
| # and Ken Raeburn <raeburn@cygnus.com>. |
| |
| # Exclude non-ELF targets. |
| if ![is_elf_format] { |
| verbose "$READELF is only intended for ELF targets" 2 |
| return |
| } |
| |
| # First some helpful procedures, then the tests themselves |
| |
| # Return the contents of the filename given |
| proc file_contents { filename } { |
| set file [open $filename r] |
| set contents [read $file] |
| close $file |
| return $contents |
| } |
| |
| # Find out the size by reading the output of the EI_CLASS field. |
| # Similar to the test for readelf -h, but we're just looking for the |
| # EI_CLASS line here. |
| proc readelf_find_size { binary_file } { |
| global READELF |
| global READELFFLAGS |
| global readelf_size |
| |
| set readelf_size "" |
| set testname "finding out ELF size with readelf -h" |
| set got [remote_exec host "$READELF $READELFFLAGS -h $binary_file" "" "/dev/null" "readelf.out"] |
| if [is_remote host] then { |
| remote_upload host "readelf.out" |
| } |
| |
| if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]]} then { |
| send_log $got |
| fail $testname |
| return |
| } |
| |
| if { ! [regexp "\n\[ \]*Class:\[ \]*ELF(\[0-9\]+)\n" \ |
| [file_contents readelf.out] nil readelf_size] } { |
| verbose -log "EI_CLASS field not found in output" |
| verbose -log "output is \n[file_contents readelf.out]" |
| fail $testname |
| return |
| } else { |
| verbose -log "ELF size is $readelf_size" |
| } |
| |
| pass $testname |
| } |
| |
| # Run an individual readelf test. |
| # Basically readelf is run on the binary_file with the given options. |
| # Readelf's output is captured and then compared against the contents |
| # of the regexp_file-readelf_size if it exists, else regexp_file. |
| |
| proc readelf_test { options binary_file regexp_file xfails } { |
| |
| global READELF |
| global READELFFLAGS |
| global readelf_size |
| global srcdir |
| global subdir |
| |
| send_log "exec $READELF $READELFFLAGS $options $binary_file > readelf.out\n" |
| set got [remote_exec host "$READELF $READELFFLAGS $options $binary_file" "" "/dev/null" "readelf.out"] |
| |
| foreach xfail $xfails { |
| setup_xfail $xfail |
| } |
| |
| if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then { |
| fail "readelf $options (reason: unexpected output)" |
| send_log $got |
| send_log "\n" |
| return |
| } |
| |
| set target_machine "" |
| if [istarget "mips*-*-*"] then { |
| if { [istarget "mips*-*-*linux*"] || [istarget "mips*-sde-elf*"] } then { |
| set target_machine tmips |
| } else { |
| set target_machine mips |
| } |
| } |
| |
| if { $target_machine != "" && [file exists $srcdir/$subdir/$regexp_file-$readelf_size-$target_machine] } then { |
| set regexp_file $regexp_file-$readelf_size-$target_machine |
| } elseif { $target_machine != "" && [file exists $srcdir/$subdir/$regexp_file-$target_machine] } then { |
| set regexp_file $regexp_file-$target_machine |
| } elseif { [file exists $srcdir/$subdir/$regexp_file-$readelf_size] } then { |
| set regexp_file $regexp_file-$readelf_size |
| } |
| |
| if { [regexp_diff readelf.out $srcdir/$subdir/$regexp_file] } then { |
| fail "readelf $options" |
| verbose "output is \n[file_contents readelf.out]" 2 |
| return |
| } |
| |
| pass "readelf $options" |
| } |
| |
| # Simple proc to skip certain expected warning messages. |
| |
| proc prune_readelf_wi_warnings { text } { |
| regsub -all "(^|\n)(.*Skipping unexpected symbol type.*)" $text "\\1" text |
| return $text |
| } |
| |
| # Testing the "readelf -wi" option is difficult because there |
| # is no guaranteed order to the output, and because some ports |
| # will use indirect string references, whilst others will use |
| # direct references. So instead of having an expected output |
| # file, like the other readelf tests, we grep for strings that |
| # really ought to be there. |
| |
| proc readelf_wi_test {} { |
| global READELF |
| global READELFFLAGS |
| global srcdir |
| global subdir |
| |
| # Compile the second test file. |
| if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } { |
| verbose "Unable to compile test file." |
| untested "readelf -wi" |
| return |
| } |
| |
| # Download it. |
| set tempfile [remote_download host tmpdir/testprog.o] |
| |
| # Run "readelf -wi" on it. |
| set got [remote_exec host "$READELF $READELFFLAGS -wi $tempfile" "" "/dev/null" "readelf.out"] |
| |
| # Upload the results. |
| set output [remote_upload host readelf.out] |
| |
| file_on_host delete $tempfile |
| |
| # Strip any superflous warnings. |
| set got [prune_readelf_wi_warnings [lindex $got 1]] |
| |
| if ![string match "" $got] then { |
| fail "readelf $READELFFLAGS -wi (reason: unexpected output)" |
| send_log $got |
| send_log "\n" |
| return |
| } |
| |
| if ![file size $output] then { |
| # If the output file is empty, then this target does not |
| # generate dwarf2 output. This is not a failure. |
| verbose "No output from 'readelf -wi'" |
| untested "readelf -wi" |
| return |
| } |
| |
| # Search for strings that should be in the output. |
| set sought { |
| ".*DW_TAG_compile_unit.*" |
| ".*DW_TAG_subprogram.*" |
| ".*DW_TAG_base_type.*" |
| ".*DW_AT_producer.*(GNU C|indirect string).*" |
| ".*DW_AT_language.*ANSI C.*" |
| ".*DW_AT_name.*(testprog.c|indirect string).*" |
| ".*DW_AT_name.*fn.*" |
| ".*DW_AT_name.*(main|indirect string).*" |
| ".*\(DW_OP_addr: 0\).*" |
| } |
| |
| foreach looked_for $sought { |
| set lines [grep $output $looked_for] |
| if ![llength $lines] then { |
| fail "readelf -wi: missing: $looked_for" |
| send_log readelf.out |
| return |
| } |
| } |
| |
| file_on_host delete $output |
| |
| # All done. |
| pass "readelf -wi" |
| } |
| |
| |
| # Test readelf's dumping abilities. |
| |
| proc readelf_dump_test {} { |
| global READELF |
| global READELFFLAGS |
| global srcdir |
| global subdir |
| |
| # Assemble the dump test file. |
| if {![binutils_assemble $srcdir/$subdir/dumptest.s tmpdir/dumptest.o]} then { |
| unresolved "readelf -p: failed to assemble dump test file" |
| return |
| } |
| # Download it. |
| set tempfile [remote_download host tmpdir/dumptest.o] |
| |
| # Run "readelf -p.data" on it. |
| set got [remote_exec host "$READELF $READELFFLAGS -p.data $tempfile" "" "/dev/null" "readelf.out"] |
| set got [lindex $got 1] |
| |
| # Upload the results. |
| set output [remote_upload host readelf.out] |
| |
| # Check for something going wrong. |
| if ![string match "" $got] then { |
| fail "readelf -p: unexpected output" |
| send_log $got |
| send_log "\n" |
| return |
| } |
| |
| # Search for strings that should be in the output. |
| set sought { |
| ".*test_string.*" |
| } |
| |
| foreach looked_for $sought { |
| set lines [grep $output $looked_for] |
| if ![llength $lines] then { |
| fail "readelf -p: missing: $looked_for" |
| send_log readelf.out |
| return |
| } |
| } |
| |
| file_on_host delete $tempfile |
| file_on_host delete $output |
| |
| # All done. |
| pass "readelf -p" |
| |
| # XXX FIXME: Add test of readelf -x here |
| } |
| |
| if ![is_remote host] { |
| if {[which $READELF] == 0} then { |
| perror "$READELF does not exist" |
| return |
| } |
| } |
| |
| send_user "Version [binutil_version $READELF]" |
| |
| # Assemble the test file. |
| if {![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o]} then { |
| perror "could not assemble test file" |
| unresolved "readelf - failed to assemble" |
| return |
| } |
| |
| if ![is_remote host] { |
| set tempfile tmpdir/bintest.o |
| } else { |
| set tempfile [remote_download host tmpdir/bintest.o] |
| } |
| |
| # First, determine the size, so specific output matchers can be used. |
| readelf_find_size $tempfile |
| |
| # Run the tests. |
| readelf_test -h $tempfile readelf.h {} |
| readelf_test -S $tempfile readelf.s {} |
| readelf_test -s $tempfile readelf.ss {} |
| readelf_test -r $tempfile readelf.r {} |
| |
| readelf_wi_test |
| |
| readelf_dump_test |