1# Support routines for LD testsuite. 2# Copyright (C) 1994-2014 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 21proc load_common_lib { name } { 22 global srcdir 23 load_file $srcdir/../../binutils/testsuite/lib/$name 24} 25 26load_common_lib binutils-common.exp 27 28# Returns 1 if the gcc for the target is at least version MAJOR.MINOR 29# Returns 0 otherwise. 30# 31proc at_least_gcc_version { major minor } { 32 33 if {![info exists CC]} { 34 set CC [find_gcc] 35 } 36 if { $CC == "" } { 37 return 0 38 } 39 set state [remote_exec host $CC --version] 40 set tmp "[lindex $state 1]\n" 41 # Look for (eg) 4.6.1 in the version output. 42 set ver_re "\[^\\.0-9\]+(\[1-9\]\[0-9\]*)\\.(\[0-9\]+)(?:\\.\[0-9\]+)?" 43 regexp $ver_re $tmp fred maj min 44 verbose "gcc version: $tmp" 45 if { ![info exists maj] || ![info exists min] } then { 46 perror "can't decipher gcc version number, fix the framework!" 47 return 0 48 } 49 verbose "major gcc version is $maj, want at least $major" 50 if { $maj == $major } then { 51 verbose "minor gcc version is $min, want at least $minor" 52 return [expr $min >= $minor] 53 } else { 54 return [expr $maj > $major] 55 } 56} 57 58# Extract and print the version number of ld. 59# 60proc default_ld_version { ld } { 61 global host_triplet 62 63 if { ![is_remote host] && [which $ld] == 0 } then { 64 perror "$ld does not exist" 65 exit 1 66 } 67 68 remote_exec host "$ld --version" "" "/dev/null" "ld.version" 69 remote_upload host "ld.version" 70 set tmp [prune_warnings [file_contents "ld.version"]] 71 remote_file build delete "ld.version" 72 remote_file host delete "ld.version" 73 74 regexp "\[^\n\]* (cygnus-|)(\[-0-9.a-zA-Z-\]+)\[\r\n\].*" $tmp version cyg number 75 if [info exists number] then { 76 clone_output "$ld $number\n" 77 } 78} 79 80proc run_host_cmd { prog command } { 81 global link_output 82 global gcc_B_opt 83 global ld_L_opt 84 85 if { ![is_remote host] && [which "$prog"] == 0 } then { 86 perror "$prog does not exist" 87 return 0 88 } 89 90 # If we are compiling with gcc, we want to add gcc_B_opt and 91 # ld_L_opt to flags. However, if $prog already has -B options, 92 # which might be the case when running gcc out of a build 93 # directory, we want our -B options to come first. 94 set gccexe $prog 95 set gccparm [string first " " $gccexe] 96 set gccflags "" 97 if { $gccparm > 0 } then { 98 set gccflags [string range $gccexe $gccparm end] 99 set gccexe [string range $gccexe 0 $gccparm] 100 set prog $gccexe 101 } 102 set gccexe [string replace $gccexe 0 [string last "/" $gccexe] ""] 103 if {[string match "*cc*" $gccexe] || [string match "*++*" $gccexe]} then { 104 set gccflags "$gcc_B_opt $gccflags $ld_L_opt" 105 } 106 107 verbose -log "$prog $gccflags $command" 108 set status [remote_exec host [concat sh -c [list "$prog $gccflags $command 2>&1"]] "" "/dev/null" "ld.tmp"] 109 remote_upload host "ld.tmp" 110 set link_output [file_contents "ld.tmp"] 111 regsub "\n$" $link_output "" link_output 112 if { [lindex $status 0] != 0 && [string match "" $link_output] } then { 113 append link_output "child process exited abnormally" 114 } 115 remote_file build delete ld.tmp 116 remote_file host delete ld.tmp 117 118 if [string match "" $link_output] then { 119 return "" 120 } 121 122 verbose -log "$link_output" 123 return "$link_output" 124} 125 126proc run_host_cmd_yesno { prog command } { 127 global exec_output 128 129 set exec_output [prune_warnings [run_host_cmd "$prog" "$command"]] 130 if [string match "" $exec_output] then { 131 return 1; 132 } 133 return 0; 134} 135 136# Link an object using relocation. 137# 138proc default_ld_relocate { ld target objects } { 139 global HOSTING_EMU 140 141 remote_file host delete $target 142 return [run_host_cmd_yesno "$ld" "$HOSTING_EMU -o $target -r $objects"] 143} 144 145# Check to see if ld is being invoked with a non-endian output format 146# 147proc is_endian_output_format { object_flags } { 148 149 if {[string match "*-oformat binary*" $object_flags] || \ 150 [string match "*-oformat ieee*" $object_flags] || \ 151 [string match "*-oformat ihex*" $object_flags] || \ 152 [string match "*-oformat netbsd-core*" $object_flags] || \ 153 [string match "*-oformat srec*" $object_flags] || \ 154 [string match "*-oformat tekhex*" $object_flags] || \ 155 [string match "*-oformat trad-core*" $object_flags] } then { 156 return 0 157 } else { 158 return 1 159 } 160} 161 162# Look for big-endian or little-endian switches in the multlib 163# options and translate these into a -EB or -EL switch. Note 164# we cannot rely upon proc process_multilib_options to do this 165# for us because for some targets the compiler does not support 166# -EB/-EL but it does support -mbig-endian/-mlittle-endian, and 167# the site.exp file will include the switch "-mbig-endian" 168# (rather than "big-endian") which is not detected by proc 169# process_multilib_options. 170# 171proc big_or_little_endian {} { 172 173 if [board_info [target_info name] exists multilib_flags] { 174 set tmp_flags " [board_info [target_info name] multilib_flags]" 175 176 foreach x $tmp_flags { 177 case $x in { 178 {*big*endian eb EB -eb -EB -mb -meb} { 179 set flags " -EB" 180 return $flags 181 } 182 {*little*endian el EL -el -EL -ml -mel} { 183 set flags " -EL" 184 return $flags 185 } 186 } 187 } 188 } 189 190 set flags "" 191 return $flags 192} 193 194# Link a program using ld. 195# 196proc default_ld_link { ld target objects } { 197 global HOSTING_EMU 198 global HOSTING_CRT0 199 global HOSTING_SCRT0 200 global HOSTING_LIBS 201 global HOSTING_SLIBS 202 global LIBS 203 global host_triplet 204 global link_output 205 global exec_output 206 207 if { [ string match "* -pie *" $objects ] } { 208 set objs "$HOSTING_SCRT0 $objects" 209 set libs "$LIBS $HOSTING_SLIBS" 210 } else { 211 set objs "$HOSTING_CRT0 $objects" 212 set libs "$LIBS $HOSTING_LIBS" 213 } 214 215 if [is_endian_output_format $objects] then { 216 set flags [big_or_little_endian] 217 } else { 218 set flags "" 219 } 220 221 remote_file host delete $target 222 223 return [run_host_cmd_yesno "$ld" "$HOSTING_EMU $flags -o $target $objs $libs"] 224} 225 226# Link a program using ld, without including any libraries. 227# 228proc default_ld_simple_link { ld target objects } { 229 global host_triplet 230 global exec_output 231 232 set flags "" 233 if [is_endian_output_format $objects] then { 234 set flags [big_or_little_endian] 235 } 236 237 remote_file host delete $target 238 set exec_output [run_host_cmd "$ld" "$flags -o $target $objects"] 239 set exec_output [prune_warnings $exec_output] 240 241 # We don't care if we get a warning about a non-existent start 242 # symbol, since the default linker script might use ENTRY. 243 regsub -all "(^|\n)(\[^\n\]*: warning: cannot find entry symbol\[^\n\]*\n?)" $exec_output "\\1" exec_output 244 245 return [string match "" $exec_output] 246} 247 248# Compile an object using cc. 249# 250proc default_ld_compile { cc source object } { 251 global CFLAGS 252 global CXXFLAGS 253 global srcdir 254 global subdir 255 global host_triplet 256 global gcc_B_opt 257 258 set cc_prog $cc 259 if {[llength $cc_prog] > 1} then { 260 set cc_prog [lindex $cc_prog 0] 261 } 262 if {![is_remote host] && [which $cc_prog] == 0} then { 263 perror "$cc_prog does not exist" 264 return 0 265 } 266 267 remote_file build delete "$object" 268 remote_file host delete "$object" 269 270 set flags "$gcc_B_opt -I$srcdir/$subdir" 271 272 # If we are compiling with gcc, we want to add gcc_B_opt to flags. 273 # However, if $prog already has -B options, which might be the 274 # case when running gcc out of a build directory, we want our -B 275 # options to come first. 276 set ccexe $cc 277 set ccparm [string first " " $cc] 278 set ccflags "" 279 if { $ccparm > 0 } then { 280 set ccflags [string range $cc $ccparm end] 281 set ccexe [string range $cc 0 $ccparm] 282 set cc $ccexe 283 } 284 285 set ccexe [string replace $ccexe 0 [string last "/" $ccexe] ""] 286 if {[string match "*++*" $ccexe]} { 287 append flags " $CXXFLAGS" 288 } else { 289 append flags " $CFLAGS" 290 } 291 292 if [board_info [target_info name] exists cflags] { 293 append flags " [board_info [target_info name] cflags]" 294 } 295 296 if [board_info [target_info name] exists multilib_flags] { 297 append flags " [board_info [target_info name] multilib_flags]" 298 } 299 300 set cmd "$cc $flags $ccflags -c $source -o $object" 301 verbose -log "$cmd" 302 303 set status [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"] 304 remote_upload host "ld.tmp" 305 set exec_output [file_contents "ld.tmp"] 306 remote_file build delete "ld.tmp" 307 remote_file host delete "ld.tmp" 308 set exec_output [prune_warnings $exec_output] 309 if [string match "" $exec_output] then { 310 if {![file exists $object]} then { 311 regexp ".*/(\[^/\]*)$" $source all dobj 312 regsub "\\.c" $dobj ".o" realobj 313 verbose "looking for $realobj" 314 if {[remote_file host exists $realobj]} then { 315 verbose -log "mv $realobj $object" 316 remote_upload "$realobj" "$object" 317 } else { 318 perror "$object not found after compilation" 319 return 0 320 } 321 } 322 return 1 323 } else { 324 verbose -log "$exec_output" 325 perror "$source: compilation failed" 326 return 0 327 } 328} 329 330# Assemble a file. 331# 332proc default_ld_assemble { as in_flags source object } { 333 global ASFLAGS 334 global host_triplet 335 global srcdir 336 global subdir 337 338 if ![info exists ASFLAGS] { set ASFLAGS "" } 339 340 set flags "[big_or_little_endian] -I$srcdir/$subdir" 341 set exec_output [run_host_cmd "$as" "$flags $in_flags $ASFLAGS -o $object $source"] 342 set exec_output [prune_warnings $exec_output] 343 if [string match "" $exec_output] then { 344 return 1 345 } else { 346 perror "$source: assembly failed" 347 return 0 348 } 349} 350 351# Run nm on a file, putting the result in the array nm_output. 352# 353proc default_ld_nm { nm nmflags object } { 354 global NMFLAGS 355 global nm_output 356 global host_triplet 357 358 if {[info exists nm_output]} { 359 unset nm_output 360 } 361 362 if ![info exists NMFLAGS] { set NMFLAGS "" } 363 364 # Ensure consistent sorting of symbols 365 if {[info exists env(LC_ALL)]} { 366 set old_lc_all $env(LC_ALL) 367 } 368 set env(LC_ALL) "C" 369 370 verbose -log "$nm $NMFLAGS $nmflags $object >tmpdir/nm.out" 371 372 set status [remote_exec host [concat sh -c [list "$nm $NMFLAGS $nmflags $object 2>ld.stderr"]] "" "/dev/null" "tmpdir/nm.out"] 373 if {[info exists old_lc_all]} { 374 set env(LC_ALL) $old_lc_all 375 } else { 376 unset env(LC_ALL) 377 } 378 remote_upload host "ld.stderr" 379 remote_upload host "tmpdir/nm.out" "tmpdir/nm.out" 380 set exec_output [prune_warnings [file_contents "ld.stderr"]] 381 remote_file host delete "ld.stderr" 382 remote_file build delete "ld.stderr" 383 if [string match "" $exec_output] then { 384 set file [open tmpdir/nm.out r] 385 while { [gets $file line] != -1 } { 386 verbose "$line" 2 387 if [regexp "^(\[0-9a-fA-F\]+) \[a-zA-Z0-9\] \\.*(.+)$" $line whole value name] { 388 set name [string trimleft $name "_"] 389 verbose "Setting nm_output($name) to 0x$value" 2 390 set nm_output($name) 0x$value 391 } 392 } 393 close $file 394 return 1 395 } else { 396 verbose -log "$exec_output" 397 perror "$object: nm failed" 398 return 0 399 } 400} 401 402# Define various symbols needed when not linking against all 403# target libs. 404proc ld_simple_link_defsyms {} { 405 406 set flags "--defsym __stack_chk_fail=0" 407 408 # ARM targets call __gccmain 409 if {[istarget arm*-*-*]} { 410 append flags " --defsym __gccmain=0" 411 } 412 413 # Windows targets need __main, some prefixed with underscore. 414 if {[istarget *-*-cygwin* ] || [istarget *-*-mingw*]} { 415 append flags " --defsym __main=0 --defsym ___main=0" 416 } 417 418 # PowerPC EABI code calls __eabi. 419 if {[istarget powerpc*-*-eabi*] || [istarget powerpc*-*-rtems*]} { 420 append flags " --defsym __eabi=0" 421 } 422 423 # mn10200 code calls __truncsipsi2_d0_d2. 424 if {[istarget mn10200*-*-*]} then { 425 append flags " --defsym __truncsipsi2_d0_d2=0" 426 } 427 428 # m6811/m6812 code has references to soft registers. 429 if {[istarget m6811-*-*] || [istarget m6812-*-*] || [istarget m68hc1*-*-*]} { 430 append flags " --defsym _.frame=0 --defsym _.d1=0 --defsym _.d2=0" 431 append flags " --defsym _.d3=0 --defsym _.d4=0" 432 append flags " --defsym _.tmp=0 --defsym _.xy=0 --defsym _.z=0" 433 } 434 435 # Some OpenBSD targets have ProPolice and reference __guard and 436 # __stack_smash_handler. 437 if [istarget *-*-openbsd*] { 438 append flags " --defsym __guard=0" 439 append flags " --defsym __stack_smash_handler=0" 440 } 441 442 return $flags 443} 444 445# run_dump_test FILE (optional:) EXTRA_OPTIONS 446# Copied from gas testsuite, tweaked and further extended. 447# 448# Assemble a .s file, then run some utility on it and check the output. 449# 450# There should be an assembly language file named FILE.s in the test 451# suite directory, and a pattern file called FILE.d. `run_dump_test' 452# will assemble FILE.s, run some tool like `objdump', `objcopy', or 453# `nm' on the .o file to produce textual output, and then analyze that 454# with regexps. The FILE.d file specifies what program to run, and 455# what to expect in its output. 456# 457# The FILE.d file begins with zero or more option lines, which specify 458# flags to pass to the assembler, the program to run to dump the 459# assembler's output, and the options it wants. The option lines have 460# the syntax: 461# 462# # OPTION: VALUE 463# 464# OPTION is the name of some option, like "name" or "objdump", and 465# VALUE is OPTION's value. The valid options are described below. 466# Whitespace is ignored everywhere, except within VALUE. The option 467# list ends with the first line that doesn't match the above syntax 468# (hmm, not great for error detection). 469# 470# The optional EXTRA_OPTIONS argument to `run_dump_test' is a list of 471# two-element lists. The first element of each is an option name, and 472# the second additional arguments to be added on to the end of the 473# option list as given in FILE.d. (If omitted, no additional options 474# are added.) 475# 476# The interesting options are: 477# 478# name: TEST-NAME 479# The name of this test, passed to DejaGNU's `pass' and `fail' 480# commands. If omitted, this defaults to FILE, the root of the 481# .s and .d files' names. 482# 483# as: FLAGS 484# When assembling, pass FLAGS to the assembler. 485# If assembling several files, you can pass different assembler 486# options in the "source" directives. See below. 487# 488# ld: FLAGS 489# Link assembled files using FLAGS, in the order of the "source" 490# directives, when using multiple files. 491# 492# ld_after_inputfiles: FLAGS 493# Similar to "ld", but put after all input files. 494# 495# objcopy_objects: FLAGS 496# Run objcopy with the specified flags after assembling any source 497# that has the special marker RUN_OBJCOPY in the source specific 498# flags. 499# 500# objcopy_linked_file: FLAGS 501# Run objcopy on the linked file with the specified flags. 502# This lets you transform the linked file using objcopy, before the 503# result is analyzed by an analyzer program specified below (which 504# may in turn *also* be objcopy). 505# 506# PROG: PROGRAM-NAME 507# The name of the program to run to analyze the .o file produced 508# by the assembler or the linker output. This can be omitted; 509# run_dump_test will guess which program to run by seeing which of 510# the flags options below is present. 511# 512# objdump: FLAGS 513# nm: FLAGS 514# objcopy: FLAGS 515# Use the specified program to analyze the assembler or linker 516# output file, and pass it FLAGS, in addition to the output name. 517# Note that they are run with LC_ALL=C in the environment to give 518# consistent sorting of symbols. 519# 520# source: SOURCE [FLAGS] 521# Assemble the file SOURCE.s using the flags in the "as" directive 522# and the (optional) FLAGS. If omitted, the source defaults to 523# FILE.s. 524# This is useful if several .d files want to share a .s file. 525# More than one "source" directive can be given, which is useful 526# when testing linking. 527# 528# dump: DUMP 529# Match against DUMP.d. If omitted, this defaults to FILE.d. This 530# is useful if several .d files differ by options only. Options are 531# always read from FILE.d. 532# 533# xfail: TARGET 534# The test is expected to fail on TARGET. This may occur more than 535# once. 536# 537# target: TARGET 538# Only run the test for TARGET. This may occur more than once; the 539# target being tested must match at least one. You may provide target 540# name "cfi" for any target supporting the CFI statements. 541# 542# notarget: TARGET 543# Do not run the test for TARGET. This may occur more than once; 544# the target being tested must not match any of them. 545# 546# error: REGEX 547# An error with message matching REGEX must be emitted for the test 548# to pass. The PROG, objdump, nm and objcopy options have no 549# meaning and need not supplied if this is present. Multiple "error" 550# directives append to the expected linker error message. 551# 552# warning: REGEX 553# Expect a linker warning matching REGEX. It is an error to issue 554# both "error" and "warning". Multiple "warning" directives 555# append to the expected linker warning message. 556# 557# Each option may occur at most once unless otherwise mentioned. 558# 559# After the option lines come regexp lines. `run_dump_test' calls 560# `regexp_diff' to compare the output of the dumping tool against the 561# regexps in FILE.d. `regexp_diff' is defined in binutils-common.exp; 562# see further comments there. 563# 564proc run_dump_test { name {extra_options {}} } { 565 global subdir srcdir 566 global OBJDUMP NM AS OBJCOPY READELF LD 567 global OBJDUMPFLAGS NMFLAGS ASFLAGS OBJCOPYFLAGS READELFFLAGS LDFLAGS 568 global host_triplet runtests 569 global env verbose 570 571 if [string match "*/*" $name] { 572 set file $name 573 set name [file tail $name] 574 } else { 575 set file "$srcdir/$subdir/$name" 576 } 577 578 if ![runtest_file_p $runtests $name] then { 579 return 580 } 581 582 set opt_array [slurp_options "${file}.d"] 583 if { $opt_array == -1 } { 584 perror "error reading options from $file.d" 585 unresolved $subdir/$name 586 return 587 } 588 set dumpfile tmpdir/dump.out 589 set run_ld 0 590 set run_objcopy 0 591 set opts(as) {} 592 set opts(ld) {} 593 set opts(ld_after_inputfiles) {} 594 set opts(xfail) {} 595 set opts(target) {} 596 set opts(notarget) {} 597 set opts(objdump) {} 598 set opts(nm) {} 599 set opts(objcopy) {} 600 set opts(readelf) {} 601 set opts(name) {} 602 set opts(PROG) {} 603 set opts(source) {} 604 set opts(dump) {} 605 set opts(error) {} 606 set opts(warning) {} 607 set opts(objcopy_linked_file) {} 608 set opts(objcopy_objects) {} 609 610 foreach i $opt_array { 611 set opt_name [lindex $i 0] 612 set opt_val [lindex $i 1] 613 if ![info exists opts($opt_name)] { 614 perror "unknown option $opt_name in file $file.d" 615 unresolved $subdir/$name 616 return 617 } 618 619 switch -- $opt_name { 620 xfail {} 621 target {} 622 notarget {} 623 warning {} 624 error {} 625 source { 626 # Move any source-specific as-flags to a separate list to 627 # simplify processing. 628 if { [llength $opt_val] > 1 } { 629 lappend asflags [lrange $opt_val 1 end] 630 set opt_val [lindex $opt_val 0] 631 } else { 632 lappend asflags {} 633 } 634 } 635 default { 636 if [string length $opts($opt_name)] { 637 perror "option $opt_name multiply set in $file.d" 638 unresolved $subdir/$name 639 return 640 } 641 642 # A single "# ld:" with no options should do the right thing. 643 if { $opt_name == "ld" } { 644 set run_ld 1 645 } 646 # Likewise objcopy_linked_file. 647 if { $opt_name == "objcopy_linked_file" } { 648 set run_objcopy 1 649 } 650 } 651 } 652 if { $opt_name == "as" || $opt_name == "ld" } { 653 set opt_val [subst $opt_val] 654 } 655 656 # Append differently whether it's a message (without space) or 657 # an option or list (with space). 658 switch -- $opt_name { 659 warning - 660 error { 661 append opts($opt_name) $opt_val 662 } 663 default { 664 set opts($opt_name) [concat $opts($opt_name) $opt_val] 665 } 666 } 667 } 668 669 foreach i $extra_options { 670 set opt_name [lindex $i 0] 671 set opt_val [lindex $i 1] 672 if ![info exists opts($opt_name)] { 673 perror "unknown option $opt_name given in extra_opts" 674 unresolved $subdir/$name 675 return 676 } 677 # Add extra option to end of existing option, adding space 678 # if necessary. 679 if { ![regexp "warning|error" $opt_name] 680 && [string length $opts($opt_name)] } { 681 append opts($opt_name) " " 682 } 683 append opts($opt_name) $opt_val 684 } 685 686 foreach opt { as ld } { 687 regsub {\[big_or_little_endian\]} $opts($opt) \ 688 [big_or_little_endian] opts($opt) 689 } 690 691 # Decide early whether we should run the test for this target. 692 if { [llength $opts(target)] > 0 } { 693 set targmatch 0 694 foreach targ $opts(target) { 695 if [istarget $targ] { 696 set targmatch 1 697 break 698 } 699 } 700 if { $targmatch == 0 } { 701 return 702 } 703 } 704 foreach targ $opts(notarget) { 705 if [istarget $targ] { 706 return 707 } 708 } 709 710 set program "" 711 # It's meaningless to require an output-testing method when we 712 # expect an error. 713 if { $opts(error) == "" } { 714 if {$opts(PROG) != ""} { 715 switch -- $opts(PROG) { 716 objdump { set program objdump } 717 nm { set program nm } 718 objcopy { set program objcopy } 719 readelf { set program readelf } 720 default 721 { perror "unrecognized program option $opts(PROG) in $file.d" 722 unresolved $subdir/$name 723 return } 724 } 725 } else { 726 # Guess which program to run, by seeing which option was specified. 727 foreach p {objdump objcopy nm readelf} { 728 if {$opts($p) != ""} { 729 if {$program != ""} { 730 perror "ambiguous dump program in $file.d" 731 unresolved $subdir/$name 732 return 733 } else { 734 set program $p 735 } 736 } 737 } 738 } 739 if { $program == "" && $opts(warning) == "" } { 740 perror "dump program unspecified in $file.d" 741 unresolved $subdir/$name 742 return 743 } 744 } 745 746 if { $opts(name) == "" } { 747 set testname "$subdir/$name" 748 } else { 749 set testname $opts(name) 750 } 751 752 if { $opts(source) == "" } { 753 set sourcefiles [list ${file}.s] 754 set asflags [list ""] 755 } else { 756 set sourcefiles {} 757 foreach sf $opts(source) { 758 if { [string match "/*" $sf] } { 759 lappend sourcefiles "$sf" 760 } else { 761 lappend sourcefiles "$srcdir/$subdir/$sf" 762 } 763 } 764 } 765 766 if { $opts(dump) == "" } { 767 set dfile ${file}.d 768 } else { 769 set dfile $srcdir/$subdir/$opts(dump) 770 } 771 772 if { [string match "*--compress-debug-sections*" $opts(as)] \ 773 && ![is_zlib_supported] } { 774 unsupported $testname 775 return 776 } 777 778 # Time to setup xfailures. 779 foreach targ $opts(xfail) { 780 setup_xfail $targ 781 } 782 783 # Assemble each file. 784 set objfiles {} 785 for { set i 0 } { $i < [llength $sourcefiles] } { incr i } { 786 set sourcefile [lindex $sourcefiles $i] 787 set sourceasflags [lindex $asflags $i] 788 set run_objcopy_objects 0 789 790 if { [string match "*RUN_OBJCOPY*" $sourceasflags] } { 791 set run_objcopy_objects 1 792 } 793 regsub "RUN_OBJCOPY" $sourceasflags "" sourceasflags 794 795 set objfile "tmpdir/dump$i.o" 796 catch "exec rm -f $objfile" exec_output 797 lappend objfiles $objfile 798 set cmd "$AS $ASFLAGS $opts(as) $sourceasflags -o $objfile $sourcefile" 799 800 send_log "$cmd\n" 801 set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"] 802 remote_upload host "ld.tmp" 803 set comp_output [prune_warnings [file_contents "ld.tmp"]] 804 remote_file host delete "ld.tmp" 805 remote_file build delete "ld.tmp" 806 807 if { [lindex $cmdret 0] != 0 || ![string match "" $comp_output] } then { 808 send_log "$comp_output\n" 809 verbose "$comp_output" 3 810 811 set exitstat "succeeded" 812 if { $cmdret != 0 } { set exitstat "failed" } 813 verbose -log "$exitstat with: <$comp_output>" 814 fail $testname 815 return 816 } 817 818 if { $run_objcopy_objects } { 819 set cmd "$OBJCOPY $opts(objcopy_objects) $objfile" 820 821 send_log "$cmd\n" 822 set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] \ 823 "" "/dev/null" "objcopy.tmp"] 824 remote_upload host "objcopy.tmp" 825 set comp_output [prune_warnings [file_contents "objcopy.tmp"]] 826 remote_file host delete "objcopy.tmp" 827 remote_file build delete "objcopy.tmp" 828 829 if { [lindex $cmdret 0] != 0 \ 830 || ![string match "" $comp_output] } { 831 send_log "$comp_output\n" 832 verbose "$comp_output" 3 833 834 set exitstat "succeeded" 835 if { $cmdret != 0 } { set exitstat "failed" } 836 verbose -log "$exitstat with: <$comp_output>" 837 fail $testname 838 return 839 } 840 } 841 } 842 843 set expmsg $opts(error) 844 if { $opts(warning) != "" } { 845 if { $expmsg != "" } { 846 perror "$testname: mixing error and warning test-directives" 847 return 848 } 849 set expmsg $opts(warning) 850 } 851 852 # Perhaps link the file(s). 853 if { $run_ld } { 854 set objfile "tmpdir/dump" 855 catch "exec rm -f $objfile" exec_output 856 857 # Add -L$srcdir/$subdir so that the linker command can use 858 # linker scripts in the source directory. 859 set cmd "$LD $LDFLAGS -L$srcdir/$subdir \ 860 $opts(ld) -o $objfile $objfiles $opts(ld_after_inputfiles)" 861 862 send_log "$cmd\n" 863 set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"] 864 remote_upload host "ld.tmp" 865 set comp_output [file_contents "ld.tmp"] 866 remote_file host delete "ld.tmp" 867 remote_file build delete "ld.tmp" 868 set cmdret [lindex $cmdret 0] 869 870 if { $cmdret == 0 && $run_objcopy } { 871 set infile $objfile 872 set objfile "tmpdir/dump1" 873 remote_file host delete $objfile 874 875 # Note that we don't use OBJCOPYFLAGS here; any flags must be 876 # explicitly specified. 877 set cmd "$OBJCOPY $opts(objcopy_linked_file) $infile $objfile" 878 879 send_log "$cmd\n" 880 set cmdret [remote_exec host [concat sh -c [list "$cmd 2>&1"]] "" "/dev/null" "ld.tmp"] 881 remote_upload host "ld.tmp" 882 append comp_output [file_contents "ld.tmp"] 883 remote_file host delete "ld.tmp" 884 remote_file build delete "ld.tmp" 885 set cmdret [lindex $cmdret 0] 886 } 887 888 regsub "\n$" $comp_output "" comp_output 889 if { $cmdret != 0 || $comp_output != "" || $expmsg != "" } then { 890 set exitstat "succeeded" 891 if { $cmdret != 0 } { set exitstat "failed" } 892 verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>" 893 send_log "$comp_output\n" 894 verbose "$comp_output" 3 895 896 if { ($expmsg == "") == ($comp_output == "") \ 897 && [regexp $expmsg $comp_output] \ 898 && (($cmdret == 0) == ($opts(error) == "")) } { 899 # We have the expected output from ld. 900 if { $opts(error) != "" || $program == "" } { 901 pass $testname 902 return 903 } 904 } else { 905 verbose -log "$exitstat with: <$comp_output>, expected: <$expmsg>" 906 fail $testname 907 return 908 } 909 } 910 } else { 911 set objfile "tmpdir/dump0.o" 912 } 913 914 # We must not have expected failure if we get here. 915 if { $opts(error) != "" } { 916 fail $testname 917 return 918 } 919 920 set progopts1 $opts($program) 921 eval set progopts \$[string toupper $program]FLAGS 922 eval set binary \$[string toupper $program] 923 924 if { ![is_remote host] && [which $binary] == 0 } { 925 untested $testname 926 return 927 } 928 929 if { $progopts1 == "" } { set $progopts1 "-r" } 930 verbose "running $binary $progopts $progopts1" 3 931 932 # Objcopy, unlike the other two, won't send its output to stdout, 933 # so we have to run it specially. 934 set cmd "$binary $progopts $progopts1 $objfile > $dumpfile" 935 if { $program == "objcopy" } { 936 set cmd "$binary $progopts $progopts1 $objfile $dumpfile" 937 } 938 939 # Ensure consistent sorting of symbols 940 if {[info exists env(LC_ALL)]} { 941 set old_lc_all $env(LC_ALL) 942 } 943 set env(LC_ALL) "C" 944 send_log "$cmd\n" 945 set cmdret [remote_exec host [concat sh -c [list "$cmd 2>ld.tmp"]] "" "/dev/null"] 946 set cmdret [lindex $cmdret 0] 947 remote_upload host "ld.tmp" 948 set comp_output [prune_warnings [file_contents "ld.tmp"]] 949 remote_file host delete "ld.tmp" 950 remote_file build delete "ld.tmp" 951 if {[info exists old_lc_all]} { 952 set env(LC_ALL) $old_lc_all 953 } else { 954 unset env(LC_ALL) 955 } 956 if { $cmdret != 0 || $comp_output != "" } { 957 send_log "exited abnormally with $cmdret, output:$comp_output\n" 958 fail $testname 959 return 960 } 961 962 if { $verbose > 2 } then { verbose "output is [file_contents $dumpfile]" 3 } 963 if { [regexp_diff $dumpfile "${dfile}"] } then { 964 fail $testname 965 if { $verbose == 2 } then { verbose "output is [file_contents $dumpfile]" 2 } 966 return 967 } 968 969 pass $testname 970} 971 972proc slurp_options { file } { 973 # If options_regsub(foo) is set to {a b}, then the contents of a 974 # "#foo:" line will have regsub -all applied to replace a with b. 975 global options_regsub 976 977 if [catch { set f [open $file r] } x] { 978 #perror "couldn't open `$file': $x" 979 perror "$x" 980 return -1 981 } 982 set opt_array {} 983 # whitespace expression 984 set ws {[ ]*} 985 set nws {[^ ]*} 986 # whitespace is ignored anywhere except within the options list; 987 # option names are alphabetic plus underscore only. 988 set pat "^#${ws}(\[a-zA-Z_\]*)$ws:${ws}(.*)$ws\$" 989 while { [gets $f line] != -1 } { 990 set line [string trim $line] 991 # Whitespace here is space-tab. 992 if [regexp $pat $line xxx opt_name opt_val] { 993 # match! 994 if [info exists options_regsub($opt_name)] { 995 set subst $options_regsub($opt_name) 996 regsub -all -- [lindex $subst 0] $opt_val [lindex $subst 1] \ 997 opt_val 998 } 999 lappend opt_array [list $opt_name $opt_val] 1000 } else { 1001 break 1002 } 1003 } 1004 close $f 1005 return $opt_array 1006} 1007 1008proc file_contents { filename } { 1009 set file [open $filename r] 1010 set contents [read $file] 1011 close $file 1012 return $contents 1013} 1014 1015proc set_file_contents { filename contents } { 1016 set file [open $filename w] 1017 puts $file "$contents" 1018 close $file 1019} 1020 1021# Create an archive using ar 1022# 1023proc ar_simple_create { ar aropts target objects } { 1024 remote_file host delete $target 1025 1026 set exec_output [run_host_cmd "$ar" "$aropts -rc $target $objects"] 1027 set exec_output [prune_warnings $exec_output] 1028 1029 if [string match "" $exec_output] then { 1030 send_log "$exec_output\n" 1031 return 1 1032 } else { 1033 return 0 1034 } 1035} 1036 1037# List contains test-items with 3 items followed by 2 lists, one item and 1038# one optional item: 1039# 0:name 1040# 1:ld/ar leading options, placed before object files 1041# 2:ld/ar trailing options, placed after object files 1042# 3:assembler options 1043# 4:filenames of assembler files 1044# 5:list of actions, options and expected outputs. 1045# 6:name of output file 1046# 7:compiler flags (optional) 1047# 1048# Actions: { command command-line-options file-containg-expected-output-regexps } 1049# Commands: 1050# objdump: Apply objdump options on result. 1051# nm: Apply nm options on result. 1052# readelf: Apply readelf options on result. 1053# ld: Don't apply anything on result. Compare output during linking with 1054# the file containing regexps (which is the second arg, not the third). 1055# Note that this *must* be the first action if it is to be used at all; 1056# in all other cases, any output from the linker during linking is 1057# treated as a sign of an error and FAILs the test. 1058# 1059proc run_ld_link_tests { ldtests } { 1060 global ld 1061 global as 1062 global nm 1063 global ar 1064 global objdump 1065 global READELF 1066 global srcdir 1067 global subdir 1068 global env 1069 global CC 1070 global CFLAGS 1071 global runtests 1072 global exec_output 1073 1074 foreach testitem $ldtests { 1075 set testname [lindex $testitem 0] 1076 1077 if ![runtest_file_p $runtests $testname] then { 1078 continue 1079 } 1080 1081 set ld_options [lindex $testitem 1] 1082 set ld_after [lindex $testitem 2] 1083 set as_options [lindex $testitem 3] 1084 set src_files [lindex $testitem 4] 1085 set actions [lindex $testitem 5] 1086 set binfile tmpdir/[lindex $testitem 6] 1087 set cflags [lindex $testitem 7] 1088 set objfiles {} 1089 set is_unresolved 0 1090 set failed 0 1091 set maybe_failed 0 1092 set ld_output "" 1093 1094# verbose -log "Testname is $testname" 1095# verbose -log "ld_options is $ld_options" 1096# verbose -log "ld_after is $ld_after" 1097# verbose -log "as_options is $as_options" 1098# verbose -log "src_files is $src_files" 1099# verbose -log "actions is $actions" 1100# verbose -log "binfile is $binfile" 1101 1102 # Assemble each file in the test. 1103 foreach src_file $src_files { 1104 set fileroot "[file rootname [file tail $src_file]]" 1105 set objfile "tmpdir/$fileroot.o" 1106 lappend objfiles $objfile 1107 1108 if { [file extension $src_file] == ".c" } { 1109 set as_file "tmpdir/$fileroot.s" 1110 if ![ld_compile "$CC -S $CFLAGS $cflags" $srcdir/$subdir/$src_file $as_file] { 1111 set is_unresolved 1 1112 break 1113 } 1114 } else { 1115 set as_file "$srcdir/$subdir/$src_file" 1116 } 1117 if ![ld_assemble $as "$as_options $as_file" $objfile] { 1118 set is_unresolved 1 1119 break 1120 } 1121 } 1122 1123 # Catch assembler errors. 1124 if { $is_unresolved } { 1125 unresolved $testname 1126 continue 1127 } 1128 1129 if { $binfile eq "tmpdir/" } { 1130 # compile only 1131 } elseif { [regexp ".*\\.a$" $binfile] } { 1132 if { ![ar_simple_create $ar $ld_options $binfile "$objfiles $ld_after"] } { 1133 set failed 1 1134 } 1135 } elseif { ![ld_simple_link $ld $binfile "-L$srcdir/$subdir $ld_options $objfiles $ld_after"] } { 1136 set maybe_failed 1 1137 set ld_output "$exec_output" 1138 } 1139 1140 if { !$failed } { 1141 foreach actionlist $actions { 1142 set action [lindex $actionlist 0] 1143 set progopts [lindex $actionlist 1] 1144 1145 # There are actions where we run regexp_diff on the 1146 # output, and there are other actions (presumably). 1147 # Handling of the former look the same. 1148 set dump_prog "" 1149 switch -- $action { 1150 objdump 1151 { set dump_prog $objdump } 1152 nm 1153 { set dump_prog $nm } 1154 readelf 1155 { set dump_prog $READELF } 1156 ld 1157 { set dump_prog "ld" } 1158 default 1159 { 1160 perror "Unrecognized action $action" 1161 set is_unresolved 1 1162 break 1163 } 1164 } 1165 1166 if { $action == "ld" } { 1167 set regexpfile $progopts 1168 verbose "regexpfile is $srcdir/$subdir/$regexpfile" 1169 set_file_contents "tmpdir/ld.messages" "$ld_output" 1170 verbose "ld.messages has '[file_contents tmpdir/ld.messages]'" 1171 if { [regexp_diff "tmpdir/ld.messages" "$srcdir/$subdir/$regexpfile"] } then { 1172 verbose "output is $ld_output" 2 1173 set failed 1 1174 break 1175 } 1176 set maybe_failed 0 1177 } elseif { !$maybe_failed && $dump_prog != "" } { 1178 set dumpfile [lindex $actionlist 2] 1179 set binary $dump_prog 1180 1181 # Ensure consistent sorting of symbols 1182 if {[info exists env(LC_ALL)]} { 1183 set old_lc_all $env(LC_ALL) 1184 } 1185 set env(LC_ALL) "C" 1186 set cmd "$binary $progopts $binfile" 1187 set status [remote_exec host [concat sh -c [list "$cmd >dump.out 2>ld.stderr"]] "" "/dev/null"] 1188 send_log "$cmd\n" 1189 remote_upload host "ld.stderr" 1190 set comp_output [prune_warnings [file_contents "ld.stderr"]] 1191 remote_file host delete "ld.stderr" 1192 remote_file build delete "ld.stderr" 1193 1194 if {[info exists old_lc_all]} { 1195 set env(LC_ALL) $old_lc_all 1196 } else { 1197 unset env(LC_ALL) 1198 } 1199 1200 if ![string match "" $comp_output] then { 1201 send_log "$comp_output\n" 1202 set failed 1 1203 break 1204 } 1205 1206 remote_upload host "dump.out" 1207 1208 if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then { 1209 verbose "output is [file_contents "dump.out"]" 2 1210 set failed 1 1211 remote_file build delete "dump.out" 1212 remote_file host delete "dump.out" 1213 break 1214 } 1215 remote_file build delete "dump.out" 1216 remote_file host delete "dump.out" 1217 } 1218 } 1219 } 1220 1221 if { $is_unresolved } { 1222 unresolved $testname 1223 } elseif { $maybe_failed || $failed } { 1224 fail $testname 1225 } else { 1226 pass $testname 1227 } 1228 } 1229} 1230 1231# This definition is taken from an unreleased version of DejaGnu. Once 1232# that version gets released, and has been out in the world for a few 1233# months at least, it may be safe to delete this copy. 1234if ![string length [info proc prune_warnings]] { 1235 # 1236 # prune_warnings -- delete various system verbosities from TEXT 1237 # 1238 # An example is: 1239 # ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9 1240 # 1241 # Sites with particular verbose os's may wish to override this in site.exp. 1242 # 1243 proc prune_warnings { text } { 1244 # This is from sun4's. Do it for all machines for now. 1245 # The "\\1" is to try to preserve a "\n" but only if necessary. 1246 regsub -all "(^|\n)(ld.so: warning:\[^\n\]*\n?)+" $text "\\1" text 1247 1248 # It might be tempting to get carried away and delete blank lines, etc. 1249 # Just delete *exactly* what we're ask to, and that's it. 1250 return $text 1251 } 1252} 1253 1254# targets_to_xfail is a list of target triplets to be xfailed. 1255# ldtests contains test-items with 3 items followed by 1 lists, 2 items 1256# and 3 optional items: 1257# 0:name 1258# 1:ld options 1259# 2:assembler options 1260# 3:filenames of source files 1261# 4:name of output file 1262# 5:expected output 1263# 6:compiler flags (optional) 1264# 7:language (optional) 1265# 8:linker warning (optional) 1266 1267proc run_ld_link_exec_tests { targets_to_xfail ldtests } { 1268 global ld 1269 global as 1270 global srcdir 1271 global subdir 1272 global env 1273 global CC 1274 global CXX 1275 global CFLAGS 1276 global CXXFLAGS 1277 global errcnt 1278 global exec_output 1279 1280 foreach testitem $ldtests { 1281 foreach target $targets_to_xfail { 1282 setup_xfail $target 1283 } 1284 set testname [lindex $testitem 0] 1285 set ld_options [lindex $testitem 1] 1286 set as_options [lindex $testitem 2] 1287 set src_files [lindex $testitem 3] 1288 set binfile tmpdir/[lindex $testitem 4] 1289 set expfile [lindex $testitem 5] 1290 set cflags [lindex $testitem 6] 1291 set lang [lindex $testitem 7] 1292 set warning [lindex $testitem 8] 1293 set objfiles {} 1294 set failed 0 1295 1296# verbose -log "Testname is $testname" 1297# verbose -log "ld_options is $ld_options" 1298# verbose -log "as_options is $as_options" 1299# verbose -log "src_files is $src_files" 1300# verbose -log "binfile is $binfile" 1301 1302 # Assemble each file in the test. 1303 foreach src_file $src_files { 1304 set fileroot "[file rootname [file tail $src_file]]" 1305 set objfile "tmpdir/$fileroot.o" 1306 lappend objfiles $objfile 1307 1308 # We ignore warnings since some compilers may generate 1309 # incorrect section attributes and the assembler will warn 1310 # them. 1311 if { [ string match "c++" $lang ] } { 1312 ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile 1313 } else { 1314 ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile 1315 } 1316 } 1317 1318 # We have to use $CC to build PIE and shared library. 1319 if { [ string match "c" $lang ] } { 1320 set link_proc ld_simple_link 1321 set link_cmd $CC 1322 } elseif { [ string match "c++" $lang ] } { 1323 set link_proc ld_simple_link 1324 set link_cmd $CXX 1325 } elseif { [ string match "-shared" $ld_options ] \ 1326 || [ string match "-pie" $ld_options ] } { 1327 set link_proc ld_simple_link 1328 set link_cmd $CC 1329 } else { 1330 set link_proc ld_link 1331 set link_cmd $ld 1332 } 1333 1334 if { $binfile eq "tmpdir/" } { 1335 # compile only 1336 pass $testname 1337 continue; 1338 } elseif ![$link_proc $link_cmd $binfile "-L$srcdir/$subdir $ld_options $objfiles"] { 1339 set failed 1 1340 } 1341 1342 # Check if exec_output is expected. 1343 if { $warning != "" } then { 1344 verbose -log "returned with: <$exec_output>, expected: <$warning>" 1345 if { [regexp $warning $exec_output] } then { 1346 set failed 0 1347 } else { 1348 set failed 1 1349 } 1350 } 1351 1352 if { $failed == 0 } { 1353 send_log "Running: $binfile > $binfile.out\n" 1354 verbose "Running: $binfile > $binfile.out" 1355 catch "exec $binfile > $binfile.out" exec_output 1356 1357 if ![string match "" $exec_output] then { 1358 send_log "$exec_output\n" 1359 verbose "$exec_output" 1 1360 set failed 1 1361 } else { 1362 send_log "diff $binfile.out $srcdir/$subdir/$expfile\n" 1363 verbose "diff $binfile.out $srcdir/$subdir/$expfile" 1364 catch "exec diff $binfile.out $srcdir/$subdir/$expfile" exec_output 1365 set exec_output [prune_warnings $exec_output] 1366 1367 if ![string match "" $exec_output] then { 1368 send_log "$exec_output\n" 1369 verbose "$exec_output" 1 1370 set failed 1 1371 } 1372 } 1373 } 1374 1375 if { $failed != 0 } { 1376 fail $testname 1377 } else { 1378 set errcnt 0 1379 pass $testname 1380 } 1381 } 1382} 1383 1384# List contains test-items with 3 items followed by 2 lists, one item and 1385# one optional item: 1386# 0:name 1387# 1:ld or ar options 1388# 2:compile options 1389# 3:filenames of source files 1390# 4:action and options. 1391# 5:name of output file 1392# 6:language (optional) 1393# 7:linker warnings (optional) 1394# 1395# Actions: 1396# objdump: Apply objdump options on result. Compare with regex (last arg). 1397# nm: Apply nm options on result. Compare with regex (last arg). 1398# readelf: Apply readelf options on result. Compare with regex (last arg). 1399# 1400proc run_cc_link_tests { ldtests } { 1401 global nm 1402 global objdump 1403 global READELF 1404 global srcdir 1405 global subdir 1406 global env 1407 global CC 1408 global CXX 1409 global CFLAGS 1410 global CXXFLAGS 1411 global ar 1412 global exec_output 1413 global board_cflags 1414 1415 if [board_info [target_info name] exists cflags] { 1416 set board_cflags " [board_info [target_info name] cflags]" 1417 } else { 1418 set board_cflags "" 1419 } 1420 1421 foreach testitem $ldtests { 1422 set testname [lindex $testitem 0] 1423 set ldflags [lindex $testitem 1] 1424 set cflags [lindex $testitem 2] 1425 set src_files [lindex $testitem 3] 1426 set actions [lindex $testitem 4] 1427 set binfile tmpdir/[lindex $testitem 5] 1428 set lang [lindex $testitem 6] 1429 set warnings [lindex $testitem 7] 1430 set objfiles {} 1431 set is_unresolved 0 1432 set failed 0 1433 1434 #verbose -log "testname is $testname" 1435 #verbose -log "ldflags is $ldflags" 1436 #verbose -log "cflags is $cflags" 1437 #verbose -log "src_files is $src_files" 1438 #verbose -log "actions is $actions" 1439 #verbose -log "binfile is $binfile" 1440 #verbose -log "lang is $lang" 1441 #verbose -log "warnings is $warnings" 1442 1443 # Compile each file in the test. 1444 foreach src_file $src_files { 1445 set fileroot "[file rootname [file tail $src_file]]" 1446 set objfile "tmpdir/$fileroot.o" 1447 lappend objfiles $objfile 1448 1449 # We ignore warnings since some compilers may generate 1450 # incorrect section attributes and the assembler will warn 1451 # them. 1452 if { [ string match "c++" $lang ] } { 1453 ld_compile "$CXX -c $CXXFLAGS $cflags" $srcdir/$subdir/$src_file $objfile 1454 } else { 1455 ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/$src_file $objfile 1456 } 1457 } 1458 1459 # Clear error and warning counts. 1460 reset_vars 1461 1462 if { [ string match "c++" $lang ] } { 1463 set cc_cmd $CXX 1464 } else { 1465 set cc_cmd $CC 1466 } 1467 1468 if { $binfile eq "tmpdir/" } { 1469 # compile only 1470 } elseif { [regexp ".*\\.a$" $binfile] } { 1471 if { ![ar_simple_create $ar $ldflags $binfile "$objfiles"] } { 1472 fail $testname 1473 set failed 1 1474 } 1475 } else { 1476 if { ![ld_simple_link $cc_cmd $binfile "$board_cflags -L$srcdir/$subdir $ldflags $objfiles"] } { 1477 set failed 1 1478 } 1479 1480 # Check if exec_output is expected. 1481 if { $warnings != "" } then { 1482 verbose -log "returned with: <$exec_output>, expected: <$warnings>" 1483 if { [regexp $warnings $exec_output] } then { 1484 set failed 0 1485 } else { 1486 set failed 1 1487 } 1488 } 1489 1490 if { $failed == 1 } { 1491 fail $testname 1492 } 1493 } 1494 1495 if { $failed == 0 } { 1496 foreach actionlist $actions { 1497 set action [lindex $actionlist 0] 1498 set progopts [lindex $actionlist 1] 1499 1500 # There are actions where we run regexp_diff on the 1501 # output, and there are other actions (presumably). 1502 # Handling of the former look the same. 1503 set dump_prog "" 1504 switch -- $action { 1505 objdump 1506 { set dump_prog $objdump } 1507 nm 1508 { set dump_prog $nm } 1509 readelf 1510 { set dump_prog $READELF } 1511 default 1512 { 1513 perror "Unrecognized action $action" 1514 set is_unresolved 1 1515 break 1516 } 1517 } 1518 1519 if { $dump_prog != "" } { 1520 set dumpfile [lindex $actionlist 2] 1521 set binary $dump_prog 1522 1523 # Ensure consistent sorting of symbols 1524 if {[info exists env(LC_ALL)]} { 1525 set old_lc_all $env(LC_ALL) 1526 } 1527 set env(LC_ALL) "C" 1528 set cmd "$binary $progopts $binfile > dump.out" 1529 send_log "$cmd\n" 1530 catch "exec $cmd" comp_output 1531 if {[info exists old_lc_all]} { 1532 set env(LC_ALL) $old_lc_all 1533 } else { 1534 unset env(LC_ALL) 1535 } 1536 set comp_output [prune_warnings $comp_output] 1537 1538 if ![string match "" $comp_output] then { 1539 send_log "$comp_output\n" 1540 set failed 1 1541 break 1542 } 1543 1544 if { [regexp_diff "dump.out" "$srcdir/$subdir/$dumpfile"] } then { 1545 verbose "output is [file_contents "dump.out"]" 2 1546 set failed 1 1547 break 1548 } 1549 } 1550 } 1551 } 1552 1553 if { $failed != 0 } { 1554 fail $testname 1555 } elseif { $is_unresolved == 0 } { 1556 pass $testname 1557 } else { 1558 unresolved $testname 1559 continue 1560 } 1561 } 1562} 1563 1564# Returns true if --gc-sections is supported on the target. 1565 1566proc check_gc_sections_available { } { 1567 global gc_sections_available_saved 1568 global ld 1569 1570 if {![info exists gc_sections_available_saved]} { 1571 # Some targets don't support gc-sections despite whatever's 1572 # advertised by ld's options. 1573 if { [istarget arc-*-*] 1574 || [istarget d30v-*-*] 1575 || [istarget dlx-*-*] 1576 || [istarget i960-*-*] 1577 || [istarget pj*-*-*] 1578 || [istarget alpha-*-*] 1579 || [istarget hppa*64-*-*] 1580 || [istarget i370-*-*] 1581 || [istarget i860-*-*] 1582 || [istarget ia64-*-*] 1583 || [istarget mep-*-*] 1584 || [istarget mn10200-*-*] 1585 || [istarget *-*-cygwin] 1586 || [istarget *-*-mingw*] } { 1587 set gc_sections_available_saved 0 1588 return 0 1589 } 1590 1591 # elf2flt uses -q (--emit-relocs), which is incompatible with 1592 # --gc-sections. 1593 if { [board_info target exists ldflags] 1594 && [regexp " -elf2flt\[ =\]" " [board_info target ldflags] "] } { 1595 set gc_sections_available_saved 0 1596 return 0 1597 } 1598 1599 # Check if the ld used by gcc supports --gc-sections. 1600 # FIXME: this test is useless since ld --help always says 1601 # --gc-sections is available 1602 set ld_output [remote_exec host $ld "--help"] 1603 if { [ string first "--gc-sections" $ld_output ] >= 0 } { 1604 set gc_sections_available_saved 1 1605 } else { 1606 set gc_sections_available_saved 0 1607 } 1608 } 1609 return $gc_sections_available_saved 1610} 1611 1612# Returns true if -shared is supported on the target 1613# Only used and accurate for ELF targets at the moment 1614 1615proc check_shared_lib_support { } { 1616 if {![istarget aarch64*-*-elf] 1617 && ![istarget arc-*-*] 1618 && ![istarget arm*-*-elf] 1619 && ![istarget avr-*-*] 1620 && ![istarget cr16-*-*] 1621 && ![istarget cris*-*-elf] 1622 && ![istarget crx-*-*] 1623 && ![istarget d10v-*-*] 1624 && ![istarget d30v-*-*] 1625 && ![istarget dlx-*-*] 1626 && ![istarget epiphany-*-*] 1627 && ![istarget fr30-*-*] 1628 && ![istarget frv-*-*] 1629 && ![istarget h8300-*-*] 1630 && ![istarget i860-*-*] 1631 && ![istarget i960-*-*] 1632 && ![istarget ip2k-*-*] 1633 && ![istarget iq2000-*-*] 1634 && ![istarget lm32-*-*] 1635 && ![istarget m32c-*-*] 1636 && ![istarget m32r-*-*] 1637 && ![istarget m6811-*-*] 1638 && ![istarget m6812-*-*] 1639 && ![istarget m68hc1*-*-*] 1640 && ![istarget mcore*-*-*] 1641 && ![istarget mep-*-*] 1642 && ![istarget microblaze-*-*] 1643 && ![istarget mips*-*-elf] 1644 && ![istarget mn10200-*-*] 1645 && ![istarget moxie-*-*] 1646 && ![istarget msp430-*-*] 1647 && ![istarget mt-*-*] 1648 && ![istarget nds32*-*-*] 1649 && ![istarget or1k*-*-*] 1650 && ![istarget pj-*-*] 1651 && ![istarget rl78-*-*] 1652 && ![istarget rx-*-*] 1653 && ![istarget spu-*-*] 1654 && ![istarget v850*-*-*] 1655 && ![istarget xstormy16-*-*] 1656 && ![istarget *-*-irix*] 1657 && ![istarget *-*-rtems] } { 1658 return 1 1659 } 1660 return 0 1661} 1662 1663# Returns true if the target ld supports the plugin API. 1664proc check_plugin_api_available { } { 1665 global plugin_api_available_saved 1666 global ld 1667 if {![info exists plugin_api_available_saved]} { 1668 # Check if the ld used by gcc supports --plugin. 1669 set ld_output [remote_exec host $ld "--help"] 1670 if { [ string first "-plugin PLUGIN" $ld_output ] >= 0 } { 1671 set plugin_api_available_saved 1 1672 } else { 1673 set plugin_api_available_saved 0 1674 } 1675 } 1676 return $plugin_api_available_saved 1677} 1678 1679# Sets ld_sysroot to the current sysroot (empty if not supported) and 1680# returns true if the target ld supports sysroot. 1681proc check_sysroot_available { } { 1682 global ld_sysroot_available_saved ld ld_sysroot 1683 if {![info exists ld_sysroot_available_saved]} { 1684 # Check if ld supports --sysroot *other* than empty. 1685 set ld_sysroot [string trimright [lindex [remote_exec host $ld "--print-sysroot"] 1]] 1686 if { $ld_sysroot == "" } { 1687 set ld_sysroot_available_saved 0 1688 } else { 1689 set ld_sysroot_available_saved 1 1690 } 1691 } 1692 return $ld_sysroot_available_saved 1693} 1694 1695# Returns true if the target compiler supports LTO 1696proc check_lto_available { } { 1697 global lto_available_saved 1698 global CC 1699 1700 if {![info exists lto_available_saved]} { 1701 if { [which $CC] == 0 } { 1702 set lto_available_saved 0 1703 return 0 1704 } 1705 # Check if gcc supports -flto -fuse-linker-plugin 1706 set flags "" 1707 if [board_info [target_info name] exists cflags] { 1708 append flags " [board_info [target_info name] cflags]" 1709 } 1710 if [board_info [target_info name] exists ldflags] { 1711 append flags " [board_info [target_info name] ldflags]" 1712 } 1713 1714 set basename "tmpdir/lto[pid]" 1715 set src ${basename}.c 1716 set output ${basename}.out 1717 set f [open $src "w"] 1718 puts $f "int main() { return 0; }" 1719 close $f 1720 remote_download host $src 1721 set lto_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -fuse-linker-plugin $src -o $output"] 1722 remote_file host delete $src 1723 remote_file host delete $output 1724 file delete $src 1725 } 1726 return $lto_available_saved 1727} 1728 1729# Returns true if the target compiler supports LTO -ffat-lto-objects 1730proc check_lto_fat_available { } { 1731 global lto_fat_available_saved 1732 global CC 1733 1734 if {![info exists lto_fat_available_saved]} { 1735 if { [which $CC] == 0 } { 1736 set lto_fat_available_saved 0 1737 return 0 1738 } 1739 # Check if gcc supports -flto -fuse-linker-plugin 1740 set flags "" 1741 if [board_info [target_info name] exists cflags] { 1742 append flags " [board_info [target_info name] cflags]" 1743 } 1744 if [board_info [target_info name] exists ldflags] { 1745 append flags " [board_info [target_info name] ldflags]" 1746 } 1747 1748 set basename "tmpdir/lto[pid]" 1749 set src ${basename}.c 1750 set output ${basename}.out 1751 set f [open $src "w"] 1752 puts $f "int main() { return 0; }" 1753 close $f 1754 remote_download host $src 1755 set lto_fat_available_saved [run_host_cmd_yesno "$CC" "$flags -flto -ffat-lto-objects -fuse-linker-plugin $src -o $output"] 1756 remote_file host delete $src 1757 remote_file host delete $output 1758 file delete $src 1759 } 1760 return $lto_fat_available_saved 1761} 1762 1763# Returns true if the target compiler supports LTO and -shared 1764proc check_lto_shared_available { } { 1765 global lto_shared_available_saved 1766 global CC 1767 1768 if {![info exists lto_shared_available_saved]} { 1769 if { [which $CC] == 0 } { 1770 set lto_shared_available_saved 0 1771 return 0 1772 } 1773 # Check if gcc supports -flto -fuse-linker-plugin -shared 1774 set flags "" 1775 if [board_info [target_info name] exists cflags] { 1776 append flags " [board_info [target_info name] cflags]" 1777 } 1778 if [board_info [target_info name] exists ldflags] { 1779 append flags " [board_info [target_info name] ldflags]" 1780 } 1781 1782 set basename "tmpdir/lto_shared[pid]" 1783 set src ${basename}.c 1784 set output ${basename}.so 1785 set f [open $src "w"] 1786 puts $f "" 1787 close $f 1788 remote_download host $src 1789 set lto_shared_available_saved [run_host_cmd_yesno "$CC" "$flags -shared -fPIC -flto -fuse-linker-plugin $src -o $output"] 1790 remote_file host delete $src 1791 remote_file host delete $output 1792 file delete $src 1793 } 1794 return $lto_shared_available_saved 1795} 1796 1797# Check if the assembler supports CFI statements. 1798 1799proc check_as_cfi { } { 1800 global check_as_cfi_result 1801 global as 1802 if [info exists check_as_cfi_result] { 1803 return $check_as_cfi_result 1804 } 1805 set as_file "tmpdir/check_as_cfi.s" 1806 set as_fh [open $as_file w 0666] 1807 puts $as_fh "# Generated file. DO NOT EDIT" 1808 puts $as_fh "\t.cfi_startproc" 1809 puts $as_fh "\t.cfi_endproc" 1810 close $as_fh 1811 remote_download host $as_file 1812 verbose -log "Checking CFI support:" 1813 rename "perror" "check_as_cfi_perror" 1814 proc perror { args } { } 1815 set success [ld_assemble $as $as_file "/dev/null"] 1816 rename "perror" "" 1817 rename "check_as_cfi_perror" "perror" 1818 #remote_file host delete $as_file 1819 set check_as_cfi_result $success 1820 return $success 1821} 1822 1823# Provide virtual target "cfi" for targets supporting CFI. 1824 1825rename "istarget" "istarget_ld" 1826proc istarget { target } { 1827 if {$target == "cfi"} { 1828 return [check_as_cfi] 1829 } 1830 return [istarget_ld $target] 1831} 1832