| # Support routines for libctf testsuite. |
| # Copyright (C) 1994-2021 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. |
| |
| load_file $srcdir/../../ld/testsuite/lib/ld-lib.exp |
| |
| proc run_native_host_cmd { command } { |
| global link_output |
| global ld |
| |
| verbose -log "$command" |
| set run_output "" |
| try { |
| set run_output [exec "sh" "-c" "$command" "2>@1"] |
| set status 0 |
| } trap CHILDSTATUS {results options} { |
| set status [lindex [dict get $options -errorcode] 2] |
| set run_output $results |
| } |
| regsub "\n$" $run_output "" run_output |
| if { [lindex $status 0] != 0 && [string match "" $run_output] } then { |
| append run_output "child process exited abnormally" |
| } |
| |
| if [string match "" $run_output] then { |
| return "" |
| } |
| |
| verbose -log "$run_output" |
| return "$run_output" |
| } |
| |
| # Compile and link a C source file for execution on the host. |
| proc compile_link_one_host_cc { src output additional_args } { |
| global CC |
| global CFLAGS |
| |
| return [run_native_host_cmd "./libtool --quiet --tag=CC --mode=link $CC $CFLAGS $src -o $output $additional_args" ] |
| } |
| |
| # run_lookup_test FILE |
| # |
| # Compile with the host compiler and link a .c file into a "lookup" binary, then |
| # compile and optionally link together a bunch of .s or .c files with CTF info |
| # and pass the name of the resulting binary to the "lookup" binary and check the |
| # output. (If none is specified, the binary is expected to generate its own CTF |
| # for testing purposes.) |
| # |
| # As with run_dump_test, this is all driven by a file (in this case, a .lk file) |
| # beginning with zero or more option lines, which specify the names of the |
| # lookup binary's source file, the source file(s) with CTF info to compile |
| # together, and whether to link them. The optional lines have the syntax: |
| # |
| # # OPTION: VALUE |
| # |
| # OPTION is the name of some option, like "name" or "lookup", and |
| # VALUE is OPTION's value. The valid options are described below. |
| # Whitespace is ignored everywhere, except within VALUE. The option |
| # list ends with the first line that doesn't match the above syntax. |
| # However, a line within the options that begins with a #, but doesn't |
| # have a recognizable option name followed by a colon, is considered a |
| # comment and entirely ignored. |
| # |
| # The interesting options are: |
| # |
| # name: TEST-NAME |
| # The name of this test, passed to DejaGNU's `pass' and `fail' |
| # commands. If omitted, this defaults to FILE, the root of the |
| # lookup .c file's name. |
| # |
| # lookup: SOURCE |
| # Compile the file SOURCE.c. If omitted, the lookup source defaults |
| # to FILE.c. |
| # |
| # source: SOURCE |
| # Assemble the file SOURCE.c and pass it to the LOOKUP program. |
| # |
| # nonshared: |
| # If set, do not link with -shared. |
| # |
| # link: |
| # If set, link the SOURCE together even if only one file is specified. |
| # |
| # link_flags: |
| # If set, extra flags to pass to the linker. |
| # |
| # xfail: GLOB|PROC ... |
| # This test is expected to fail on a specified list of targets. |
| # |
| # Each option may occur at most once unless otherwise mentioned. |
| # |
| # After the option lines come regexp lines. run_lookup_test calls |
| # regexp_diff to compare the output of the lookup program against the |
| # regexps in FILE.d. |
| # |
| proc run_lookup_test { name } { |
| global CC_FOR_TARGET CFLAGS_FOR_TARGET LIBS |
| global copyfile env runtests srcdir subdir verbose |
| |
| if ![runtest_file_p $runtests $name] then { |
| return |
| } |
| |
| if [string match "*/*" $name] { |
| set file $name |
| set name [file tail $name] |
| } else { |
| set file "$srcdir/$subdir/$name" |
| } |
| |
| set opt_array [slurp_options "${file}.lk"] |
| if { $opt_array == -1 } { |
| perror "error reading options from $file.lk" |
| unresolved $subdir/$name |
| return |
| } |
| set run_ld 0 |
| set shared "-shared" |
| set opts(link) {} |
| set opts(link_flags) {} |
| set opts(nonshared) {} |
| set opts(lookup) {} |
| set opts(name) {} |
| set opts(source) {} |
| set opts(xfail) {} |
| |
| foreach i $opt_array { |
| set opt_name [lindex $i 0] |
| set opt_val [lindex $i 1] |
| if { $opt_name == "" } { |
| set in_extra 1 |
| continue |
| } |
| if ![info exists opts($opt_name)] { |
| perror "unknown option $opt_name in file $file.lk" |
| unresolved $subdir/$name |
| return |
| } |
| |
| set opts($opt_name) [concat $opts($opt_name) $opt_val] |
| } |
| |
| if { [llength $opts(lookup)] == 0 } { |
| set opts(lookup) "$file.c" |
| } else { |
| set opts(lookup) "[file dirname $file]/$opts(lookup)" |
| } |
| |
| if { [llength $opts(name)] == 0 } { |
| set opts(name) $opts(lookup) |
| } |
| |
| if { [llength $opts(link)] != 0 |
| || [llength $opts(source)] > 1 } { |
| set run_ld 1 |
| } |
| |
| if { [llength $opts(nonshared)] != 0 } { |
| set shared "" |
| } |
| |
| set testname $opts(name) |
| if { $opts(name) == "" } { |
| set testname "$subdir/$name" |
| } |
| |
| # Compile and link the lookup program. |
| set comp_output [compile_link_one_host_cc $opts(lookup) "tmpdir/lookup" "libctf.la"] |
| |
| if { $comp_output != ""} { |
| send_log "compilation of lookup program $opts(lookup) failed with <$comp_output>" |
| perror "compilation of lookup program $opts(lookup) failed" |
| fail $testname |
| return 0 |
| } |
| |
| # Compile the inputs and posibly link them together. |
| |
| set lookup_output "" |
| if { [llength $opts(source)] > 0 } { |
| set lookup_flags "" |
| if { $run_ld } { |
| set lookup_output "tmpdir/out.so" |
| set lookup_flags "-gctf -fPIC $shared $opts(link_flags)" |
| } else { |
| set lookup_output "tmpdir/out.o" |
| set lookup_flags "-gctf -fPIC -c" |
| } |
| if [board_info [target_info name] exists cflags] { |
| append lookup_flags " [board_info [target_info name] cflags]" |
| } |
| if [board_info [target_info name] exists ldflags] { |
| append lookup_flags " [board_info [target_info name] ldflags]" |
| } |
| set src {} |
| foreach sfile $opts(source) { |
| if [is_remote host] { |
| lappend src [remote_download host [file join [file dirname $file] $sfile]] |
| } else { |
| lappend src [file join [file dirname $file] $sfile] |
| } |
| } |
| |
| set comp_output [run_host_cmd "$CC_FOR_TARGET" "$CFLAGS_FOR_TARGET $lookup_flags [concat $src] -o $lookup_output"] |
| |
| if { $comp_output != ""} { |
| send_log "compilation of CTF program [concat $src] failed with <$comp_output>" |
| fail $testname |
| return 0 |
| } |
| } |
| |
| # Time to setup xfailures. |
| foreach targ $opts(xfail) { |
| if [match_target $targ] { |
| setup_xfail "*-*-*" |
| break |
| } |
| } |
| |
| # Invoke the lookup program on the outputs. |
| |
| set results [run_host_cmd tmpdir/lookup $lookup_output] |
| |
| set f [open "tmpdir/lookup.out" "w"] |
| puts $f $results |
| close $f |
| |
| if { [regexp_diff "tmpdir/lookup.out" "${file}.lk"] } then { |
| fail $testname |
| if { $verbose == 2 } then { verbose "output is [file_contents tmpdir/lookup.out]" 2 } |
| return 0 |
| } |
| |
| pass $testname |
| return 0 |
| } |