1# Support routines for libctf testsuite. 2# Copyright (C) 1994-2024 Free Software Foundation, Inc. 3# 4# This file is part of the GNU Binutils. 5# 6# This file is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 3 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program; if not, write to the Free Software 18# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19# MA 02110-1301, USA. 20 21load_file $srcdir/../../ld/testsuite/lib/ld-lib.exp 22 23proc run_native_host_cmd { command } { 24 global link_output 25 global ld 26 27 verbose -log "$command" 28 set run_output "" 29 try { 30 set run_output [exec "sh" "-c" "$command" "2>@1"] 31 set status 0 32 } trap CHILDSTATUS {results options} { 33 set status [lindex [dict get $options -errorcode] 2] 34 set run_output $results 35 } 36 regsub "\n$" $run_output "" run_output 37 if { [lindex $status 0] != 0 && [string match "" $run_output] } then { 38 append run_output "child process exited abnormally" 39 } 40 41 if [string match "" $run_output] then { 42 return "" 43 } 44 45 verbose -log "$run_output" 46 return "$run_output" 47} 48 49# Compile and link a C source file for execution on the host. 50proc compile_link_one_host_cc { src output additional_args } { 51 global CC 52 global CFLAGS 53 54 return [run_native_host_cmd "./libtool --quiet --tag=CC --mode=link $CC $CFLAGS $src -o $output $additional_args" ] 55} 56 57# run_lookup_test FILE 58# 59# Compile with the host compiler and link a .c file into a "lookup" binary, then 60# compile and optionally link together a bunch of .s or .c files with CTF info 61# and pass the name of the resulting binary to the "lookup" binary and check the 62# output. (If none is specified, the binary is expected to generate its own CTF 63# for testing purposes.) 64# 65# As with run_dump_test, this is all driven by a file (in this case, a .lk file) 66# beginning with zero or more option lines, which specify the names of the 67# lookup binary's source file, the source file(s) with CTF info to compile 68# together, and whether to link them. The optional lines have the syntax: 69# 70# # OPTION: VALUE 71# 72# OPTION is the name of some option, like "name" or "lookup", and 73# VALUE is OPTION's value. The valid options are described below. 74# Whitespace is ignored everywhere, except within VALUE. The option 75# list ends with the first line that doesn't match the above syntax. 76# However, a line within the options that begins with a #, but doesn't 77# have a recognizable option name followed by a colon, is considered a 78# comment and entirely ignored. 79# 80# The interesting options are: 81# 82# name: TEST-NAME 83# The name of this test, passed to DejaGNU's `pass' and `fail' 84# commands. If omitted, this defaults to FILE, the root of the 85# lookup .c file's name. 86# 87# lookup: SOURCE 88# Compile the file SOURCE.c. If omitted, the lookup source defaults 89# to FILE.c. 90# 91# source: SOURCE 92# Assemble the file SOURCE.c and pass it to the LOOKUP program. 93# 94# nonshared: 95# If set, do not link with -shared. 96# 97# link: 98# If set, link the SOURCE together even if only one file is specified. 99# 100# link_flags: 101# If set, extra flags to pass to the linker. 102# 103# lookup_link: 104# If set, extra libraries to link the lookup program with. 105# 106# xfail: GLOB|PROC ... 107# This test is expected to fail on a specified list of targets. 108# 109# no_cross: 110# If set, do not run this test when host != target. 111# 112# host: 113# If set, only run this test on hosts matching the given glob. 114# 115# wrapper: 116# Wrap invocations of LOOKUP in this command. (Useful for valgrind 117# invocations, etc.) 118# 119# Each option may occur at most once unless otherwise mentioned. 120# 121# After the option lines come regexp lines. run_lookup_test calls 122# regexp_diff to compare the output of the lookup program against the 123# regexps in FILE.d. 124# 125proc run_lookup_test { name } { 126 global CC_FOR_TARGET CFLAGS_FOR_TARGET LIBS TEST_CROSS 127 global copyfile env runtests srcdir subdir verbose 128 129 if ![runtest_file_p $runtests $name] then { 130 return 131 } 132 133 if [string match "*/*" $name] { 134 set file $name 135 set name [file tail $name] 136 } else { 137 set file "$srcdir/$subdir/$name" 138 } 139 140 set opt_array [slurp_options "${file}.lk"] 141 if { $opt_array == -1 } { 142 perror "error reading options from $file.lk" 143 unresolved $subdir/$name 144 return 145 } 146 set run_ld 0 147 set shared "-shared" 148 set opts(link) {} 149 set opts(link_flags) {} 150 set opts(lookup_link) {} 151 set opts(nonshared) {} 152 set opts(lookup) {} 153 set opts(name) {} 154 set opts(source) {} 155 set opts(xfail) {} 156 set opts(no_cross) {} 157 set opts(host) {} 158 set opts(wrapper) {} 159 160 foreach i $opt_array { 161 set opt_name [lindex $i 0] 162 set opt_val [lindex $i 1] 163 if { $opt_name == "" } { 164 set in_extra 1 165 continue 166 } 167 if ![info exists opts($opt_name)] { 168 perror "unknown option $opt_name in file $file.lk" 169 unresolved $subdir/$name 170 return 171 } 172 173 set opts($opt_name) [concat $opts($opt_name) $opt_val] 174 } 175 176 if { [llength $opts(no_cross)] != 0 177 && "$TEST_CROSS" eq "yes" } { 178 untested "$subdir/$name not tested when cross-compiling" 179 return 180 } 181 182 if { [llength $opts(host)] != 0 && ![ishost $opts(host)] } { 183 untested "$subdir/$name only runs on $opts(host)" 184 return 185 } 186 187 if { [llength $opts(lookup)] == 0 } { 188 set opts(lookup) "$file.c" 189 } else { 190 set opts(lookup) "[file dirname $file]/$opts(lookup)" 191 } 192 193 if { [llength $opts(name)] == 0 } { 194 set opts(name) $opts(lookup) 195 } 196 197 if { [llength $opts(link)] != 0 198 || [llength $opts(source)] > 1 } { 199 set run_ld 1 200 } 201 202 if { [llength $opts(nonshared)] != 0 } { 203 set shared "" 204 } 205 206 set testname $opts(name) 207 if { $opts(name) == "" } { 208 set testname "$subdir/$name" 209 } 210 211 # Compile and link the lookup program. 212 set comp_output [prune_warnings [compile_link_one_host_cc $opts(lookup) "tmpdir/lookup" "libctf.la $opts(lookup_link)"]] 213 214 if { $comp_output != ""} { 215 send_log "compilation of lookup program $opts(lookup) failed with <$comp_output>" 216 perror "compilation of lookup program $opts(lookup) failed" 217 fail $testname 218 return 0 219 } 220 221 # Compile the inputs and posibly link them together. 222 223 set lookup_output "" 224 if { [llength $opts(source)] > 0 } { 225 set lookup_flags "" 226 if { $run_ld } { 227 set lookup_output "tmpdir/out.so" 228 set lookup_flags "-gctf -fPIC $shared $opts(link_flags)" 229 } else { 230 set lookup_output "tmpdir/out.o" 231 set lookup_flags "-gctf -fPIC -c" 232 } 233 if [board_info [target_info name] exists cflags] { 234 append lookup_flags " [board_info [target_info name] cflags]" 235 } 236 if [board_info [target_info name] exists ldflags] { 237 append lookup_flags " [board_info [target_info name] ldflags]" 238 } 239 set src {} 240 foreach sfile $opts(source) { 241 if [is_remote host] { 242 lappend src [remote_download host [file join [file dirname $file] $sfile]] 243 } else { 244 lappend src [file join [file dirname $file] $sfile] 245 } 246 } 247 248 set comp_output [prune_warnings [run_host_cmd "$CC_FOR_TARGET" "$CFLAGS_FOR_TARGET $lookup_flags [concat $src] -o $lookup_output"]] 249 250 if { $comp_output != ""} { 251 send_log "compilation of CTF program [concat $src] failed with <$comp_output>" 252 fail $testname 253 return 0 254 } 255 } 256 257 # Time to setup xfailures. 258 foreach targ $opts(xfail) { 259 if [match_target $targ] { 260 setup_xfail "*-*-*" 261 break 262 } 263 } 264 265 # Invoke the lookup program on the outputs, possibly through the wrapper. 266 267 if { [llength $opts(wrapper)] == 0 } { 268 set results [run_host_cmd tmpdir/lookup $lookup_output] 269 } else { 270 set results [run_host_cmd "$opts(wrapper) tmpdir/lookup" $lookup_output] 271 } 272 273 set f [open "tmpdir/lookup.out" "w"] 274 puts $f $results 275 close $f 276 277 if { [regexp_diff "tmpdir/lookup.out" "${file}.lk"] } then { 278 fail $testname 279 if { $verbose == 2 } then { verbose "output is [file_contents tmpdir/lookup.out]" 2 } 280 return 0 281 } 282 283 pass $testname 284 return 0 285} 286