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