]>
Commit | Line | Data |
---|---|---|
c59e30ed NA |
1 | # Support routines for libctf testsuite. |
2 | # Copyright (C) 1994-2021 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 | ||
21 | proc load_common_lib { name } { | |
22 | global srcdir | |
23 | load_file $srcdir/../../binutils/testsuite/lib/$name | |
24 | } | |
25 | ||
26 | load_common_lib binutils-common.exp | |
27 | ||
28 | proc run_native_host_cmd { command } { | |
29 | global link_output | |
30 | global ld | |
31 | ||
32 | verbose -log "$command" | |
33 | set run_output "" | |
34 | try { | |
35 | set run_output [exec "sh" "-c" "$command" "2>@1"] | |
36 | set status 0 | |
37 | } trap CHILDSTATUS {results options} { | |
38 | set status [lindex [dict get $options -errorcode] 2] | |
39 | set run_output $results | |
40 | } | |
41 | regsub "\n$" $run_output "" run_output | |
42 | if { [lindex $status 0] != 0 && [string match "" $run_output] } then { | |
43 | append run_output "child process exited abnormally" | |
44 | } | |
45 | ||
46 | if [string match "" $run_output] then { | |
47 | return "" | |
48 | } | |
49 | ||
50 | verbose -log "$run_output" | |
51 | return "$run_output" | |
52 | } | |
53 | ||
54 | proc run_host_cmd { prog command } { | |
55 | global link_output | |
56 | global gcc_B_opt | |
57 | global gcc_ld_B_opt_tested | |
58 | global ld | |
59 | ||
60 | if { ![is_remote host] && [which "$prog"] == 0 } then { | |
61 | perror "$prog does not exist" | |
62 | return 0 | |
63 | } | |
64 | ||
65 | # If we are compiling with gcc, we want to add gcc_B_opt to flags. However, | |
66 | # if $prog already has -B options, which might be the case when running gcc | |
67 | # out of a build directory, we want our -B options to come first. | |
68 | set gccexe $prog | |
69 | set gccparm [string first " " $gccexe] | |
70 | set gccflags "" | |
71 | if { $gccparm > 0 } then { | |
72 | set gccflags [string range $gccexe $gccparm end] | |
73 | set gccexe [string range $gccexe 0 $gccparm] | |
74 | set prog $gccexe | |
75 | } | |
76 | set gccexe [string replace $gccexe 0 [string last "/" $gccexe] ""] | |
77 | if {[string match "*cc*" $gccexe] || [string match "*++*" $gccexe]} then { | |
78 | set gccflags "$gcc_B_opt $gccflags" | |
79 | if {![info exists gcc_ld_B_opt_tested]} { | |
80 | set gcc_ld_B_opt_tested 1 | |
81 | set ld_version_message [run_host_cmd "$ld" "--version"] | |
82 | set gcc_ld_version_message [run_host_cmd "$prog" "$gccflags -Wl,--version"] | |
83 | if {[string first $ld_version_message $gcc_ld_version_message] < 0} { | |
84 | perror "************************************************************************" | |
85 | perror "Your compiler driver ignores -B when choosing ld." | |
86 | perror "You will not be testing the new ld in many of the following tests." | |
87 | set gcc_ld_version [run_host_cmd "$prog" "$gccflags --print-prog-name=ld"] | |
88 | if {![string match "" $gcc_ld_version] && ![string match "ld" $gcc_ld_version]} { | |
89 | perror "It seems you will be testing $gcc_ld_version instead." | |
90 | } | |
91 | perror "************************************************************************" | |
92 | } | |
93 | } | |
94 | } | |
95 | ||
96 | verbose -log "$prog $gccflags $command" | |
97 | set status [remote_exec host [concat sh -c [list "$prog $gccflags $command 2>&1"]] "" "/dev/null" "libctf.tmp"] | |
98 | remote_upload host "libctf.tmp" | |
99 | set run_output [file_contents "libctf.tmp"] | |
100 | regsub "\n$" $run_output "" run_output | |
101 | if { [lindex $status 0] != 0 && [string match "" $run_output] } then { | |
102 | append run_output "child process exited abnormally" | |
103 | } | |
104 | remote_file build delete libctf.tmp | |
105 | remote_file host delete libctf.tmp | |
106 | ||
107 | if [string match "" $run_output] then { | |
108 | return "" | |
109 | } | |
110 | ||
111 | verbose -log "$run_output" | |
112 | return "$run_output" | |
113 | } | |
114 | ||
115 | proc run_host_cmd_yesno { prog command } { | |
116 | global exec_output | |
117 | global errcnt warncnt | |
118 | ||
119 | set exec_output [prune_warnings [run_host_cmd "$prog" "$command"]] | |
120 | # Ignore error and warning. | |
121 | set errcnt 0 | |
122 | set warncnt 0 | |
123 | if [string match "" $exec_output] then { | |
124 | return 1; | |
125 | } | |
126 | return 0; | |
127 | } | |
128 | ||
129 | # Return true if we can build a program with the compiler. | |
130 | # On some targets, CC might be defined, but libraries and startup | |
131 | # code might be missing or require special options that the ld test | |
132 | # harness doesn't know about. | |
133 | ||
134 | proc check_compiler_available { } { | |
135 | global compiler_available_saved | |
136 | global CC | |
137 | ||
138 | if {![info exists compiler_available_saved]} { | |
139 | if { [which $CC] == 0 } { | |
140 | set compiler_available_saved 0 | |
141 | return 0 | |
142 | } | |
143 | ||
144 | set flags "" | |
145 | if [board_info [target_info name] exists cflags] { | |
146 | append flags " [board_info [target_info name] cflags]" | |
147 | } | |
148 | if [board_info [target_info name] exists ldflags] { | |
149 | append flags " [board_info [target_info name] ldflags]" | |
150 | } | |
151 | ||
152 | set basename "tmpdir/compiler[pid]" | |
153 | set src ${basename}.c | |
154 | set output ${basename}.out | |
155 | set f [open $src "w"] | |
156 | puts $f "int main (void)" | |
157 | puts $f "{" | |
158 | puts $f " return 0; " | |
159 | puts $f "}" | |
160 | close $f | |
161 | if [is_remote host] { | |
162 | set src [remote_download host $src] | |
163 | } | |
164 | set compiler_available_saved [run_host_cmd_yesno "$CC" "$flags $src -o $output"] | |
165 | remote_file host delete $src | |
166 | remote_file host delete $output | |
167 | file delete $src | |
168 | } | |
169 | return $compiler_available_saved | |
170 | } | |
171 | ||
172 | # Compile and link a C source file for execution on the host. | |
173 | proc compile_link_one_host_cc { src output additional_args } { | |
174 | global CC_FOR_HOST | |
175 | global CFLAGS | |
176 | ||
177 | return [run_native_host_cmd "./libtool --quiet --tag=CC --mode=link $CC_FOR_HOST $CFLAGS $src -o $output $additional_args" ] | |
178 | } | |
179 | ||
180 | # Compile a C source file, with the specified additional_flags. | |
181 | proc compile_one_cc { src output additional_flags } { | |
182 | global CC | |
183 | global CFLAGS | |
184 | ||
185 | set flags "" | |
186 | if [board_info [target_info name] exists cflags] { | |
187 | append flags " [board_info [target_info name] cflags]" | |
188 | } | |
189 | if [board_info [target_info name] exists ldflags] { | |
190 | append flags " [board_info [target_info name] ldflags]" | |
191 | } | |
192 | ||
193 | if [is_remote host] { | |
194 | set src [remote_download host $src] | |
195 | } | |
196 | return [run_host_cmd "$CC" "$flags $CFLAGS $additional_flags $src -o $output"] | |
197 | } | |
198 | ||
199 | # run_lookup_test FILE | |
200 | # | |
201 | # Compile with the host compiler and link a .c file into a "lookup" binary, then | |
202 | # compile and optionally link together a bunch of .s or .c files with CTF info | |
203 | # and pass the name of the resulting binary to the "lookup" binary and check the | |
204 | # output. (If none is specified, the binary is expected to generate its own CTF | |
205 | # for testing purposes.) | |
206 | # | |
207 | # As with run_dump_test, this is all driven by a file (in this case, a .lk file) | |
208 | # beginning with zero or more option lines, which specify the names of the | |
209 | # lookup binary's source file, the source file(s) with CTF info to compile | |
210 | # together, and whether to link them. The optional lines have the syntax: | |
211 | # | |
212 | # # OPTION: VALUE | |
213 | # | |
214 | # OPTION is the name of some option, like "name" or "lookup", and | |
215 | # VALUE is OPTION's value. The valid options are described below. | |
216 | # Whitespace is ignored everywhere, except within VALUE. The option | |
217 | # list ends with the first line that doesn't match the above syntax. | |
218 | # However, a line within the options that begins with a #, but doesn't | |
219 | # have a recognizable option name followed by a colon, is considered a | |
220 | # comment and entirely ignored. | |
221 | # | |
222 | # The interesting options are: | |
223 | # | |
224 | # name: TEST-NAME | |
225 | # The name of this test, passed to DejaGNU's `pass' and `fail' | |
226 | # commands. If omitted, this defaults to FILE, the root of the | |
227 | # lookup .c file's name. | |
228 | # | |
229 | # lookup: SOURCE | |
230 | # Compile the file SOURCE.c. If omitted, the lookup source defaults | |
231 | # to FILE.c. | |
232 | # | |
233 | # source: SOURCE | |
234 | # Assemble the file SOURCE.c and pass it to the LOOKUP program. | |
235 | # | |
35a01a04 NA |
236 | # nonshared: |
237 | # If set, do not link with -shared. | |
238 | # | |
c59e30ed NA |
239 | # link: |
240 | # If set, link the SOURCE together even if only one file is specified. | |
241 | # | |
242 | # link_flags: | |
243 | # If set, extra flags to pass to the linker. | |
244 | # | |
245 | # xfail: GLOB|PROC ... | |
246 | # This test is expected to fail on a specified list of targets. | |
247 | # | |
248 | # Each option may occur at most once unless otherwise mentioned. | |
249 | # | |
250 | # After the option lines come regexp lines. run_lookup_test calls | |
251 | # regexp_diff to compare the output of the lookup program against the | |
252 | # regexps in FILE.d. | |
253 | # | |
254 | proc run_lookup_test { name } { | |
255 | global CC CFLAGS LIBS | |
256 | global copyfile env runtests srcdir subdir verbose | |
257 | ||
258 | if ![runtest_file_p $runtests $name] then { | |
259 | return | |
260 | } | |
261 | ||
262 | if [string match "*/*" $name] { | |
263 | set file $name | |
264 | set name [file tail $name] | |
265 | } else { | |
266 | set file "$srcdir/$subdir/$name" | |
267 | } | |
268 | ||
269 | set opt_array [slurp_options "${file}.lk"] | |
270 | if { $opt_array == -1 } { | |
271 | perror "error reading options from $file.lk" | |
272 | unresolved $subdir/$name | |
273 | return | |
274 | } | |
275 | set run_ld 0 | |
35a01a04 | 276 | set shared "-shared" |
c59e30ed NA |
277 | set opts(link) {} |
278 | set opts(link_flags) {} | |
35a01a04 | 279 | set opts(nonshared) {} |
c59e30ed NA |
280 | set opts(lookup) {} |
281 | set opts(name) {} | |
282 | set opts(source) {} | |
283 | set opts(xfail) {} | |
284 | ||
285 | foreach i $opt_array { | |
286 | set opt_name [lindex $i 0] | |
287 | set opt_val [lindex $i 1] | |
288 | if { $opt_name == "" } { | |
289 | set in_extra 1 | |
290 | continue | |
291 | } | |
292 | if ![info exists opts($opt_name)] { | |
293 | perror "unknown option $opt_name in file $file.lk" | |
294 | unresolved $subdir/$name | |
295 | return | |
296 | } | |
297 | ||
298 | set opts($opt_name) [concat $opts($opt_name) $opt_val] | |
299 | } | |
300 | ||
301 | if { [llength $opts(lookup)] == 0 } { | |
302 | set opts(lookup) "$file.c" | |
303 | } else { | |
304 | set opts(lookup) "[file dirname $file]/$opts(lookup)" | |
305 | } | |
306 | ||
307 | if { [llength $opts(name)] == 0 } { | |
308 | set opts(name) $opts(lookup) | |
309 | } | |
310 | ||
311 | if { [llength $opts(link)] != 0 | |
312 | || [llength $opts(source)] > 1 } { | |
313 | set run_ld 1 | |
314 | } | |
315 | ||
35a01a04 NA |
316 | if { [llength $opts(nonshared)] != 0 } { |
317 | set shared "" | |
318 | } | |
319 | ||
c59e30ed NA |
320 | set testname $opts(name) |
321 | if { $opts(name) == "" } { | |
322 | set testname "$subdir/$name" | |
323 | } | |
324 | ||
325 | # Compile and link the lookup program. | |
326 | set comp_output [compile_link_one_host_cc $opts(lookup) "tmpdir/lookup" "libctf.la"] | |
327 | ||
328 | if { $comp_output != ""} { | |
329 | send_log "compilation of lookup program $opts(lookup) failed with <$comp_output>" | |
330 | perror "compilation of lookup program $opts(lookup) failed" | |
331 | fail $testname | |
332 | return 0 | |
333 | } | |
334 | ||
335 | # Compile the inputs and posibly link them together. | |
336 | ||
337 | set lookup_output "" | |
338 | if { [llength $opts(source)] > 0 } { | |
339 | set lookup_flags "" | |
340 | if { $run_ld } { | |
341 | set lookup_output "tmpdir/out.so" | |
35a01a04 | 342 | set lookup_flags "-gt -fPIC $shared $opts(link_flags)" |
c59e30ed NA |
343 | } else { |
344 | set lookup_output "tmpdir/out.o" | |
345 | set lookup_flags "-gt -fPIC -c" | |
346 | } | |
347 | if [board_info [target_info name] exists cflags] { | |
348 | append lookup_flags " [board_info [target_info name] cflags]" | |
349 | } | |
350 | if [board_info [target_info name] exists ldflags] { | |
351 | append lookup_flags " [board_info [target_info name] ldflags]" | |
352 | } | |
353 | set src {} | |
354 | foreach sfile $opts(source) { | |
355 | if [is_remote host] { | |
356 | lappend src [remote_download host [file join [file dirname $file] $sfile]] | |
357 | } else { | |
358 | lappend src [file join [file dirname $file] $sfile] | |
359 | } | |
360 | } | |
361 | ||
362 | set comp_output [run_host_cmd "$CC" "$CFLAGS $lookup_flags [concat $src] -o $lookup_output"] | |
363 | ||
364 | if { $comp_output != ""} { | |
365 | send_log "compilation of CTF program [concat $src] failed with <$comp_output>" | |
366 | fail $testname | |
367 | return 0 | |
368 | } | |
369 | } | |
370 | ||
371 | # Time to setup xfailures. | |
372 | foreach targ $opts(xfail) { | |
373 | if [match_target $targ] { | |
374 | setup_xfail "*-*-*" | |
375 | break | |
376 | } | |
377 | } | |
378 | ||
379 | # Invoke the lookup program on the outputs. | |
380 | ||
381 | set results [run_host_cmd tmpdir/lookup $lookup_output] | |
382 | ||
383 | set f [open "tmpdir/lookup.out" "w"] | |
384 | puts $f $results | |
385 | close $f | |
386 | ||
387 | if { [regexp_diff "tmpdir/lookup.out" "${file}.lk"] } then { | |
388 | fail $testname | |
389 | if { $verbose == 2 } then { verbose "output is [file_contents tmpdir/lookup.out]" 2 } | |
390 | return 0 | |
391 | } | |
392 | ||
393 | pass $testname | |
394 | return 0 | |
395 | } | |
396 | ||
397 | # Returns true if the target compiler supports -gt | |
398 | proc check_ctf_available { } { | |
399 | global ctf_available_saved | |
400 | ||
401 | if {![info exists ctf_available_saved]} { | |
402 | if { ![check_compiler_available] } { | |
403 | set ctf_available_saved 0 | |
404 | } else { | |
405 | set basename "tmpdir/ctf_available[pid]" | |
406 | set src ${basename}.c | |
407 | set output ${basename}.o | |
408 | set f [open $src "w"] | |
409 | puts $f "int main() { return 0; }" | |
410 | close $f | |
70d3120f NA |
411 | set comp_output [compile_one_cc $src $output "-gt -c"] |
412 | if { $comp_output == ""} { | |
413 | set ctf_available_saved 1 | |
414 | } else { | |
415 | set ctf_available_saved 0 | |
416 | } | |
c59e30ed NA |
417 | remote_file host delete $src |
418 | remote_file host delete $output | |
419 | file delete $src | |
420 | } | |
421 | } | |
422 | return $ctf_available_saved | |
423 | } |